-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
9P and/or virtio-fs support #26
Comments
I will try them later. |
Even the user-mode SMB-support might be interesting to use for sharing files from the host to the VM. |
You can easily provide cur_dir = __dir__
config.vm.synced_folder '.', '/vagrant', disabled: true
qe.extra_qemu_args= "-fsdev local,id=vagrant_dev,path=#{cur_dir},security_model=mapped-xattr
-device virtio-9p-pci,fsdev=vagrant_dev,mount_tag=vagrant_mount".split You do need to write the logic to mount the volumes though. |
Here's how I sorted this out This config will create the following mounts within the vm
cur_dir = __dir__
fstab_add_script = File.join(cur_dir, 'fstab_add.py')
# directory on host system
salt_dir = '/somedir/srv/salt'
# mount point within vm
salt_mount = '/srv/salt'
qe.extra_qemu_args= "-fsdev local,id=vagrant_dev,path=#{cur_dir},security_model=mapped-xattr
-device virtio-9p-pci,fsdev=vagrant_dev,mount_tag=vagrant_mount
-fsdev local,id=salt_dev,path=#{salt_dir},security_model=mapped-xattr
-device virtio-9p-pci,fsdev=salt_dev,mount_tag=salt_mount".split
config.vm.synced_folder cur_dir, '/vagrant', disabled: true
config.vm.provision 'shell', path: fstab_add_script, args: ['vagrant_mount', '/vagrant']
config.vm.provision 'shell', path: fstab_add_script, args: ['salt_mount', salt_mount] The parser.add_argument('device')
parser.add_argument('mountpoint')
parser.add_argument('fstype', nargs='?', default='9p')
parser.add_argument('options', nargs='?', default='version=9p2000.L,posixacl,msize=104857600,cache=none')
parser.add_argument('dump', nargs='?', default='0')
parser.add_argument('passno', nargs='?', default='0') Also |
Here are the contents of the #!/usr/bin/python3
from typing import (
NamedTuple, List
)
import argparse
import logging
import os
import subprocess
import sys
etc_fstab = '/etc/fstab'
log = logging.getLogger(__name__)
fstab_entry_type = NamedTuple(
'fstab_entry_type', [
('fstype', str),
('mountpoint', str),
('device_spec', str),
('device_path', str),
('options', str),
('dump', str),
('fs_passno', str)
]
)
class Fstab:
"""
**Managing fstab values**
"""
def __init__(self):
self.fstab = []
def read(self, filename: str) -> None:
"""
Import specified fstab file
Read the given fstab file and initialize a new entry list
:param string filename: path to a fstab file
"""
self.fstab = []
with open(filename) as fstab:
for line in fstab.readlines():
fstab_entry = line.split()
self.add_entry(fstab_entry)
def add_entry(self, fstab_entry: list, add_new_entry=False):
new_entry = self._parse_entry(fstab_entry, add_new_entry=add_new_entry)
if new_entry:
for entry in self.fstab:
if entry.mountpoint == new_entry.mountpoint:
log.warning(
'Mountpoint for "{0}" in use by "{1}", skipped'.format(
self._file_entry(new_entry),
self._file_entry(entry)
)
)
return
self.fstab.append(new_entry)
if add_new_entry:
mountpoint_new = fstab_entry[1]
return mountpoint_new
def get_devices(self) -> List[fstab_entry_type]:
return self.fstab
def export(self, filename: str) -> None:
"""
Export entries
:param string filename: path to file name
"""
with open(filename, 'w') as fstab:
for entry in self.fstab:
fstab.write(
self._file_entry(entry) + os.linesep
)
def export_pretty(self, filename: str) -> None:
fstab_contents = []
output = []
for entry in self.fstab:
row = [entry.device_spec, entry.mountpoint, entry.fstype, entry.options, entry.dump, entry.fs_passno, '\n']
fstab_contents.append(row)
col_width = [max(map(len, col)) for col in zip(*fstab_contents)]
formatted_output = []
for row in fstab_contents:
formatted_output.append(" ".join((val.ljust(width) for val, width in zip(row, col_width))))
with open(filename, 'w') as fstab:
fstab.write((''.join(formatted_output)))
def _file_entry(self, entry):
return '{0} {1} {2} {3} {4} {5}'.format(
entry.device_spec, entry.mountpoint,
entry.fstype, entry.options, entry.dump,
entry.fs_passno
)
def _parse_entry(self, data_record, add_new_entry=False):
data_length = len(data_record)
if data_record and data_length >= 2 \
and not data_record[0].startswith('#'):
device = data_record[0]
mountpoint = data_record[1]
fstype = data_record[2]
options = data_record[3]
dump = data_record[4]
fs_passno = data_record[5]
if device.startswith('UUID'):
device_path = ''.join(
['/dev/disk/by-uuid/', device.split('=')[1]]
)
elif device.startswith('LABEL'):
device_path = ''.join(
['/dev/disk/by-label/', device.split('=')[1]]
)
elif device.startswith('PARTUUID'):
device_path = ''.join(
['/dev/disk/by-partuuid/', device.split('=')[1]]
)
else:
device_path = device
return fstab_entry_type(
fstype=fstype,
mountpoint=mountpoint,
device_path=device_path,
device_spec=device,
options=options,
dump=dump,
fs_passno=fs_passno
)
def create_dir(dir_path):
if not os.path.isdir(dir_path):
try:
os.makedirs(dir_path)
return True
except Exception as e:
log.error(f'Failed to create directory: {dir_path}\n{e}')
sys.exit(1)
def mount(mountpoint):
cmd_str = f'mount {mountpoint}'
cmd = cmd_str.split()
cmd_output = subprocess.run(cmd, universal_newlines=True)
if cmd_output.returncode != 0:
log.error(f'Error mounting {mountpoint}')
sys.exit(2)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('device')
parser.add_argument('mountpoint')
parser.add_argument('fstype', nargs='?', default='9p')
parser.add_argument('options', nargs='?', default='version=9p2000.L,posixacl,msize=104857600,cache=none')
parser.add_argument('dump', nargs='?', default='0')
parser.add_argument('passno', nargs='?', default='0')
args = parser.parse_args()
fstab_entry = [args.device, args.mountpoint, args.fstype, args.options, args.dump, args.passno]
fstab = Fstab()
fstab.read(etc_fstab)
mountpoint_new = fstab.add_entry(fstab_entry, add_new_entry=True)
if mountpoint_new:
fstab.export_pretty(etc_fstab)
create_dir(mountpoint_new)
mount(mountpoint_new) |
@leifliddy The problem comes here when you need something from that mounted folder later.
Probably an experimental feature should be used: https://developer.hashicorp.com/vagrant/docs/provisioning/basic_usage#dependency-provisioners |
@zentavr It should create def create_dir(dir_path):
if not os.path.isdir(dir_path):
try:
os.makedirs(dir_path)
return True
except Exception as e:
log.error(f'Failed to create directory: {dir_path}\n{e}')
sys.exit(1)
.....
if mountpoint_new:
fstab.export_pretty(etc_fstab)
create_dir(mountpoint_new)
mount(mountpoint_new) |
@leifliddy I'd done
My whole Vagrantfile: # -*- mode: ruby -*-
# vi: set ft=ruby :
require 'getoptlong'
$vm_mem = '5120'
$vm_cpus = '2'
$vm_gui = false
$vb_box = 'ubuntu/jammy64'
$qe_box = 'generic/ubuntu2204'
$docker_box = 'ubuntu:jammy'
$vm_name = 'resecs-livecd'
#qemuSharedDir='/opt/homebrew/share/qemu'
qemuSharedDir=''
# https://stackoverflow.com/a/35777091/315044
# https://ruby-doc.org/stdlib-2.1.0/libdoc/getoptlong/rdoc/GetoptLong.html
opts = GetoptLong.new(
[ '--qemu-shared-dir', '-S', GetoptLong::REQUIRED_ARGUMENT ], # With required parameter.
)
opts.ordering=(GetoptLong::REQUIRE_ORDER)
opts.each do |opt, arg|
case opt
when '--qemu-shared-dir'
puts '--qemu-shared-dir accepted. Setting up QEMU shared dir.'
qemuSharedDir=arg
end
end
$script = <<-'SCRIPT'
#!/usr/bin/env bash
sudo rm -rf /usr/bin/python
sudo ln -s /usr/bin/python3 /usr/bin/python
sudo /usr/bin/python -V
echo "Installing python3-distutils"
sudo apt-get install -y python3-distutils
echo "Downloading pip"
curl -s https://bootstrap.pypa.io/get-pip.py | sudo python
echo "Done."
SCRIPT
Vagrant.configure("2") do |config|
config.vm.box = $vb_box
config.vm.hostname = $vm_name
config.vm.provision "fstab_vagrant_share", type: "shell",
preserve_order: true,
path: "dummy.sh"
config.vm.provider 'qemu' do |qe, override|
override.vm.box = $qe_box
qe.arch = "x86_64"
qe.machine = "q35"
qe.net_device = "virtio-net-pci"
qe.memory = $vm_mem
qe.cpu = "Skylake-Server,+aes"
qe.smp = "cpus=#{$vm_cpus},sockets=1,cores=#{$vm_cpus},threads=1"
qe.no_daemonize = $vm_gui
qe.qemu_dir = qemuSharedDir
#qe.extra_qemu_args = %w(-accel hvf)
# Inspired by: https://github.com/ppggff/vagrant-qemu/issues/26
cur_dir = __dir__
fstab_add_script = File.join(cur_dir, 'fstab_add.py')
# Map host directory to /opt/build
config.vm.synced_folder cur_dir, '/opt/build', disabled: true
qe.extra_qemu_args= "-fsdev local,id=virtfs0,path=#{cur_dir},security_model=mapped-xattr
-device virtio-9p-pci,fsdev=virtfs0,mount_tag=vagrant_share".split
# Invoke mount (use "mount_tag" value here)
override.vm.provision "fstab_vagrant_share", type: "shell",
name: "fstab__vagrant_share",
path: fstab_add_script,
args: ["vagrant_share", '/opt/build']
end
config.vm.provider 'virtualbox' do |vb|
vb.memory = $vm_mem
vb.cpus = $vm_cpus
vb.gui = $vm_gui
vb.name = $vm_name
# Map host directory to /opt/build
#config.vm.synced_folder '.', '/opt/build', create: true, type: 'virtualbox', disabled: true
config.vm.synced_folder '.', '/opt/build', create: true, type: 'virtualbox'
end
config.vm.provider "docker" do |d|
d.image = $docker_box
d.has_ssh = true
d.volumes = [
"./:/opt/build,rw"
]
end
config.vm.provision "shell", name: 'python__install', inline: $script
#
# Run Ansible from the Vagrant VM
#
config.vm.provision "create_image", type: "ansible_local", after: "fstab_vagrant_share", run: "always" do |ansible|
ansible.provisioning_path = "/opt/build"
ansible.playbook = "playbook.yml"
#ansible.tags = ""
#ansible.skip_tags = ""
ansible.verbose = "-vv"
ansible.install = true
ansible.install_mode = "pip"
ansible.pip_install_cmd = "curl -s https://bootstrap.pypa.io/get-pip.py | sudo python"
ansible.version = "2.9.27"
# Drive type could be "mbr" or "gpt"
ansible.extra_vars = {
image_path: "/opt/build/livecd",
drive_type: "hybrid",
burn_iso: true,
burn_img: false
}
end
end Output:
How you can see, it works only because of these experimental workarounds. The doc says:
Seems like in my scenario it will work only with the hacks I'd put (and probably I'd broken Virtualbox emulator here). |
I'd love to see support for either https://wiki.qemu.org/Documentation/9psetup or https://virtio-fs.gitlab.io/
Virtio-fs is a bit more modern than 9p but is a tiny bit more complex due to it using a external daemon for it's fs operations rather than having qemu doing that bit directly.
The text was updated successfully, but these errors were encountered: