vms/run: split large vm run method into smaller ones

This commit is contained in:
Jörg Thalheim
2023-12-08 14:34:49 +01:00
parent c4a8193047
commit f6d4c721c4

View File

@@ -18,13 +18,47 @@ from .inspect import VmConfig, inspect_vm
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def graphics_options(vm: VmConfig) -> list[str]:
if vm.wayland:
# fmt: off
return [
"-nographic",
"-vga", "none",
"-device", "virtio-gpu-rutabaga,gfxstream-vulkan=on,cross-domain=on,hostmem=4G,wsi=headless",
]
# fmt: on
else:
# fmt: off
return [
"-audiodev", "spice,id=audio0",
"-device", "intel-hda",
"-device", "hda-duplex,audiodev=audio0",
"-display", "gtk,gl=on",
"-device", "virtio-gpu-gl",
"-display", "spice-app,gl=on",
"-device", "virtio-serial-pci",
"-chardev", "spicevmc,id=vdagent0,name=vdagent",
"-device", "virtserialport,chardev=vdagent0,name=com.redhat.spice.0",
"-device", "qemu-xhci,id=spicepass",
"-chardev", "spicevmc,id=usbredirchardev1,name=usbredir",
"-device", "usb-redir,chardev=usbredirchardev1,id=usbredirdev1",
"-chardev", "spicevmc,id=usbredirchardev2,name=usbredir",
"-device", "usb-redir,chardev=usbredirchardev2,id=usbredirdev2",
"-chardev", "spicevmc,id=usbredirchardev3,name=usbredir",
"-device", "usb-redir,chardev=usbredirchardev3,id=usbredirdev3",
"-device", "pci-ohci,id=smartpass",
"-device", "usb-ccid",
"-chardev", "spicevmc,id=ccid,name=smartcard",
]
# fmt: on
def qemu_command( def qemu_command(
vm: VmConfig, vm: VmConfig,
nixos_config: dict[str, str], nixos_config: dict[str, str],
xchg_dir: Path, xchg_dir: Path,
secrets_dir: Path, secrets_dir: Path,
disk_img: Path, disk_img: Path,
spice_socket: Path,
) -> list[str]: ) -> list[str]:
kernel_cmdline = [ kernel_cmdline = [
(Path(nixos_config["toplevel"]) / "kernel-params").read_text(), (Path(nixos_config["toplevel"]) / "kernel-params").read_text(),
@@ -58,42 +92,7 @@ def qemu_command(
] # fmt: on ] # fmt: on
if vm.graphics: if vm.graphics:
if vm.wayland: command.extend(graphics_options(vm))
# fmt: off
command.extend(
[
"-audiodev", "spice,id=audio0",
"-device", "intel-hda",
"-device", "hda-duplex,audiodev=audio0",
"-display", "gtk,gl=on",
"-device", "virtio-gpu-gl",
"-display", "spice-app,gl=on",
"-device", "virtio-serial-pci",
"-chardev", "spicevmc,id=vdagent0,name=vdagent",
"-device", "virtserialport,chardev=vdagent0,name=com.redhat.spice.0",
"-device", "qemu-xhci,id=spicepass",
"-chardev", "spicevmc,id=usbredirchardev1,name=usbredir",
"-device", "usb-redir,chardev=usbredirchardev1,id=usbredirdev1",
"-chardev", "spicevmc,id=usbredirchardev2,name=usbredir",
"-device", "usb-redir,chardev=usbredirchardev2,id=usbredirdev2",
"-chardev", "spicevmc,id=usbredirchardev3,name=usbredir",
"-device", "usb-redir,chardev=usbredirchardev3,id=usbredirdev3",
"-device", "pci-ohci,id=smartpass",
"-device", "usb-ccid",
"-chardev", "spicevmc,id=ccid,name=smartcard",
]
)
# fmt: on
else:
# fmt: off
command.extend(
[
"-nographic",
"-vga", "none",
"-device", "virtio-gpu-rutabaga,gfxstream-vulkan=on,cross-domain=on,hostmem=4G,wsi=headless",
]
)
# fmt: on
else: else:
command.append("-nographic") command.append("-nographic")
return command return command
@@ -143,39 +142,20 @@ def get_clan_name(vm: VmConfig, nix_options: list[str]) -> str:
return proc.stdout.strip().strip('"') return proc.stdout.strip().strip('"')
def run_vm( def generate_secrets(
vm: VmConfig, nix_options: list[str] = [], log_fd: IO[str] | None = None vm: VmConfig,
) -> None: clan_name: str,
""" nixos_config: dict[str, str],
log_fd can be used to stream the output of all commands to a UI tmpdir: Path,
""" log_fd: IO[str] | None,
machine = vm.flake_attr ) -> Path:
log.debug(f"Creating VM for {machine}")
# TODO: We should get this from the vm argument
nixos_config = get_vm_create_info(vm, nix_options)
clan_name = get_clan_name(vm, nix_options)
log.debug(f"Building VM for clan name: {clan_name}")
flake_dir = Path(vm.flake_url)
flake_dir.mkdir(exist_ok=True)
with tempfile.TemporaryDirectory() as tmpdir_:
tmpdir = Path(tmpdir_)
xchg_dir = tmpdir / "xchg"
xchg_dir.mkdir(exist_ok=True)
secrets_dir = tmpdir / "secrets" secrets_dir = tmpdir / "secrets"
secrets_dir.mkdir(exist_ok=True) secrets_dir.mkdir(exist_ok=True)
disk_img = tmpdir / "disk.img"
spice_socket = tmpdir / "spice.sock"
env = os.environ.copy() env = os.environ.copy()
env["CLAN_DIR"] = str(vm.flake_url) env["CLAN_DIR"] = str(vm.flake_url)
env["PYTHONPATH"] = str( env["PYTHONPATH"] = str(":".join(sys.path)) # TODO do this in the clanCore module
":".join(sys.path)
) # TODO do this in the clanCore module
env["SECRETS_DIR"] = str(secrets_dir) env["SECRETS_DIR"] = str(secrets_dir)
# Only generate secrets for local clans # Only generate secrets for local clans
@@ -203,7 +183,11 @@ def run_vm(
raise ClanError( raise ClanError(
f"Failed to upload secrets: {shlex.join(cmd)} failed with {res.returncode}" f"Failed to upload secrets: {shlex.join(cmd)} failed with {res.returncode}"
) )
return secrets_dir
def prepare_disk(tmpdir: Path, log_fd: IO[str] | None) -> Path:
disk_img = tmpdir / "disk.img"
cmd = nix_shell( cmd = nix_shell(
["qemu"], ["qemu"],
[ [
@@ -245,6 +229,34 @@ def run_vm(
raise ClanError( raise ClanError(
f"Failed to create ext4 filesystem: {shlex.join(cmd)} failed with {res.returncode}" f"Failed to create ext4 filesystem: {shlex.join(cmd)} failed with {res.returncode}"
) )
return disk_img
def run_vm(
vm: VmConfig, nix_options: list[str] = [], log_fd: IO[str] | None = None
) -> None:
"""
log_fd can be used to stream the output of all commands to a UI
"""
machine = vm.flake_attr
log.debug(f"Creating VM for {machine}")
# TODO: We should get this from the vm argument
nixos_config = get_vm_create_info(vm, nix_options)
clan_name = get_clan_name(vm, nix_options)
log.debug(f"Building VM for clan name: {clan_name}")
flake_dir = Path(vm.flake_url)
flake_dir.mkdir(exist_ok=True)
with tempfile.TemporaryDirectory() as tmpdir_:
tmpdir = Path(tmpdir_)
xchg_dir = tmpdir / "xchg"
xchg_dir.mkdir(exist_ok=True)
secrets_dir = generate_secrets(vm, clan_name, nixos_config, tmpdir, log_fd)
disk_img = prepare_disk(tmpdir, log_fd)
qemu_cmd = qemu_command( qemu_cmd = qemu_command(
vm, vm,
@@ -252,7 +264,6 @@ def run_vm(
xchg_dir=xchg_dir, xchg_dir=xchg_dir,
secrets_dir=secrets_dir, secrets_dir=secrets_dir,
disk_img=disk_img, disk_img=disk_img,
spice_socket=spice_socket,
) )
if vm.wayland: if vm.wayland: