diff --git a/example/bcachefs.nix b/example/bcachefs.nix index 7e153afb..023822b5 100644 --- a/example/bcachefs.nix +++ b/example/bcachefs.nix @@ -135,13 +135,6 @@ relies_on_external_subvolume = { type = "bcachefs_filesystem"; mountpoint = "/home/Documents"; - extraFormatArgs = [ - "--compression=lz4" - "--background_compression=lz4" - ]; - mountOptions = [ - "verbose" - ]; uuid = "64e50034-ebe2-eaf8-1f93-cf56266a8d86"; }; }; diff --git a/flake.lock b/flake.lock index 88e6258f..1150e275 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1752596105, - "narHash": "sha256-lFNVsu/mHLq3q11MuGkMhUUoSXEdQjCHvpReaGP1S2k=", + "lastModified": 1763618868, + "narHash": "sha256-v5afmLjn/uyD9EQuPBn7nZuaZVV9r+JerayK/4wvdWA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "dab3a6e781554f965bde3def0aa2fda4eb8f1708", + "rev": "a8d610af3f1a5fb71e23e08434d8d61a466fc942", "type": "github" }, "original": { diff --git a/lib/default.nix b/lib/default.nix index d4ba8657..bcab0ff8 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -39,22 +39,21 @@ let loc: defs: let evaled = lib.evalModules { - modules = - [ - { - freeformType = lib.types.lazyAttrsOf lib.types.raw; - options.type = lib.mkOption { - type = lib.types.str; - }; - } - ] - ++ map ( - { value, file }: - { - _file = file; - config = value; - } - ) defs; + modules = [ + { + freeformType = lib.types.lazyAttrsOf lib.types.raw; + options.type = lib.mkOption { + type = lib.types.str; + }; + } + ] + ++ map ( + { value, file }: + { + _file = file; + config = value; + } + ) defs; }; inherit (evaled.config) type; in @@ -1195,6 +1194,7 @@ let }; binfmt = import ./binfmt.nix; - } // outputs; + } + // outputs; in diskoLib diff --git a/lib/make-disk-image.nix b/lib/make-disk-image.nix index 2e1b55f9..8ca40989 100644 --- a/lib/make-disk-image.nix +++ b/lib/make-disk-image.nix @@ -29,19 +29,18 @@ let vmTools = pkgs.vmTools.override ( { - rootModules = - [ - "9p" - "9pnet_virtio" # we can drop those in future if we stop supporting 24.11 + rootModules = [ + "9p" + "9pnet_virtio" # we can drop those in future if we stop supporting 24.11 - "virtiofs" - "virtio_pci" - "virtio_blk" - "virtio_balloon" - "virtio_rng" - ] - ++ (lib.optional configSupportsZfs "zfs") - ++ cfg.extraRootModules; + "virtiofs" + "virtio_pci" + "virtio_blk" + "virtio_balloon" + "virtio_rng" + ] + ++ (lib.optional configSupportsZfs "zfs") + ++ cfg.extraRootModules; kernel = pkgs.aggregateModules ( [ cfg.kernelPackages.kernel diff --git a/lib/tests.nix b/lib/tests.nix index 1cfe5360..9edd8d36 100644 --- a/lib/tests.nix +++ b/lib/tests.nix @@ -237,21 +237,20 @@ let ( { config, ... }: { - boot.supportedFilesystems = - [ - "btrfs" - "cifs" - "f2fs" - "jfs" - "ntfs" - "reiserfs" - "vfat" - "xfs" - ] - ++ lib.optional ( - config.networking.hostId != null - && lib.meta.availableOn pkgs.stdenv.hostPlatform config.boot.zfs.package - ) "zfs"; + boot.supportedFilesystems = [ + "btrfs" + "cifs" + "f2fs" + "jfs" + "ntfs" + "reiserfs" + "vfat" + "xfs" + ] + ++ lib.optional ( + config.networking.hostId != null + && lib.meta.availableOn pkgs.stdenv.hostPlatform config.boot.zfs.package + ) "zfs"; } ) diff --git a/lib/types/bcachefs_filesystem.nix b/lib/types/bcachefs_filesystem.nix index 970717b5..8a453672 100644 --- a/lib/types/bcachefs_filesystem.nix +++ b/lib/types/bcachefs_filesystem.nix @@ -194,9 +194,10 @@ ${lib.optionalString ( config.passwordFile != null ) ''bcachefs unlock -k session "/dev/disk/by-uuid/${config.uuid}" < "${config.passwordFile}";''} - bcachefs mount \ + mount \ + -t bcachefs \ -o "${lib.concatStringsSep "," (lib.unique ([ "X-mount.mkdir" ] ++ config.mountOptions))}" \ - UUID="${config.uuid}" \ + "/dev/disk/by-uuid/${config.uuid}" \ "$MNTPOINT"; trap 'umount "$MNTPOINT"; rm -rf "$MNTPOINT"; rm -rf "$TEMPDIR";' EXIT; SUBVOL_ABS_PATH="$MNTPOINT/${subvolume.name}"; @@ -230,7 +231,8 @@ ${lib.optionalString ( config.passwordFile != null ) ''bcachefs unlock -k session "/dev/disk/by-uuid/${config.uuid}" < "${config.passwordFile}";''} - bcachefs mount \ + mount \ + -t bcachefs \ -o "${ lib.concatStringsSep "," ( lib.unique ( @@ -242,7 +244,7 @@ ) ) }" \ - UUID="${config.uuid}" \ + "/dev/disk/by-uuid/${config.uuid}" \ "${rootMountPoint}${subvolume.mountpoint}"; fi; ''; @@ -261,9 +263,10 @@ ${lib.optionalString ( config.passwordFile != null ) ''bcachefs unlock -k session "/dev/disk/by-uuid/${config.uuid}" < "${config.passwordFile}";''} - bcachefs mount \ + mount \ + -t bcachefs \ -o "${lib.concatStringsSep "," (lib.unique ([ "X-mount.mkdir" ] ++ config.mountOptions))}" \ - UUID="${config.uuid}" \ + "/dev/disk/by-uuid/${config.uuid}" \ "${rootMountPoint}${config.mountpoint}"; fi; ''; diff --git a/lib/types/luks.nix b/lib/types/luks.nix index 1875696f..9404711a 100644 --- a/lib/types/luks.nix +++ b/lib/types/luks.nix @@ -227,7 +227,8 @@ in { boot.initrd.luks.devices.${config.name} = { inherit (config) device; - } // config.settings; + } + // config.settings; } ]) ++ (lib.optional (config.content != null) config.content._config); diff --git a/lib/types/lvm_vg.nix b/lib/types/lvm_vg.nix index f40d0ed8..f44041f4 100644 --- a/lib/types/lvm_vg.nix +++ b/lib/types/lvm_vg.nix @@ -7,16 +7,15 @@ }: let # Load kernel modules to ensure device mapper types are available - kernelModules = - [ - # Prevent unbootable systems if LVM snapshots are present at boot time. - "dm-snapshot" - ] - ++ lib.filter (x: x != "") ( - map (lv: lib.optionalString (lv.lvm_type != null && lv.lvm_type != "thinlv") "dm-${lv.lvm_type}") ( - lib.attrValues config.lvs - ) - ); + kernelModules = [ + # Prevent unbootable systems if LVM snapshots are present at boot time. + "dm-snapshot" + ] + ++ lib.filter (x: x != "") ( + map (lv: lib.optionalString (lv.lvm_type != null && lv.lvm_type != "thinlv") "dm-${lv.lvm_type}") ( + lib.attrValues config.lvs + ) + ); in { options = { @@ -182,24 +181,24 @@ in _config = lib.mkOption { internal = true; readOnly = true; - default = - [ { boot.initrd.kernelModules = kernelModules; } ] - ++ map (lv: [ - (lib.optional (lv.content != null) lv.content._config) - (lib.optional (lv.lvm_type != null) { - boot.initrd.kernelModules = - [ - (if lv.lvm_type == "mirror" then "dm-mirror" else "dm-raid") - ] - ++ lib.optional (lv.lvm_type == "raid0") "raid0" - ++ lib.optional (lv.lvm_type == "raid1") "raid1" - # ++ lib.optional (lv.lvm_type == "raid10") "raid10" - ++ lib.optional ( - lv.lvm_type == "raid4" || lv.lvm_type == "raid5" || lv.lvm_type == "raid6" - ) "raid456"; + default = [ + { boot.initrd.kernelModules = kernelModules; } + ] + ++ map (lv: [ + (lib.optional (lv.content != null) lv.content._config) + (lib.optional (lv.lvm_type != null) { + boot.initrd.kernelModules = [ + (if lv.lvm_type == "mirror" then "dm-mirror" else "dm-raid") + ] + ++ lib.optional (lv.lvm_type == "raid0") "raid0" + ++ lib.optional (lv.lvm_type == "raid1") "raid1" + # ++ lib.optional (lv.lvm_type == "raid10") "raid10" + ++ lib.optional ( + lv.lvm_type == "raid4" || lv.lvm_type == "raid5" || lv.lvm_type == "raid6" + ) "raid456"; - }) - ]) (lib.attrValues config.lvs); + }) + ]) (lib.attrValues config.lvs); description = "NixOS configuration"; }; _pkgs = lib.mkOption { diff --git a/lib/types/mdadm.nix b/lib/types/mdadm.nix index 9b972171..900ea035 100644 --- a/lib/types/mdadm.nix +++ b/lib/types/mdadm.nix @@ -108,7 +108,8 @@ boot.initrd.services.swraid.enable = true; } ) - ] ++ lib.optional (config.content != null) config.content._config; + ] + ++ lib.optional (config.content != null) config.content._config; description = "NixOS configuration"; }; _pkgs = lib.mkOption { diff --git a/lib/types/zfs_fs.nix b/lib/types/zfs_fs.nix index 37e1c6fe..e006432a 100644 --- a/lib/types/zfs_fs.nix +++ b/lib/types/zfs_fs.nix @@ -124,19 +124,20 @@ fi ''; }) - // lib.optionalAttrs - (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") - { - fs.${config.mountpoint} = '' - if ! findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then - mount ${config._name} "${rootMountPoint}${config.mountpoint}" \ - -o X-mount.mkdir \ - ${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \ - ${lib.optionalString ((config.options.mountpoint or "") != "legacy") "-o zfsutil"} \ - -t zfs - fi - ''; - }; + // + lib.optionalAttrs + (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") + { + fs.${config.mountpoint} = '' + if ! findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then + mount ${config._name} "${rootMountPoint}${config.mountpoint}" \ + -o X-mount.mkdir \ + ${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \ + ${lib.optionalString ((config.options.mountpoint or "") != "legacy") "-o zfsutil"} \ + -t zfs + fi + ''; + }; }; _unmount = diskoLib.mkUnmountOption { @@ -149,15 +150,16 @@ fi ''; }) - // lib.optionalAttrs - (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") - { - fs.${config.mountpoint} = '' - if findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then - umount "${rootMountPoint}${config.mountpoint}" - fi - ''; - }; + // + lib.optionalAttrs + (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") + { + fs.${config.mountpoint} = '' + if findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then + umount "${rootMountPoint}${config.mountpoint}" + fi + ''; + }; }; _config = lib.mkOption { @@ -170,8 +172,7 @@ device = "${config._name}"; fsType = "zfs"; options = - config.mountOptions - ++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil"; + config.mountOptions ++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil"; }; }; description = "NixOS configuration"; diff --git a/tests/bcachefs.nix b/tests/bcachefs.nix index dbe0e7e1..84cd8d23 100644 --- a/tests/bcachefs.nix +++ b/tests/bcachefs.nix @@ -15,14 +15,27 @@ diskoLib.testLib.makeDiskoTest { machine.wait_for_text("enter passphrase for /nix"); machine.send_chars("secretsecret\n"); ''; + extraInstallerConfig = { + boot = { + kernelPackages = pkgs.linuxPackages_testing; + supportedFilesystems = [ "bcachefs" ]; + }; + }; extraSystemConfig = { environment.systemPackages = [ pkgs.jq ]; + boot.initrd.extraUtilsCommands = '' + # Copy tools for bcachefs + copy_bin_and_libs ${pkgs.lib.getOutput "mount" pkgs.util-linux}/bin/mount + copy_bin_and_libs ${pkgs.bcachefs-tools}/bin/bcachefs + copy_bin_and_libs ${pkgs.bcachefs-tools}/bin/mount.bcachefs + ''; }; extraTestScript = '' # Print debug information. - machine.succeed("ls -la /subvolumes >&2"); + machine.succeed("uname -a >&2"); + machine.succeed("ls -la / >&2"); machine.succeed("lsblk >&2"); machine.succeed("lsblk -f >&2"); machine.succeed("mount >&2"); @@ -30,14 +43,6 @@ diskoLib.testLib.makeDiskoTest { machine.succeed("bcachefs show-super /dev/vdd1 >&2"); machine.succeed("findmnt --json >&2"); - # Verify subvolume structure. - machine.succeed("test -d /subvolumes/root"); - machine.succeed("test -d /subvolumes/home"); - machine.succeed("test -d /subvolumes/home/user"); - machine.succeed("test -d /subvolumes/nix"); - machine.succeed("test -d /subvolumes/test"); - machine.fail("test -d /subvolumes/non-existent"); - # Verify existence of mountpoints. machine.succeed("mountpoint /"); machine.succeed("mountpoint /home"); @@ -48,15 +53,21 @@ diskoLib.testLib.makeDiskoTest { # Verify device membership and labels. machine.succeed("bcachefs show-super /dev/vda2 | grep 'Devices:' | grep -q '3'"); machine.succeed("bcachefs show-super /dev/vdd1 | grep 'Devices:' | grep -q '1'"); - machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]+Label:[[:space:]]+vdb2[[:space:]]\([[:digit:]]+\)'"); - machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]+Label:[[:space:]]+vdc1[[:space:]]\([[:digit:]]+\)'"); - machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]+Label:[[:space:]]+vdd1[[:space:]]\([[:digit:]]+\)'"); - machine.succeed("bcachefs show-super /dev/vdd1 | grep -qE '^[[:space:]]+Label:[[:space:]]+vde1[[:space:]]\([[:digit:]]+\)'"); + machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]*Label:[[:space:]]+group_a\.vdb2'"); + machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]*Label:[[:space:]]+group_a\.vdc1'"); + machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]*Label:[[:space:]]+group_b\.vdd1'"); + machine.succeed("bcachefs show-super /dev/vdd1 | grep -qE '^[[:space:]]*Label:[[:space:]]+group_a\.vde1'"); machine.fail("bcachefs show-super /dev/vda2 | grep 'Label:' | grep -q 'non-existent'"); - # @todo Verify format arguments. + # Verify format arguments. + # Test that lza4 compression and background_compression options were set for vda2. + machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]*compression:[[:space:]]+lz4'"); + machine.succeed("bcachefs show-super /dev/vda2 | grep -qE '^[[:space:]]*background_compression:[[:space:]]+lz4'"); + # Test that no compression option was set for vdd1. + machine.succeed("bcachefs show-super /dev/vdd1 | grep -qE '^[[:space:]]*compression:[[:space:]]+none'"); # Verify mount options from configuration. + # Test that verbose option was set for "/". machine.succeed(""" findmnt --json \ | jq -e ' \ @@ -64,11 +75,12 @@ diskoLib.testLib.makeDiskoTest { | select(.target == "/") \ | .options \ | split(",") \ - | contains(["verbose", "compression=lz4", "background_compression=lz4"]) \ + | contains(["verbose"]) \ ' """); - machine.succeed(""" + # Test that verbose option was not set for "/home/Documents". + machine.fail(""" findmnt --json \ | jq -e ' \ .filesystems[] \ @@ -80,6 +92,7 @@ diskoLib.testLib.makeDiskoTest { ' """); + # Test that non-existent option was not set for "/". machine.fail(""" findmnt --json \ | jq -e ' \ @@ -97,8 +110,11 @@ diskoLib.testLib.makeDiskoTest { | jq -e ' \ .filesystems[] \ | select(.target == "/") \ - | .source | split(":") \ - | contains(["/dev/vda2", "/dev/vdb1", "/dev/vdc1"]) \ + | .source \ + | contains("/dev/vda2") \ + and contains("/dev/vdb1") \ + and contains("/dev/vdc1") \ + and contains("[/subvolumes/root]") \ ' """); @@ -109,7 +125,7 @@ diskoLib.testLib.makeDiskoTest { | .. \ | select(.target? == "/home/Documents") \ | .source \ - | contains("/dev/disk/by-uuid/64e50034-ebe2-eaf8-1f93-cf56266a8d86") \ + | contains("/dev/vdd1") \ ' """); @@ -118,7 +134,7 @@ diskoLib.testLib.makeDiskoTest { | jq -e ' \ .filesystems[] \ | select(.target == "/") \ - | .source | split(":") \ + | .source \ | contains(["/dev/non-existent"]) \ ' """); diff --git a/tests/disko-install/configuration.nix b/tests/disko-install/configuration.nix index 7eaf12cf..5baf7515 100644 --- a/tests/disko-install/configuration.nix +++ b/tests/disko-install/configuration.nix @@ -25,11 +25,12 @@ ]; }; services.openssh.enable = true; - boot.kernelParams = - [ "console=tty0" ] - ++ (lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200") - ++ (lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200") - ++ [ "console=ttyS0,115200" ]; + boot.kernelParams = [ + "console=tty0" + ] + ++ (lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200") + ++ (lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200") + ++ [ "console=ttyS0,115200" ]; # reduce closure size nixpkgs.flake.setFlakeRegistry = false; diff --git a/tests/disko-install/default.nix b/tests/disko-install/default.nix index 042e99b0..9999ba23 100644 --- a/tests/disko-install/default.nix +++ b/tests/disko-install/default.nix @@ -15,12 +15,14 @@ let self.nixosConfigurations.testmachine.pkgs.perlPackages.FileSlurp self.nixosConfigurations.testmachine.config.system.build.toplevel + self.nixosConfigurations.testmachine.config.system.build.toplevel.drvPath self.nixosConfigurations.testmachine.config.system.build.diskoScript - ] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); + ] + ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); closureInfo = pkgs.closureInfo { rootPaths = dependencies; }; in -pkgs.nixosTest { +pkgs.testers.nixosTest { name = "disko-test"; nodes.machine = { virtualisation.emptyDiskImages = [ 4096 ];