mirror of
https://github.com/SebastianWendel/nixpkgs.git
synced 2024-09-21 12:59:04 +02:00
Merge pull request #206839 from lheckemann/stateless-vms
nixos/qemu-vm: allow use without a disk image
This commit is contained in:
commit
48269da315
|
@ -108,9 +108,9 @@ let
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
NIX_DISK_IMAGE=$(readlink -f "''${NIX_DISK_IMAGE:-${config.virtualisation.diskImage}}")
|
NIX_DISK_IMAGE=$(readlink -f "''${NIX_DISK_IMAGE:-${toString config.virtualisation.diskImage}}") || test -z "$NIX_DISK_IMAGE"
|
||||||
|
|
||||||
if ! test -e "$NIX_DISK_IMAGE"; then
|
if test -n "$NIX_DISK_IMAGE" && ! test -e "$NIX_DISK_IMAGE"; then
|
||||||
${qemu}/bin/qemu-img create -f qcow2 "$NIX_DISK_IMAGE" \
|
${qemu}/bin/qemu-img create -f qcow2 "$NIX_DISK_IMAGE" \
|
||||||
${toString config.virtualisation.diskSize}M
|
${toString config.virtualisation.diskSize}M
|
||||||
fi
|
fi
|
||||||
|
@ -346,7 +346,7 @@ in
|
||||||
|
|
||||||
virtualisation.diskImage =
|
virtualisation.diskImage =
|
||||||
mkOption {
|
mkOption {
|
||||||
type = types.str;
|
type = types.nullOr types.str;
|
||||||
default = "./${config.system.name}.qcow2";
|
default = "./${config.system.name}.qcow2";
|
||||||
defaultText = literalExpression ''"./''${config.system.name}.qcow2"'';
|
defaultText = literalExpression ''"./''${config.system.name}.qcow2"'';
|
||||||
description =
|
description =
|
||||||
|
@ -354,6 +354,9 @@ in
|
||||||
Path to the disk image containing the root filesystem.
|
Path to the disk image containing the root filesystem.
|
||||||
The image will be created on startup if it does not
|
The image will be created on startup if it does not
|
||||||
exist.
|
exist.
|
||||||
|
|
||||||
|
If null, a tmpfs will be used as the root filesystem and
|
||||||
|
the VM's state will not be persistent.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -990,12 +993,12 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
virtualisation.qemu.drives = mkMerge [
|
virtualisation.qemu.drives = mkMerge [
|
||||||
[{
|
(mkIf (cfg.diskImage != null) [{
|
||||||
name = "root";
|
name = "root";
|
||||||
file = ''"$NIX_DISK_IMAGE"'';
|
file = ''"$NIX_DISK_IMAGE"'';
|
||||||
driveExtraOpts.cache = "writeback";
|
driveExtraOpts.cache = "writeback";
|
||||||
driveExtraOpts.werror = "report";
|
driveExtraOpts.werror = "report";
|
||||||
}]
|
}])
|
||||||
(mkIf cfg.useNixStoreImage [{
|
(mkIf cfg.useNixStoreImage [{
|
||||||
name = "nix-store";
|
name = "nix-store";
|
||||||
file = ''"$TMPDIR"/store.img'';
|
file = ''"$TMPDIR"/store.img'';
|
||||||
|
@ -1018,20 +1021,21 @@ in
|
||||||
}) cfg.emptyDiskImages)
|
}) cfg.emptyDiskImages)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
fileSystems = mkVMOverride cfg.fileSystems;
|
||||||
|
|
||||||
# Mount the host filesystem via 9P, and bind-mount the Nix store
|
# Mount the host filesystem via 9P, and bind-mount the Nix store
|
||||||
# of the host into our own filesystem. We use mkVMOverride to
|
# of the host into our own filesystem. We use mkVMOverride to
|
||||||
# allow this module to be applied to "normal" NixOS system
|
# allow this module to be applied to "normal" NixOS system
|
||||||
# configuration, where the regular value for the `fileSystems'
|
# configuration, where the regular value for the `fileSystems'
|
||||||
# attribute should be disregarded for the purpose of building a VM
|
# attribute should be disregarded for the purpose of building a VM
|
||||||
# test image (since those filesystems don't exist in the VM).
|
# test image (since those filesystems don't exist in the VM).
|
||||||
fileSystems =
|
virtualisation.fileSystems = let
|
||||||
let
|
|
||||||
mkSharedDir = tag: share:
|
mkSharedDir = tag: share:
|
||||||
{
|
{
|
||||||
name =
|
name =
|
||||||
if tag == "nix-store" && cfg.writableStore
|
if tag == "nix-store" && cfg.writableStore
|
||||||
then "/nix/.ro-store"
|
then "/nix/.ro-store"
|
||||||
else share.target;
|
else share.target;
|
||||||
value.device = tag;
|
value.device = tag;
|
||||||
value.fsType = "9p";
|
value.fsType = "9p";
|
||||||
value.neededForBoot = true;
|
value.neededForBoot = true;
|
||||||
|
@ -1039,44 +1043,42 @@ in
|
||||||
[ "trans=virtio" "version=9p2000.L" "msize=${toString cfg.msize}" ]
|
[ "trans=virtio" "version=9p2000.L" "msize=${toString cfg.msize}" ]
|
||||||
++ lib.optional (tag == "nix-store") "cache=loose";
|
++ lib.optional (tag == "nix-store") "cache=loose";
|
||||||
};
|
};
|
||||||
in
|
in lib.mkMerge [
|
||||||
mkVMOverride (cfg.fileSystems //
|
(lib.mapAttrs' mkSharedDir cfg.sharedDirectories)
|
||||||
optionalAttrs cfg.useDefaultFilesystems {
|
{
|
||||||
"/".device = cfg.bootDevice;
|
"/" = lib.mkIf cfg.useDefaultFilesystems (if cfg.diskImage == null then {
|
||||||
"/".fsType = "ext4";
|
device = "tmpfs";
|
||||||
"/".autoFormat = true;
|
fsType = "tmpfs";
|
||||||
} //
|
} else {
|
||||||
optionalAttrs config.boot.tmpOnTmpfs {
|
device = cfg.bootDevice;
|
||||||
"/tmp" = {
|
fsType = "ext4";
|
||||||
|
autoFormat = true;
|
||||||
|
});
|
||||||
|
"/tmp" = lib.mkIf config.boot.tmpOnTmpfs {
|
||||||
device = "tmpfs";
|
device = "tmpfs";
|
||||||
fsType = "tmpfs";
|
fsType = "tmpfs";
|
||||||
neededForBoot = true;
|
neededForBoot = true;
|
||||||
# Sync with systemd's tmp.mount;
|
# Sync with systemd's tmp.mount;
|
||||||
options = [ "mode=1777" "strictatime" "nosuid" "nodev" "size=${toString config.boot.tmpOnTmpfsSize}" ];
|
options = [ "mode=1777" "strictatime" "nosuid" "nodev" "size=${toString config.boot.tmpOnTmpfsSize}" ];
|
||||||
};
|
};
|
||||||
} //
|
"/nix/${if cfg.writableStore then ".ro-store" else "store"}" = lib.mkIf cfg.useNixStoreImage {
|
||||||
optionalAttrs cfg.useNixStoreImage {
|
|
||||||
"/nix/${if cfg.writableStore then ".ro-store" else "store"}" = {
|
|
||||||
device = "${lookupDriveDeviceName "nix-store" cfg.qemu.drives}";
|
device = "${lookupDriveDeviceName "nix-store" cfg.qemu.drives}";
|
||||||
neededForBoot = true;
|
neededForBoot = true;
|
||||||
options = [ "ro" ];
|
options = [ "ro" ];
|
||||||
};
|
};
|
||||||
} //
|
"/nix/.rw-store" = lib.mkIf (cfg.writableStore && cfg.writableStoreUseTmpfs) {
|
||||||
optionalAttrs (cfg.writableStore && cfg.writableStoreUseTmpfs) {
|
|
||||||
"/nix/.rw-store" = {
|
|
||||||
fsType = "tmpfs";
|
fsType = "tmpfs";
|
||||||
options = [ "mode=0755" ];
|
options = [ "mode=0755" ];
|
||||||
neededForBoot = true;
|
neededForBoot = true;
|
||||||
};
|
};
|
||||||
} //
|
|
||||||
optionalAttrs cfg.useBootLoader {
|
|
||||||
# see note [Disk layout with `useBootLoader`]
|
# see note [Disk layout with `useBootLoader`]
|
||||||
"/boot" = {
|
"/boot" = lib.mkIf cfg.useBootLoader {
|
||||||
device = "${lookupDriveDeviceName "boot" cfg.qemu.drives}2"; # 2 for e.g. `vdb2`, as created in `bootDisk`
|
device = "${lookupDriveDeviceName "boot" cfg.qemu.drives}2"; # 2 for e.g. `vdb2`, as created in `bootDisk`
|
||||||
fsType = "vfat";
|
fsType = "vfat";
|
||||||
noCheck = true; # fsck fails on a r/o filesystem
|
noCheck = true; # fsck fails on a r/o filesystem
|
||||||
};
|
};
|
||||||
} // lib.mapAttrs' mkSharedDir cfg.sharedDirectories);
|
}
|
||||||
|
];
|
||||||
|
|
||||||
boot.initrd.systemd = lib.mkIf (config.boot.initrd.systemd.enable && cfg.writableStore) {
|
boot.initrd.systemd = lib.mkIf (config.boot.initrd.systemd.enable && cfg.writableStore) {
|
||||||
mounts = [{
|
mounts = [{
|
||||||
|
|
Loading…
Reference in a new issue