diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index e73c5e7..0d07452 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -1,3 +1,15 @@ +2023-04-07 7d70009 + +zfs_datasets are now split into zfs_fs and zfs_volume. zfs_type got removed. size is only available for zfs_volume + +2023-04-07 654ecb3 + +lvm_lv types are always part of a lvm_vg and it is no longer possible (and neccessary) to specify the type + +2023-04-07 d6f062e + +parition types are always part of a table and it is no longer possible (and neccessary) to specify the type + 2023-03-22 2624af6 disk config now needs to be inside a disko.devices attrset always diff --git a/example/bcachefs.nix b/example/bcachefs.nix index e1df20e..d400b6b 100644 --- a/example/bcachefs.nix +++ b/example/bcachefs.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "100MiB"; @@ -22,7 +21,6 @@ } { name = "root"; - type = "partition"; start = "100MiB"; end = "100%"; part-type = "primary"; diff --git a/example/boot-raid1.nix b/example/boot-raid1.nix index 139922d..43d68c5 100644 --- a/example/boot-raid1.nix +++ b/example/boot-raid1.nix @@ -10,14 +10,12 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; part-type = "primary"; flags = [ "bios_grub" ]; } { - type = "partition"; name = "ESP"; start = "1MiB"; end = "128MiB"; @@ -29,7 +27,6 @@ }; } { - type = "partition"; name = "mdadm"; start = "128MiB"; end = "100%"; @@ -50,14 +47,12 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; part-type = "primary"; flags = [ "bios_grub" ]; } { - type = "partition"; name = "ESP"; start = "1MiB"; end = "128MiB"; @@ -69,7 +64,6 @@ }; } { - type = "partition"; name = "mdadm"; start = "128MiB"; end = "100%"; @@ -101,7 +95,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "primary"; start = "1MiB"; end = "100%"; diff --git a/example/btrfs-subvolumes.nix b/example/btrfs-subvolumes.nix index 7484961..f08d00b 100644 --- a/example/btrfs-subvolumes.nix +++ b/example/btrfs-subvolumes.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "128MiB"; @@ -23,7 +22,6 @@ } { name = "root"; - type = "partition"; start = "128MiB"; end = "100%"; content = { diff --git a/example/complex.nix b/example/complex.nix index e222339..501de2a 100644 --- a/example/complex.nix +++ b/example/complex.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "128MiB"; @@ -32,7 +31,6 @@ format = "gpt"; partitions = [ { - type = "partition"; start = "1M"; end = "100%"; name = "luks"; @@ -60,7 +58,6 @@ format = "gpt"; partitions = [ { - type = "partition"; start = "1M"; end = "100%"; name = "luks"; @@ -90,7 +87,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "bla"; start = "1MiB"; end = "100%"; @@ -109,7 +105,6 @@ type = "lvm_vg"; lvs = { root = { - type = "lvm_lv"; size = "10M"; lvm_type = "mirror"; content = { @@ -122,7 +117,6 @@ }; }; raid1 = { - type = "lvm_lv"; size = "30M"; lvm_type = "raid0"; content = { @@ -131,7 +125,6 @@ }; }; raid2 = { - type = "lvm_lv"; size = "30M"; lvm_type = "raid0"; content = { @@ -140,7 +133,6 @@ }; }; zfs1 = { - type = "lvm_lv"; size = "128M"; lvm_type = "raid0"; content = { @@ -149,7 +141,6 @@ }; }; zfs2 = { - type = "lvm_lv"; size = "128M"; lvm_type = "raid0"; content = { @@ -172,21 +163,21 @@ datasets = { zfs_fs = { - zfs_type = "filesystem"; + type = "zfs_fs"; mountpoint = "/zfs_fs"; options."com.sun:auto-snapshot" = "true"; }; zfs_unmounted_fs = { - zfs_type = "filesystem"; + type = "zfs_fs"; options.mountpoint = "none"; }; zfs_legacy_fs = { - zfs_type = "filesystem"; + type = "zfs_fs"; options.mountpoint = "legacy"; mountpoint = "/zfs_legacy_fs"; }; zfs_testvolume = { - zfs_type = "volume"; + type = "zfs_volume"; size = "10M"; content = { type = "filesystem"; diff --git a/example/gpt-bios-compat.nix b/example/gpt-bios-compat.nix index c64930e..2bdd6d8 100644 --- a/example/gpt-bios-compat.nix +++ b/example/gpt-bios-compat.nix @@ -11,7 +11,6 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; part-type = "primary"; @@ -19,7 +18,6 @@ } { name = "root"; - type = "partition"; # leave space for the grub aka BIOS boot start = "1M"; end = "100%"; diff --git a/example/hybrid-tmpfs-on-root.nix b/example/hybrid-tmpfs-on-root.nix index 8eef875..7a4ef8f 100644 --- a/example/hybrid-tmpfs-on-root.nix +++ b/example/hybrid-tmpfs-on-root.nix @@ -9,13 +9,11 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; flags = [ "bios_grub" ]; } { - type = "partition"; name = "ESP"; start = "1M"; end = "512M"; @@ -28,7 +26,6 @@ } { name = "nix"; - type = "partition"; start = "512M"; end = "100%"; part-type = "primary"; diff --git a/example/hybrid.nix b/example/hybrid.nix index 92aacf3..aeef6b8 100644 --- a/example/hybrid.nix +++ b/example/hybrid.nix @@ -10,13 +10,11 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; flags = [ "bios_grub" ]; } { - type = "partition"; name = "ESP"; start = "1M"; end = "512M"; @@ -28,7 +26,6 @@ }; } { - type = "partition"; name = "root"; start = "512M"; end = "100%"; diff --git a/example/luks-lvm.nix b/example/luks-lvm.nix index 733333e..c6340d0 100644 --- a/example/luks-lvm.nix +++ b/example/luks-lvm.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "100MiB"; @@ -24,7 +23,6 @@ }; } { - type = "partition"; name = "luks"; start = "100MiB"; end = "100%"; @@ -48,7 +46,6 @@ type = "lvm_vg"; lvs = { root = { - type = "lvm_lv"; size = "100M"; content = { type = "filesystem"; @@ -60,7 +57,6 @@ }; }; home = { - type = "lvm_lv"; size = "10M"; content = { type = "filesystem"; @@ -69,7 +65,6 @@ }; }; raw = { - type = "lvm_lv"; size = "10M"; }; }; diff --git a/example/lvm-raid.nix b/example/lvm-raid.nix index cf20b21..2c06d88 100644 --- a/example/lvm-raid.nix +++ b/example/lvm-raid.nix @@ -10,7 +10,6 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "100M"; fs-type = "fat32"; @@ -21,7 +20,6 @@ }; } { - type = "partition"; name = "primary"; start = "100M"; end = "100%"; @@ -42,7 +40,6 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "100M"; fs-type = "fat32"; @@ -53,7 +50,6 @@ }; } { - type = "partition"; name = "primary"; start = "100M"; end = "100%"; @@ -83,7 +79,6 @@ type = "lvm_vg"; lvs = { root = { - type = "lvm_lv"; size = "100M"; lvm_type = "mirror"; content = { @@ -96,7 +91,6 @@ }; }; home = { - type = "lvm_lv"; size = "10M"; lvm_type = "raid0"; content = { diff --git a/example/mdadm.nix b/example/mdadm.nix index efe95c6..ccabe5c 100644 --- a/example/mdadm.nix +++ b/example/mdadm.nix @@ -10,14 +10,12 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; part-type = "primary"; flags = [ "bios_grub" ]; } { - type = "partition"; name = "mdadm"; start = "1MiB"; end = "100%"; @@ -38,14 +36,12 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; part-type = "primary"; flags = [ "bios_grub" ]; } { - type = "partition"; name = "mdadm"; start = "1MiB"; end = "100%"; @@ -67,7 +63,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "primary"; start = "1MiB"; end = "100%"; diff --git a/example/multi-device-no-deps.nix b/example/multi-device-no-deps.nix index a01644b..09b0839 100644 --- a/example/multi-device-no-deps.nix +++ b/example/multi-device-no-deps.nix @@ -10,7 +10,6 @@ partitions = [ { name = "nix"; - type = "partition"; part-type = "primary"; start = "0%"; end = "100%"; @@ -33,7 +32,6 @@ partitions = [ { name = "root"; - type = "partition"; part-type = "primary"; start = "0%"; end = "100%"; diff --git a/example/negative-size.nix b/example/negative-size.nix index 9ec27ab..89d8754 100644 --- a/example/negative-size.nix +++ b/example/negative-size.nix @@ -10,7 +10,6 @@ partitions = [ { name = "nix"; - type = "partition"; part-type = "primary"; start = "0%"; end = "-10MiB"; diff --git a/example/simple-efi.nix b/example/simple-efi.nix index 0a5f2d1..459fdec 100644 --- a/example/simple-efi.nix +++ b/example/simple-efi.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "100MiB"; @@ -22,7 +21,6 @@ } { name = "root"; - type = "partition"; start = "100MiB"; end = "100%"; part-type = "primary"; diff --git a/example/stand-alone/configuration.nix b/example/stand-alone/configuration.nix index 973f3f2..6161cea 100644 --- a/example/stand-alone/configuration.nix +++ b/example/stand-alone/configuration.nix @@ -25,7 +25,6 @@ let partitions = [ { name = "root"; - type = "partition"; part-type = "primary"; start = "1M"; end = "100%"; diff --git a/example/swap.nix b/example/swap.nix index e442b9c..14ec861 100644 --- a/example/swap.nix +++ b/example/swap.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "100MiB"; @@ -22,7 +21,6 @@ } { name = "root"; - type = "partition"; start = "100MiB"; end = "-1G"; part-type = "primary"; @@ -34,7 +32,6 @@ } { name = "swap"; - type = "partition"; start = "-1G"; end = "100%"; part-type = "primary"; diff --git a/example/tmpfs.nix b/example/tmpfs.nix index 8942e9f..cc43115 100644 --- a/example/tmpfs.nix +++ b/example/tmpfs.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "100MiB"; @@ -22,7 +21,6 @@ } { name = "root"; - type = "partition"; start = "100MiB"; end = "100%"; part-type = "primary"; diff --git a/example/with-lib.nix b/example/with-lib.nix index 4500f3e..ed3c19d 100644 --- a/example/with-lib.nix +++ b/example/with-lib.nix @@ -10,7 +10,6 @@ partitions = [ { name = "boot"; - type = "partition"; start = "0"; end = "1M"; part-type = "primary"; @@ -18,7 +17,6 @@ } { name = "root"; - type = "partition"; # leave space for the grub aka BIOS boot start = "1M"; end = "100%"; diff --git a/example/zfs-over-legacy.nix b/example/zfs-over-legacy.nix index 9ca67a8..2a5a2c6 100644 --- a/example/zfs-over-legacy.nix +++ b/example/zfs-over-legacy.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "1MiB"; end = "100MiB"; @@ -24,7 +23,6 @@ }; } { - type = "partition"; start = "100MiB"; end = "100%"; name = "primary"; @@ -52,11 +50,11 @@ type = "zpool"; datasets = { "root" = { - zfs_type = "filesystem"; + type = "zfs_fs"; options.mountpoint = "none"; }; "root/zfs_fs" = { - zfs_type = "filesystem"; + type = "zfs_fs"; mountpoint = "/zfs_fs"; options."com.sun:auto-snapshot" = "true"; }; diff --git a/example/zfs.nix b/example/zfs.nix index e126d51..f5db396 100644 --- a/example/zfs.nix +++ b/example/zfs.nix @@ -9,7 +9,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "ESP"; start = "0"; end = "64MiB"; @@ -22,7 +21,6 @@ }; } { - type = "partition"; name = "zfs"; start = "128MiB"; end = "100%"; @@ -42,7 +40,6 @@ format = "gpt"; partitions = [ { - type = "partition"; name = "zfs"; start = "128MiB"; end = "100%"; @@ -68,21 +65,21 @@ datasets = { zfs_fs = { - zfs_type = "filesystem"; + type = "zfs_fs"; mountpoint = "/zfs_fs"; options."com.sun:auto-snapshot" = "true"; }; zfs_unmounted_fs = { - zfs_type = "filesystem"; + type = "zfs_fs"; options.mountpoint = "none"; }; zfs_legacy_fs = { - zfs_type = "filesystem"; + type = "zfs_fs"; options.mountpoint = "legacy"; mountpoint = "/zfs_legacy_fs"; }; zfs_testvolume = { - zfs_type = "volume"; + type = "zfs_volume"; size = "10M"; content = { type = "filesystem"; @@ -91,8 +88,7 @@ }; }; encrypted = { - zfs_type = "filesystem"; - size = "20M"; + type = "zfs_fs"; options = { mountpoint = "none"; encryption = "aes-256-gcm"; @@ -104,8 +100,7 @@ ''; }; "encrypted/test" = { - zfs_type = "filesystem"; - size = "2M"; + type = "zfs_fs"; mountpoint = "/zfs_crypted"; }; }; diff --git a/types/default.nix b/types/default.nix index f0e1909..ec2f4f5 100644 --- a/types/default.nix +++ b/types/default.nix @@ -133,7 +133,7 @@ rec { || lib.hasSuffix "Hook" n || isAttrsOfSubmodule o # TODO don't hardcode diskoLib.subType options. - || n == "content" || n == "partitions" + || n == "content" || n == "partitions" || n == "datasets" ); in lib.toShellVars @@ -342,14 +342,14 @@ rec { btrfs_subvol = ./btrfs_subvol.nix; filesystem = ./filesystem.nix; table = ./table.nix; - partition = ./partition.nix; swap = ./swap.nix; lvm_pv = ./lvm_pv.nix; lvm_vg = ./lvm_vg.nix; - lvm_lv = ./lvm_lv.nix; zfs = ./zfs.nix; zpool = ./zpool.nix; zfs_dataset = ./zfs_dataset.nix; + zfs_fs = ./zfs_fs.nix; + zfs_volume = ./zfs_volume.nix; mdadm = ./mdadm.nix; mdraid = ./mdraid.nix; luks = ./luks.nix; diff --git a/types/lvm_lv.nix b/types/lvm_lv.nix deleted file mode 100644 index d2df6fc..0000000 --- a/types/lvm_lv.nix +++ /dev/null @@ -1,76 +0,0 @@ -{ config, options, lib, diskoLib, ... }: -{ - options = { - name = lib.mkOption { - type = lib.types.str; - default = config._module.args.name; - description = "Name of the logical volume"; - }; - type = lib.mkOption { - type = lib.types.enum [ "lvm_lv" ]; - default = "lvm_lv"; - internal = true; - description = "Type"; - }; - size = lib.mkOption { - type = lib.types.str; # TODO lvm size type - description = "Size of the logical volume"; - }; - lvm_type = lib.mkOption { - type = lib.types.nullOr (lib.types.enum [ "mirror" "raid0" "raid1" ]); # TODO add all lib.types - default = null; # maybe there is always a default type? - description = "LVM type"; - }; - extraArgs = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - description = "Extra arguments"; - }; - content = diskoLib.partitionType; - _meta = lib.mkOption { - internal = true; - readOnly = true; - type = lib.types.functionTo diskoLib.jsonType; - default = dev: - lib.optionalAttrs (config.content != null) (config.content._meta dev); - description = "Metadata"; - }; - _create = diskoLib.mkCreateOption { - inherit config options; - default = { vg }: '' - lvcreate \ - --yes \ - ${if lib.hasInfix "%" config.size then "-l" else "-L"} ${config.size} \ - -n ${config.name} \ - ${lib.optionalString (config.lvm_type != null) "--type=${config.lvm_type}"} \ - ${toString config.extraArgs} \ - ${vg} - ${lib.optionalString (config.content != null) (config.content._create {dev = "/dev/${vg}/${config.name}";})} - ''; - }; - _mount = diskoLib.mkMountOption { - inherit config options; - default = { vg }: - lib.optionalAttrs (config.content != null) (config.content._mount { dev = "/dev/${vg}/${config.name}"; }); - }; - _config = lib.mkOption { - internal = true; - readOnly = true; - default = vg: - [ - (lib.optional (config.content != null) (config.content._config "/dev/${vg}/${config.name}")) - (lib.optional (config.lvm_type != null) { - boot.initrd.kernelModules = [ "dm-${config.lvm_type}" ]; - }) - ]; - description = "NixOS configuration"; - }; - _pkgs = lib.mkOption { - internal = true; - readOnly = true; - type = lib.types.functionTo (lib.types.listOf lib.types.package); - default = pkgs: lib.optionals (config.content != null) (config.content._pkgs pkgs); - description = "Packages"; - }; - }; -} diff --git a/types/lvm_vg.nix b/types/lvm_vg.nix index 70845ff..a6b1cc3 100644 --- a/types/lvm_vg.nix +++ b/types/lvm_vg.nix @@ -12,7 +12,30 @@ description = "Type"; }; lvs = lib.mkOption { - type = lib.types.attrsOf subTypes.lvm_lv; + type = lib.types.attrsOf (lib.types.submodule ({ config, ... }: { + options = { + name = lib.mkOption { + type = lib.types.str; + default = config._module.args.name; + description = "Name of the logical volume"; + }; + size = lib.mkOption { + type = lib.types.str; # TODO lvm size type + description = "Size of the logical volume"; + }; + lvm_type = lib.mkOption { + type = lib.types.nullOr (lib.types.enum [ "mirror" "raid0" "raid1" ]); # TODO add all lib.types + default = null; # maybe there is always a default type? + description = "LVM type"; + }; + extraArgs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "Extra arguments"; + }; + content = diskoLib.partitionType; + }; + })); default = { }; description = "LVS for the volume group"; }; @@ -21,7 +44,9 @@ readOnly = true; type = diskoLib.jsonType; default = - diskoLib.deepMergeMap (lv: lv._meta [ "lvm_vg" config.name ]) (lib.attrValues config.lvs); + diskoLib.deepMergeMap (lv: + lib.optionalAttrs (lv.content != null) (lv.content._meta [ "lvm_vg" config.name ]) + ) (lib.attrValues config.lvs); description = "Metadata"; }; _create = diskoLib.mkCreateOption { @@ -30,14 +55,25 @@ readarray -t lvm_devices < <(cat "$disko_devices_dir"/lvm_${config.name}) vgcreate ${config.name} \ "''${lvm_devices[@]}" - ${lib.concatMapStrings (lv: lv._create {vg = config.name; }) (lib.attrValues config.lvs)} + ${lib.concatMapStrings (lv: '' + lvcreate \ + --yes \ + ${if lib.hasInfix "%" lv.size then "-l" else "-L"} ${lv.size} \ + -n ${lv.name} \ + ${lib.optionalString (lv.lvm_type != null) "--type=${lv.lvm_type}"} \ + ${toString lv.extraArgs} \ + ${config.name} + ${lib.optionalString (lv.content != null) (lv.content._create {dev = "/dev/${config.name}/${lv.name}";})} + '') (lib.attrValues config.lvs)} ''; }; _mount = diskoLib.mkMountOption { inherit config options; default = _: let - lvMounts = diskoLib.deepMergeMap (lv: lv._mount { vg = config.name; }) (lib.attrValues config.lvs); + lvMounts = diskoLib.deepMergeMap (lv: + lib.optionalAttrs (lv.content != null) (lv.content._mount { dev = "/dev/${config.name}/${lv.name}"; }) + ) (lib.attrValues config.lvs); in { dev = '' @@ -51,14 +87,21 @@ internal = true; readOnly = true; default = - map (lv: lv._config config.name) (lib.attrValues config.lvs); + map (lv: [ + (lib.optional (lv.content != null) (lv.content._config "/dev/${config.name}/${lv.name}")) + (lib.optional (lv.lvm_type != null) { + boot.initrd.kernelModules = [ "dm-${lv.lvm_type}" ]; + }) + ]) (lib.attrValues config.lvs); description = "NixOS configuration"; }; _pkgs = lib.mkOption { internal = true; readOnly = true; type = lib.types.functionTo (lib.types.listOf lib.types.package); - default = pkgs: lib.flatten (map (lv: lv._pkgs pkgs) (lib.attrValues config.lvs)); + default = pkgs: lib.flatten (map (lv: + lib.optional (lv.content != null) (lv.content._pkgs pkgs) + ) (lib.attrValues config.lvs)); description = "Packages"; }; }; diff --git a/types/partition.nix b/types/partition.nix deleted file mode 100644 index 03d585f..0000000 --- a/types/partition.nix +++ /dev/null @@ -1,100 +0,0 @@ -{ config, options, lib, diskoLib, ... }: -{ - options = { - type = lib.mkOption { - type = lib.types.enum [ "partition" ]; - internal = true; - description = "Type"; - }; - part-type = lib.mkOption { - type = lib.types.enum [ "primary" "logical" "extended" ]; - default = "primary"; - description = "Partition type"; - }; - fs-type = lib.mkOption { - type = lib.types.nullOr (lib.types.enum [ "btrfs" "ext2" "ext3" "ext4" "fat16" "fat32" "hfs" "hfs+" "linux-swap" "ntfs" "reiserfs" "udf" "xfs" ]); - default = null; - description = "Filesystem type to use"; - }; - name = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "Name of the partition"; - }; - start = lib.mkOption { - type = lib.types.str; - default = "0%"; - description = "Start of the partition"; - }; - end = lib.mkOption { - type = lib.types.str; - default = "100%"; - description = "End of the partition"; - }; - index = lib.mkOption { - type = lib.types.int; - # TODO find a better way to get the index - default = lib.toInt (lib.head (builtins.match ".*entry ([[:digit:]]+)]" config._module.args.name)); - description = "Index of the partition"; - }; - flags = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - description = "Partition flags"; - }; - bootable = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Whether to make the partition bootable"; - }; - content = diskoLib.partitionType; - _meta = lib.mkOption { - internal = true; - readOnly = true; - type = lib.types.functionTo diskoLib.jsonType; - default = dev: - lib.optionalAttrs (config.content != null) (config.content._meta dev); - description = "Metadata"; - }; - _create = diskoLib.mkCreateOption { - inherit config options; - default = { dev, type }: '' - ${lib.optionalString (type == "gpt") '' - parted -s ${dev} -- mkpart ${config.name} ${diskoLib.maybeStr config.fs-type} ${config.start} ${config.end} - ''} - ${lib.optionalString (type == "msdos") '' - parted -s ${dev} -- mkpart ${config.part-type} ${diskoLib.maybeStr config.fs-type} ${diskoLib.maybeStr config.fs-type} ${config.start} ${config.end} - ''} - # ensure /dev/disk/by-path/..-partN exists before continuing - udevadm trigger --subsystem-match=block; udevadm settle - ${lib.optionalString config.bootable '' - parted -s ${dev} -- set ${toString config.index} boot on - ''} - ${lib.concatMapStringsSep "" (flag: '' - parted -s ${dev} -- set ${toString config.index} ${flag} on - '') config.flags} - # ensure further operations can detect new partitions - udevadm trigger --subsystem-match=block; udevadm settle - ${lib.optionalString (config.content != null) (config.content._create {dev = diskoLib.deviceNumbering dev config.index;})} - ''; - }; - _mount = diskoLib.mkMountOption { - inherit config options; - default = { dev }: - lib.optionalAttrs (config.content != null) (config.content._mount { dev = diskoLib.deviceNumbering dev config.index; }); - }; - _config = lib.mkOption { - internal = true; - readOnly = true; - default = dev: - lib.optional (config.content != null) (config.content._config (diskoLib.deviceNumbering dev config.index)); - description = "NixOS configuration"; - }; - _pkgs = lib.mkOption { - internal = true; - readOnly = true; - type = lib.types.functionTo (lib.types.listOf lib.types.package); - default = pkgs: lib.optionals (config.content != null) (config.content._pkgs pkgs); - description = "Packages"; - }; - }; -} diff --git a/types/table.nix b/types/table.nix index b47ed29..0d9fb14 100644 --- a/types/table.nix +++ b/types/table.nix @@ -12,7 +12,51 @@ description = "The kind of partition table"; }; partitions = lib.mkOption { - type = lib.types.listOf subTypes.partition; + type = lib.types.listOf (lib.types.submodule ({ config, ... }: { + options = { + part-type = lib.mkOption { + type = lib.types.enum [ "primary" "logical" "extended" ]; + default = "primary"; + description = "Partition type"; + }; + fs-type = lib.mkOption { + type = lib.types.nullOr (lib.types.enum [ "btrfs" "ext2" "ext3" "ext4" "fat16" "fat32" "hfs" "hfs+" "linux-swap" "ntfs" "reiserfs" "udf" "xfs" ]); + default = null; + description = "Filesystem type to use"; + }; + name = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "Name of the partition"; + }; + start = lib.mkOption { + type = lib.types.str; + default = "0%"; + description = "Start of the partition"; + }; + end = lib.mkOption { + type = lib.types.str; + default = "100%"; + description = "End of the partition"; + }; + index = lib.mkOption { + type = lib.types.int; + # TODO find a better way to get the index + default = lib.toInt (lib.head (builtins.match ".*entry ([[:digit:]]+)]" config._module.args.name)); + description = "Index of the partition"; + }; + flags = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "Partition flags"; + }; + bootable = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to make the partition bootable"; + }; + content = diskoLib.partitionType; + }; + })); default = [ ]; description = "List of partitions to add to the partition table"; }; @@ -21,21 +65,43 @@ readOnly = true; type = lib.types.functionTo diskoLib.jsonType; default = dev: - diskoLib.deepMergeMap (partition: partition._meta dev) config.partitions; + lib.foldr lib.recursiveUpdate {} (lib.imap (index: partition: + lib.optionalAttrs (partition.content != null) (partition.content._meta dev) + ) config.partitions); description = "Metadata"; }; _create = diskoLib.mkCreateOption { inherit config options; default = { dev }: '' parted -s ${dev} -- mklabel ${config.format} - ${lib.concatMapStrings (partition: partition._create {inherit dev; type = config.format;} ) config.partitions} + ${lib.concatStrings (lib.imap (index: partition: '' + ${lib.optionalString (config.format == "gpt") '' + parted -s ${dev} -- mkpart ${partition.name} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} + ''} + ${lib.optionalString (config.format == "msdos") '' + parted -s ${dev} -- mkpart ${partition.part-type} ${diskoLib.maybeStr partition.fs-type} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} + ''} + # ensure /dev/disk/by-path/..-partN exists before continuing + udevadm trigger --subsystem-match=block; udevadm settle + ${lib.optionalString partition.bootable '' + parted -s ${dev} -- set ${toString index} boot on + ''} + ${lib.concatMapStringsSep "" (flag: '' + parted -s ${dev} -- set ${toString index} ${flag} on + '') partition.flags} + # ensure further operations can detect new partitions + udevadm trigger --subsystem-match=block; udevadm settle + ${lib.optionalString (partition.content != null) (partition.content._create { dev = diskoLib.deviceNumbering dev index; })} + '') config.partitions)} ''; }; _mount = diskoLib.mkMountOption { inherit config options; default = { dev }: let - partMounts = diskoLib.deepMergeMap (partition: partition._mount { inherit dev; }) config.partitions; + partMounts = lib.foldr lib.recursiveUpdate {} (lib.imap (index: partition: + lib.optionalAttrs (partition.content != null) (partition.content._mount { dev = diskoLib.deviceNumbering dev index; }) + ) config.partitions); in { dev = partMounts.dev or ""; @@ -46,7 +112,9 @@ internal = true; readOnly = true; default = dev: - map (partition: partition._config dev) config.partitions; + lib.imap (index: partition: + lib.optional (partition.content != null) (partition.content._config (diskoLib.deviceNumbering dev index)) + ) config.partitions; description = "NixOS configuration"; }; _pkgs = lib.mkOption { @@ -54,7 +122,9 @@ readOnly = true; type = lib.types.functionTo (lib.types.listOf lib.types.package); default = pkgs: - [ pkgs.parted pkgs.systemdMinimal ] ++ lib.flatten (map (partition: partition._pkgs pkgs) config.partitions); + [ pkgs.parted pkgs.systemdMinimal ] ++ lib.flatten (map (partition: + lib.optional (partition.content != null) (partition.content._pkgs pkgs) + ) config.partitions); description = "Packages"; }; }; diff --git a/types/zfs_dataset.nix b/types/zfs_fs.nix similarity index 60% rename from types/zfs_dataset.nix rename to types/zfs_fs.nix index c3eadbc..a9ad950 100644 --- a/types/zfs_dataset.nix +++ b/types/zfs_fs.nix @@ -7,15 +7,11 @@ description = "Name of the dataset"; }; type = lib.mkOption { - type = lib.types.enum [ "zfs_dataset" ]; - default = "zfs_dataset"; + type = lib.types.enum [ "zfs_fs" ]; + default = "zfs_fs"; internal = true; description = "Type"; }; - zfs_type = lib.mkOption { - type = lib.types.enum [ "filesystem" "volume" ]; - description = "The type of the dataset"; - }; options = lib.mkOption { type = lib.types.attrsOf lib.types.str; default = { }; @@ -27,46 +23,30 @@ description = "Mount options"; }; - # filesystem options mountpoint = lib.mkOption { type = lib.types.nullOr optionTypes.absolute-pathname; default = null; description = "Path to mount the dataset to"; }; - # volume options - size = lib.mkOption { - type = lib.types.nullOr lib.types.str; # TODO size - default = null; - description = "Size of the dataset"; - }; - - content = diskoLib.partitionType; _meta = lib.mkOption { internal = true; readOnly = true; type = lib.types.functionTo diskoLib.jsonType; - default = dev: - lib.optionalAttrs (config.content != null) (config.content._meta dev); + default = dev: {}; description = "Metadata"; }; _create = diskoLib.mkCreateOption { inherit config options; default = { zpool }: '' zfs create ${zpool}/${config.name} \ - ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} \ - ${lib.optionalString (config.zfs_type == "volume") "-V ${config.size}"} - ${lib.optionalString (config.zfs_type == "volume") '' - udevadm trigger --subsystem-match=block; udevadm settle - ${lib.optionalString (config.content != null) (config.content._create {dev = "/dev/zvol/${zpool}/${config.name}";})} - ''} + ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} ''; }; _mount = diskoLib.mkMountOption { inherit config options; default = { zpool }: - lib.optionalAttrs (config.zfs_type == "volume" && config.content != null) (config.content._mount { dev = "/dev/zvol/${zpool}/${config.name}"; }) // - lib.optionalAttrs (config.zfs_type == "filesystem" && config.options.mountpoint or "" != "none") { + lib.optionalAttrs (config.options.mountpoint or "" != "none") { fs.${config.mountpoint} = '' if ! findmnt ${zpool}/${config.name} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then mount ${zpool}/${config.name} "${rootMountPoint}${config.mountpoint}" \ @@ -82,22 +62,22 @@ internal = true; readOnly = true; default = zpool: - (lib.optional (config.zfs_type == "volume" && config.content != null) (config.content._config "/dev/zvol/${zpool}/${config.name}")) ++ - (lib.optional (config.zfs_type == "filesystem" && config.options.mountpoint or "" != "none") { + lib.optional (config.options.mountpoint or "" != "none") { fileSystems.${config.mountpoint} = { device = "${zpool}/${config.name}"; fsType = "zfs"; options = config.mountOptions ++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil"; }; - }); + }; description = "NixOS configuration"; }; _pkgs = lib.mkOption { internal = true; readOnly = true; type = lib.types.functionTo (lib.types.listOf lib.types.package); - default = pkgs: [ pkgs.util-linux ] ++ lib.optionals (config.content != null) (config.content._pkgs pkgs); + default = pkgs: [ pkgs.util-linux ]; description = "Packages"; }; }; } + diff --git a/types/zfs_volume.nix b/types/zfs_volume.nix new file mode 100644 index 0000000..2609ed6 --- /dev/null +++ b/types/zfs_volume.nix @@ -0,0 +1,73 @@ +{ config, options, lib, diskoLib, optionTypes, rootMountPoint, ... }: +{ + options = { + name = lib.mkOption { + type = lib.types.str; + default = config._module.args.name; + description = "Name of the dataset"; + }; + type = lib.mkOption { + type = lib.types.enum [ "zfs_volume" ]; + default = "zfs_volume"; + internal = true; + description = "Type"; + }; + options = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = { }; + description = "Options to set for the dataset"; + }; + mountOptions = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "defaults" ]; + description = "Mount options"; + }; + + # volume options + size = lib.mkOption { + type = lib.types.nullOr lib.types.str; # TODO size + default = null; + description = "Size of the dataset"; + }; + + content = diskoLib.partitionType; + + _meta = lib.mkOption { + internal = true; + readOnly = true; + type = lib.types.functionTo diskoLib.jsonType; + default = dev: + lib.optionalAttrs (config.content != null) (config.content._meta dev); + description = "Metadata"; + }; + _create = diskoLib.mkCreateOption { + inherit config options; + default = { zpool }: '' + zfs create ${zpool}/${config.name} \ + ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} -V ${config.size} + udevadm trigger --subsystem-match=block; udevadm settle + ${lib.optionalString (config.content != null) (config.content._create {dev = "/dev/zvol/${zpool}/${config.name}";})} + ''; + }; + _mount = diskoLib.mkMountOption { + inherit config options; + default = { zpool }: + lib.optionalAttrs (config.content != null) (config.content._mount { dev = "/dev/zvol/${zpool}/${config.name}"; }); + }; + _config = lib.mkOption { + internal = true; + readOnly = true; + default = zpool: + lib.optional (config.content != null) (config.content._config "/dev/zvol/${zpool}/${config.name}"); + description = "NixOS configuration"; + }; + _pkgs = lib.mkOption { + internal = true; + readOnly = true; + type = lib.types.functionTo (lib.types.listOf lib.types.package); + default = pkgs: [ pkgs.util-linux ] ++ lib.optionals (config.content != null) (config.content._pkgs pkgs); + description = "Packages"; + }; + }; +} + diff --git a/types/zpool.nix b/types/zpool.nix index 0a7e66a..4c70bd6 100644 --- a/types/zpool.nix +++ b/types/zpool.nix @@ -38,7 +38,8 @@ description = "Options to pass to mount"; }; datasets = lib.mkOption { - type = lib.types.attrsOf subTypes.zfs_dataset; + type = lib.types.attrsOf (diskoLib.subType { inherit (subTypes) zfs_fs zfs_volume; }); + # type = lib.types.attrsOf subTypes.zfs_fs; description = "List of datasets to define"; }; _meta = lib.mkOption { @@ -72,7 +73,7 @@ zpool list '${config.name}' >/dev/null 2>/dev/null || zpool import '${config.name}' ${lib.concatMapStrings (x: x.dev or "") (lib.attrValues datasetMounts)} ''; - fs = datasetMounts.fs // lib.optionalAttrs (config.mountpoint != null) { + fs = (datasetMounts.fs or {}) // lib.optionalAttrs (config.mountpoint != null) { ${config.mountpoint} = '' if ! findmnt ${config.name} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then mount ${config.name} "${rootMountPoint}${config.mountpoint}" \