switch to spice for graphical vms

This commit is contained in:
Jörg Thalheim
2023-11-23 13:22:59 +01:00
parent 4f18c48892
commit 93ab408827

View File

@@ -14,13 +14,82 @@ from ..task_manager import BaseTask, Command, create_task
from .inspect import VmConfig, inspect_vm from .inspect import VmConfig, inspect_vm
def qemu_command(
vm: VmConfig,
nixos_config: dict[str, str],
xchg_dir: Path,
secrets_dir: Path,
disk_img: Path,
) -> list[str]:
kernel_cmdline = [
(Path(nixos_config["toplevel"]) / "kernel-params").read_text(),
f'init={nixos_config["toplevel"]}/init',
f'regInfo={nixos_config["regInfo"]}/registration',
"console=ttyS0,115200n8",
"console=tty0",
]
# fmt: off
command = [
"qemu-kvm",
"-name", vm.flake_attr,
"-m", f'{nixos_config["memorySize"]}M',
"-smp", str(nixos_config["cores"]),
"-cpu", "max",
"-device", "virtio-rng-pci",
"-net", "nic,netdev=user.0,model=virtio",
"-netdev", "user,id=user.0",
"-virtfs", "local,path=/nix/store,security_model=none,mount_tag=nix-store",
"-virtfs", f"local,path={xchg_dir},security_model=none,mount_tag=shared",
"-virtfs", f"local,path={xchg_dir},security_model=none,mount_tag=xchg",
"-virtfs", f"local,path={secrets_dir},security_model=none,mount_tag=secrets",
"-drive", f"cache=writeback,file={disk_img},format=raw,id=drive1,if=none,index=1,werror=report",
"-device", "virtio-blk-pci,bootindex=1,drive=drive1,serial=root",
"-device", "virtio-keyboard",
# TODO: we also need to fixup timezone than...
# "-rtc", "base=localtime,clock=host,driftfix=slew",
"-vga", "virtio",
"-usb", "-device", "usb-tablet,bus=usb-bus.0",
"-kernel", f'{nixos_config["toplevel"]}/kernel',
"-initrd", nixos_config["initrd"],
"-append", " ".join(kernel_cmdline),
] # fmt: on
if vm.graphics:
# fmt: off
command.extend(
[
"-audiodev", "spice,id=audio0",
"-device", "intel-hda",
"-device", "hda-duplex,audiodev=audio0",
"-device", "virtio-serial-pci",
"-chardev", "spicevmc,id=vdagent0,name=vdagent",
"-device", "virtserialport,chardev=vdagent0,name=com.redhat.spice.0",
"-spice", "disable-ticketing=on,port=5930,addr=127.0.0.1",
"-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:
command.append("-nographic")
return command
class BuildVmTask(BaseTask): class BuildVmTask(BaseTask):
def __init__(self, uuid: UUID, vm: VmConfig, nix_options: list[str] = []) -> None: def __init__(self, uuid: UUID, vm: VmConfig, nix_options: list[str] = []) -> None:
super().__init__(uuid, num_cmds=7) super().__init__(uuid, num_cmds=7)
self.vm = vm self.vm = vm
self.nix_options = nix_options self.nix_options = nix_options
def get_vm_create_info(self, cmds: Iterator[Command]) -> dict: def get_vm_create_info(self, cmds: Iterator[Command]) -> dict[str, str]:
config = nix_config() config = nix_config()
system = config["system"] system = config["system"]
@@ -58,7 +127,7 @@ class BuildVmTask(BaseTask):
self.log.debug(f"Creating VM for {machine}") self.log.debug(f"Creating VM for {machine}")
# TODO: We should get this from the vm argument # TODO: We should get this from the vm argument
vm_config = self.get_vm_create_info(cmds) nixos_config = self.get_vm_create_info(cmds)
clan_name = self.get_clan_name(cmds) clan_name = self.get_clan_name(cmds)
self.log.debug(f"Building VM for clan name: {clan_name}") self.log.debug(f"Building VM for clan name: {clan_name}")
@@ -87,7 +156,7 @@ class BuildVmTask(BaseTask):
cmd = next(cmds) cmd = next(cmds)
if Path(self.vm.flake_url).is_dir(): if Path(self.vm.flake_url).is_dir():
cmd.run( cmd.run(
[vm_config["generateSecrets"], clan_name], [nixos_config["generateSecrets"], clan_name],
env=env, env=env,
name="generateSecrets", name="generateSecrets",
) )
@@ -96,7 +165,7 @@ class BuildVmTask(BaseTask):
cmd = next(cmds) cmd = next(cmds)
cmd.run( cmd.run(
[vm_config["uploadSecrets"]], [nixos_config["uploadSecrets"]],
env=env, env=env,
name="uploadSecrets", name="uploadSecrets",
) )
@@ -132,65 +201,20 @@ class BuildVmTask(BaseTask):
) )
cmd = next(cmds) cmd = next(cmds)
cmdline = [
(Path(vm_config["toplevel"]) / "kernel-params").read_text(), qemu_cmd = qemu_command(
f'init={vm_config["toplevel"]}/init', self.vm,
f'regInfo={vm_config["regInfo"]}/registration', nixos_config,
"console=ttyS0,115200n8", xchg_dir=xchg_dir,
"console=tty0", secrets_dir=secrets_dir,
] disk_img=disk_img,
qemu_command = [ )
"qemu-kvm", print(
"-name", "nix shell nixpkgs#spice-gtk -c spicy --port 5930 --spice-shared-dir $HOME"
machine, )
"-m",
f'{vm_config["memorySize"]}M', print("$ " + shlex.join(qemu_cmd))
"-smp", cmd.run(nix_shell(["qemu"], qemu_cmd), name="qemu")
str(vm_config["cores"]),
"-cpu",
"max",
"-device",
"virtio-rng-pci",
"-net",
"nic,netdev=user.0,model=virtio",
"-netdev",
"user,id=user.0",
"-virtfs",
"local,path=/nix/store,security_model=none,mount_tag=nix-store",
"-virtfs",
f"local,path={xchg_dir},security_model=none,mount_tag=shared",
"-virtfs",
f"local,path={xchg_dir},security_model=none,mount_tag=xchg",
"-virtfs",
f"local,path={secrets_dir},security_model=none,mount_tag=secrets",
"-drive",
f"cache=writeback,file={disk_img},format=raw,id=drive1,if=none,index=1,werror=report",
"-device",
"virtio-blk-pci,bootindex=1,drive=drive1,serial=root",
"-device",
"virtio-keyboard",
# TODO: audio card
# "-audiodev", "spice,id=audio0",
# "-device", "intel-hda",
# "-device", "hda-duplex,audiodev=audio0",
# TODO: we also need to fixup timezone than...
# "-rtc", "base=localtime,clock=host,driftfix=slew",
"-vga",
"virtio",
"-usb",
"-device",
"usb-tablet,bus=usb-bus.0",
"-kernel",
f'{vm_config["toplevel"]}/kernel',
"-initrd",
vm_config["initrd"],
"-append",
" ".join(cmdline),
]
if not self.vm.graphics:
qemu_command.append("-nographic")
print("$ " + shlex.join(qemu_command))
cmd.run(nix_shell(["qemu"], qemu_command), name="qemu")
def create_vm(vm: VmConfig, nix_options: list[str] = []) -> BuildVmTask: def create_vm(vm: VmConfig, nix_options: list[str] = []) -> BuildVmTask: