diff --git a/example/complex.nix b/example/complex.nix index 58e215b..501de2a 100644 --- a/example/complex.nix +++ b/example/complex.nix @@ -163,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/zfs-over-legacy.nix b/example/zfs-over-legacy.nix index 25d0f02..2a5a2c6 100644 --- a/example/zfs-over-legacy.nix +++ b/example/zfs-over-legacy.nix @@ -50,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 3700018..4fd2bd9 100644 --- a/example/zfs.nix +++ b/example/zfs.nix @@ -64,21 +64,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"; @@ -87,8 +87,7 @@ }; }; encrypted = { - zfs_type = "filesystem"; - size = "20M"; + type = "zfs_fs"; options = { mountpoint = "none"; encryption = "aes-256-gcm"; @@ -97,8 +96,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 5f5eeec..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 @@ -348,6 +348,8 @@ rec { 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/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}" \