Merge pull request #290730 from nikstur/qemu-vm-refactoring
qemu-vm.nix refactoring
This commit is contained in:
commit
a62c421981
@ -393,7 +393,7 @@ in
|
||||
The path (inside the VM) to the device containing the EFI System Partition (ESP).
|
||||
|
||||
If you are *not* booting from a UEFI firmware, this value is, by
|
||||
default, `null`. The ESP is mounted under `/boot`.
|
||||
default, `null`. The ESP is mounted to `boot.loader.efi.efiSysMountpoint`.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -1054,38 +1054,6 @@ in
|
||||
|
||||
boot.loader.supportsInitrdSecrets = mkIf (!cfg.useBootLoader) (mkVMOverride false);
|
||||
|
||||
boot.initrd.postMountCommands = lib.mkIf (!config.boot.initrd.systemd.enable)
|
||||
''
|
||||
# Mark this as a NixOS machine.
|
||||
mkdir -p $targetRoot/etc
|
||||
echo -n > $targetRoot/etc/NIXOS
|
||||
|
||||
# Fix the permissions on /tmp.
|
||||
chmod 1777 $targetRoot/tmp
|
||||
|
||||
mkdir -p $targetRoot/boot
|
||||
|
||||
${optionalString cfg.writableStore ''
|
||||
echo "mounting overlay filesystem on /nix/store..."
|
||||
mkdir -p -m 0755 $targetRoot/nix/.rw-store/store $targetRoot/nix/.rw-store/work $targetRoot/nix/store
|
||||
mount -t overlay overlay $targetRoot/nix/store \
|
||||
-o lowerdir=$targetRoot/nix/.ro-store,upperdir=$targetRoot/nix/.rw-store/store,workdir=$targetRoot/nix/.rw-store/work || fail
|
||||
''}
|
||||
'';
|
||||
|
||||
systemd.tmpfiles.settings."10-qemu-vm" = lib.mkIf config.boot.initrd.systemd.enable {
|
||||
"/etc/NIXOS".f = {
|
||||
mode = "0644";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
"${config.boot.loader.efi.efiSysMountPoint}".d = {
|
||||
mode = "0644";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
|
||||
# After booting, register the closure of the paths in
|
||||
# `virtualisation.additionalPaths' in the Nix database in the VM. This
|
||||
# allows Nix operations to work in the VM. The path to the
|
||||
@ -1101,8 +1069,7 @@ in
|
||||
'';
|
||||
|
||||
boot.initrd.availableKernelModules =
|
||||
optional cfg.writableStore "overlay"
|
||||
++ optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx"
|
||||
optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx"
|
||||
++ optional (cfg.tpm.enable) "tpm_tis";
|
||||
|
||||
virtualisation.additionalPaths = [ config.system.build.toplevel ];
|
||||
@ -1110,7 +1077,9 @@ in
|
||||
virtualisation.sharedDirectories = {
|
||||
nix-store = mkIf cfg.mountHostNixStore {
|
||||
source = builtins.storeDir;
|
||||
target = "/nix/store";
|
||||
# Always mount this to /nix/.ro-store because we never want to actually
|
||||
# write to the host Nix Store.
|
||||
target = "/nix/.ro-store";
|
||||
securityModel = "none";
|
||||
};
|
||||
xchg = {
|
||||
@ -1220,10 +1189,7 @@ in
|
||||
virtualisation.fileSystems = let
|
||||
mkSharedDir = tag: share:
|
||||
{
|
||||
name =
|
||||
if tag == "nix-store" && cfg.writableStore
|
||||
then "/nix/.ro-store"
|
||||
else share.target;
|
||||
name = share.target;
|
||||
value.device = tag;
|
||||
value.fsType = "9p";
|
||||
value.neededForBoot = true;
|
||||
@ -1248,7 +1214,17 @@ in
|
||||
# Sync with systemd's tmp.mount;
|
||||
options = [ "mode=1777" "strictatime" "nosuid" "nodev" "size=${toString config.boot.tmp.tmpfsSize}" ];
|
||||
};
|
||||
"/nix/${if cfg.writableStore then ".ro-store" else "store"}" = lib.mkIf cfg.useNixStoreImage {
|
||||
"/nix/store" = lib.mkIf (cfg.useNixStoreImage || cfg.mountHostNixStore) (if cfg.writableStore then {
|
||||
overlay = {
|
||||
lowerdir = [ "/nix/.ro-store" ];
|
||||
upperdir = "/nix/.rw-store/upper";
|
||||
workdir = "/nix/.rw-store/work";
|
||||
};
|
||||
} else {
|
||||
device = "/nix/.ro-store";
|
||||
options = [ "bind" ];
|
||||
});
|
||||
"/nix/.ro-store" = lib.mkIf cfg.useNixStoreImage {
|
||||
device = "/dev/disk/by-label/${nixStoreFilesystemLabel}";
|
||||
neededForBoot = true;
|
||||
options = [ "ro" ];
|
||||
@ -1258,40 +1234,13 @@ in
|
||||
options = [ "mode=0755" ];
|
||||
neededForBoot = true;
|
||||
};
|
||||
"/boot" = lib.mkIf (cfg.useBootLoader && cfg.bootPartition != null) {
|
||||
"${config.boot.loader.efi.efiSysMountPoint}" = lib.mkIf (cfg.useBootLoader && cfg.bootPartition != null) {
|
||||
device = cfg.bootPartition;
|
||||
fsType = "vfat";
|
||||
noCheck = true; # fsck fails on a r/o filesystem
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
boot.initrd.systemd = lib.mkIf (config.boot.initrd.systemd.enable && cfg.writableStore) {
|
||||
mounts = [{
|
||||
where = "/sysroot/nix/store";
|
||||
what = "overlay";
|
||||
type = "overlay";
|
||||
options = "lowerdir=/sysroot/nix/.ro-store,upperdir=/sysroot/nix/.rw-store/store,workdir=/sysroot/nix/.rw-store/work";
|
||||
wantedBy = ["initrd-fs.target"];
|
||||
before = ["initrd-fs.target"];
|
||||
requires = ["rw-store.service"];
|
||||
after = ["rw-store.service"];
|
||||
unitConfig.RequiresMountsFor = "/sysroot/nix/.ro-store";
|
||||
}];
|
||||
services.rw-store = {
|
||||
before = [ "shutdown.target" ];
|
||||
conflicts = [ "shutdown.target" ];
|
||||
unitConfig = {
|
||||
DefaultDependencies = false;
|
||||
RequiresMountsFor = "/sysroot/nix/.rw-store";
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "/bin/mkdir -p -m 0755 /sysroot/nix/.rw-store/store /sysroot/nix/.rw-store/work /sysroot/nix/store";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
swapDevices = (if cfg.useDefaultFilesystems then mkVMOverride else mkDefault) [ ];
|
||||
boot.initrd.luks.devices = (if cfg.useDefaultFilesystems then mkVMOverride else mkDefault) {};
|
||||
|
||||
|
@ -804,6 +804,7 @@ in {
|
||||
qemu-vm-restrictnetwork = handleTest ./qemu-vm-restrictnetwork.nix {};
|
||||
qemu-vm-volatile-root = runTest ./qemu-vm-volatile-root.nix;
|
||||
qemu-vm-external-disk-image = runTest ./qemu-vm-external-disk-image.nix;
|
||||
qemu-vm-store = runTest ./qemu-vm-store.nix;
|
||||
qgis = handleTest ./qgis.nix { qgisPackage = pkgs.qgis; };
|
||||
qgis-ltr = handleTest ./qgis.nix { qgisPackage = pkgs.qgis-ltr; };
|
||||
qownnotes = handleTest ./qownnotes.nix {};
|
||||
|
71
nixos/tests/qemu-vm-store.nix
Normal file
71
nixos/tests/qemu-vm-store.nix
Normal file
@ -0,0 +1,71 @@
|
||||
{ lib, ... }: {
|
||||
|
||||
name = "qemu-vm-store";
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ nikstur ];
|
||||
|
||||
nodes = {
|
||||
sharedWritable = {
|
||||
virtualisation.writableStore = true;
|
||||
};
|
||||
|
||||
sharedReadOnly = {
|
||||
virtualisation.writableStore = false;
|
||||
};
|
||||
|
||||
imageWritable = {
|
||||
virtualisation.useNixStoreImage = true;
|
||||
virtualisation.writableStore = true;
|
||||
};
|
||||
|
||||
imageReadOnly = {
|
||||
virtualisation.useNixStoreImage = true;
|
||||
virtualisation.writableStore = false;
|
||||
};
|
||||
|
||||
fullDisk = {
|
||||
virtualisation.useBootLoader = true;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
build_derivation = """
|
||||
nix-build --option substitute false -E 'derivation {
|
||||
name = "t";
|
||||
builder = "/bin/sh";
|
||||
args = ["-c" "echo something > $out"];
|
||||
system = builtins.currentSystem;
|
||||
preferLocalBuild = true;
|
||||
}'
|
||||
"""
|
||||
|
||||
start_all()
|
||||
|
||||
with subtest("Nix Store is writable"):
|
||||
sharedWritable.succeed(build_derivation)
|
||||
imageWritable.succeed(build_derivation)
|
||||
fullDisk.succeed(build_derivation)
|
||||
|
||||
with subtest("Nix Store is read only"):
|
||||
sharedReadOnly.fail(build_derivation)
|
||||
imageReadOnly.fail(build_derivation)
|
||||
|
||||
# Checking whether the fs type is 9P is just a proxy to test whether the
|
||||
# Nix Store is shared. If we switch to a different technology (e.g.
|
||||
# virtiofs) for sharing, we need to adjust these tests.
|
||||
|
||||
with subtest("Nix store is shared from the host via 9P"):
|
||||
sharedWritable.succeed("findmnt --kernel --type 9P /nix/.ro-store")
|
||||
sharedReadOnly.succeed("findmnt --kernel --type 9P /nix/.ro-store")
|
||||
|
||||
with subtest("Nix store is not shared via 9P"):
|
||||
imageWritable.fail("findmnt --kernel --type 9P /nix/.ro-store")
|
||||
imageReadOnly.fail("findmnt --kernel --type 9P /nix/.ro-store")
|
||||
|
||||
with subtest("Nix store is not mounted separately"):
|
||||
rootDevice = fullDisk.succeed("stat -c %d /")
|
||||
nixStoreDevice = fullDisk.succeed("stat -c %d /nix/store")
|
||||
assert rootDevice == nixStoreDevice, "Nix store is mounted separately from the root fs"
|
||||
'';
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user