vms: support secrets and fix cross compilation

This commit is contained in:
lassulus
2023-10-04 18:01:50 +02:00
parent fc50b1786b
commit 9457a0f4b9
4 changed files with 47 additions and 8 deletions

View File

@@ -3,6 +3,14 @@ let
vmConfig = extendModules { vmConfig = extendModules {
modules = [ modules = [
(modulesPath + "/virtualisation/qemu-vm.nix") (modulesPath + "/virtualisation/qemu-vm.nix")
{
virtualisation.fileSystems.${config.clanCore.secretsUploadDirectory} = lib.mkForce {
device = "secrets";
fsType = "9p";
neededForBoot = true;
options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
};
}
]; ];
}; };
in in
@@ -52,6 +60,8 @@ in
toplevel = vmConfig.config.system.build.toplevel; toplevel = vmConfig.config.system.build.toplevel;
regInfo = (pkgs.closureInfo { rootPaths = vmConfig.config.virtualisation.additionalPaths; }); regInfo = (pkgs.closureInfo { rootPaths = vmConfig.config.virtualisation.additionalPaths; });
inherit (config.clan.virtualisation) memorySize cores graphics; inherit (config.clan.virtualisation) memorySize cores graphics;
generateSecrets = config.system.clan.generateSecrets;
uploadSecrets = config.system.clan.uploadSecrets;
}); });
}; };

View File

@@ -8,7 +8,7 @@ import sys
import threading import threading
import traceback import traceback
from enum import Enum from enum import Enum
from typing import Any, Iterator, Type, TypeVar from typing import Any, Iterator, Optional, Type, TypeVar
from uuid import UUID, uuid4 from uuid import UUID, uuid4
from .errors import ClanError from .errors import ClanError
@@ -30,7 +30,7 @@ class Command:
self._output.put(None) self._output.put(None)
self.done = True self.done = True
def run(self, cmd: list[str]) -> None: def run(self, cmd: list[str], env: Optional[dict[str, str]] = None) -> None:
self.running = True self.running = True
self.log.debug(f"Running command: {shlex.join(cmd)}") self.log.debug(f"Running command: {shlex.join(cmd)}")
self.p = subprocess.Popen( self.p = subprocess.Popen(
@@ -38,6 +38,7 @@ class Command:
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
encoding="utf-8", encoding="utf-8",
env=env,
) )
assert self.p.stdout is not None and self.p.stderr is not None assert self.p.stdout is not None and self.p.stderr is not None
os.set_blocking(self.p.stdout.fileno(), False) os.set_blocking(self.p.stdout.fileno(), False)

View File

@@ -1,32 +1,36 @@
import argparse import argparse
import asyncio import asyncio
import json import json
import os
import shlex import shlex
import sys
import tempfile import tempfile
from pathlib import Path from pathlib import Path
from typing import Iterator from typing import Iterator
from uuid import UUID from uuid import UUID
from ..dirs import get_clan_flake_toplevel from ..dirs import get_clan_flake_toplevel
from ..nix import nix_build, nix_shell from ..nix import nix_build, nix_config, nix_shell
from ..task_manager import BaseTask, Command, create_task from ..task_manager import BaseTask, Command, create_task
from .inspect import VmConfig, inspect_vm from .inspect import VmConfig, inspect_vm
class BuildVmTask(BaseTask): class BuildVmTask(BaseTask):
def __init__(self, uuid: UUID, vm: VmConfig) -> None: def __init__(self, uuid: UUID, vm: VmConfig) -> None:
super().__init__(uuid, num_cmds=4) super().__init__(uuid, num_cmds=6)
self.vm = vm self.vm = vm
def get_vm_create_info(self, cmds: Iterator[Command]) -> dict: def get_vm_create_info(self, cmds: Iterator[Command]) -> dict:
config = nix_config()
system = config["system"]
clan_dir = self.vm.flake_url clan_dir = self.vm.flake_url
machine = self.vm.flake_attr machine = self.vm.flake_attr
cmd = next(cmds) cmd = next(cmds)
cmd.run( cmd.run(
nix_build( nix_build(
[ [
# f'{clan_dir}#clanInternals.machines."{system}"."{machine}".config.clan.virtualisation.createJSON' # TODO use this f'{clan_dir}#clanInternals.machines."{system}"."{machine}".config.system.clan.vm.create'
f'{clan_dir}#nixosConfigurations."{machine}".config.system.clan.vm.create'
] ]
) )
) )
@@ -48,8 +52,29 @@ class BuildVmTask(BaseTask):
tmpdir = Path(tmpdir_) tmpdir = Path(tmpdir_)
xchg_dir = tmpdir / "xchg" xchg_dir = tmpdir / "xchg"
xchg_dir.mkdir() xchg_dir.mkdir()
secrets_dir = tmpdir / "secrets"
secrets_dir.mkdir()
disk_img = f"{tmpdir_}/disk.img" disk_img = f"{tmpdir_}/disk.img"
env = os.environ.copy()
env["CLAN_DIR"] = str(self.vm.flake_url)
env["PYTHONPATH"] = str(
":".join(sys.path)
) # TODO do this in the clanCore module
env["SECRETS_DIR"] = str(secrets_dir)
cmd = next(cmds)
cmd.run(
[vm_config["generateSecrets"]],
env=env,
)
cmd = next(cmds)
cmd.run(
[vm_config["uploadSecrets"]],
env=env,
)
cmd = next(cmds) cmd = next(cmds)
cmd.run( cmd.run(
nix_shell( nix_shell(
@@ -97,6 +122,7 @@ class BuildVmTask(BaseTask):
"-virtfs", "local,path=/nix/store,security_model=none,mount_tag=nix-store", "-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=shared",
"-virtfs", f"local,path={xchg_dir},security_model=none,mount_tag=xchg", "-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', "-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-blk-pci,bootindex=1,drive=drive1,serial=root",
"-device", "virtio-keyboard", "-device", "virtio-keyboard",

View File

@@ -6,7 +6,7 @@ from pydantic import BaseModel
from ..async_cmd import run from ..async_cmd import run
from ..dirs import get_clan_flake_toplevel from ..dirs import get_clan_flake_toplevel
from ..nix import nix_eval from ..nix import nix_config, nix_eval
class VmConfig(BaseModel): class VmConfig(BaseModel):
@@ -19,9 +19,11 @@ class VmConfig(BaseModel):
async def inspect_vm(flake_url: str, flake_attr: str) -> VmConfig: async def inspect_vm(flake_url: str, flake_attr: str) -> VmConfig:
config = nix_config()
system = config["system"]
cmd = nix_eval( cmd = nix_eval(
[ [
f"{flake_url}#nixosConfigurations.{json.dumps(flake_attr)}.config.system.clan.vm.config" f'{flake_url}#clanInternals.machines."{system}"."{flake_attr}".config.system.clan.vm.config'
] ]
) )
stdout = await run(cmd) stdout = await run(cmd)