diff --git a/nixos/modules/tasks/storage/default.nix b/nixos/modules/tasks/storage/default.nix
index 6c971bc35995ca..39464dc200173d 100644
--- a/nixos/modules/tasks/storage/default.nix
+++ b/nixos/modules/tasks/storage/default.nix
@@ -75,6 +75,7 @@ let
orderableOptions = deviceSpec: {
options.before = storageLib.mkDeviceSpecOption {
typeContainer = types.listOf;
+ applyTypeContainer = map;
validDeviceTypes = [ deviceSpec.name ];
default = [];
description = ''
@@ -85,6 +86,7 @@ let
options.after = storageLib.mkDeviceSpecOption {
typeContainer = types.listOf;
+ applyTypeContainer = map;
validDeviceTypes = [ deviceSpec.name ];
default = [];
description = ''
@@ -114,6 +116,7 @@ let
devices = storageLib.mkDeviceSpecOption {
typeContainer = types.listOf;
+ applyTypeContainer = map;
validDeviceTypes = containerTypes;
description = ''
List of devices that will be part of this array.
@@ -124,6 +127,7 @@ let
volgroupOptions.options = {
devices = storageLib.mkDeviceSpecOption {
typeContainer = types.listOf;
+ applyTypeContainer = map;
validDeviceTypes = containerTypes;
description = ''
List of devices that will be part of this volume group.
@@ -143,6 +147,7 @@ let
btrfsOptions.options = {
devices = storageLib.mkDeviceSpecOption {
typeContainer = types.listOf;
+ applyTypeContainer = map;
validDeviceTypes = containerTypes;
description = ''
List of devices that will be part of this BTRFS volume.
@@ -258,6 +263,7 @@ in
options.storage = storageLib.mkDeviceSpecOption {
validDeviceTypes = containerTypes ++ [ "btrfs" ];
typeContainer = types.nullOr;
+ applyTypeContainer = fun: val: if val == null then null else fun val;
default = null;
example = "partition.root";
description = ''
@@ -279,6 +285,7 @@ in
options.storage = storageLib.mkDeviceSpecOption {
validDeviceTypes = containerTypes;
typeContainer = types.nullOr;
+ applyTypeContainer = fun: val: if val == null then null else fun val;
default = null;
example = "partition.swap";
description = ''
diff --git a/nixos/modules/tasks/storage/lib.nix b/nixos/modules/tasks/storage/lib.nix
index 9d8d1f521aa3ea..e3c3f4a6a35ba0 100644
--- a/nixos/modules/tasks/storage/lib.nix
+++ b/nixos/modules/tasks/storage/lib.nix
@@ -83,6 +83,17 @@ let
strAssertions = lib.concatStringsSep "\n" (assertions);
in if assertions == [] then true else builtins.trace strAssertions false;
+ /* Decode a device specification string like "partition.foo" into an attribute
+ * set consisting of the attributes `type' ("partition" here) and `name'
+ * ("foo" here).
+ */
+ decodeSpec = spec: let
+ typeAndName = builtins.match "([a-z]+)\\.([a-zA-Z0-9_-]+)" spec;
+ in if typeAndName == null then null else {
+ type = lib.head typeAndName;
+ name = lib.last typeAndName;
+ };
+
/* Validate the device specification and return true if it's valid or false if
* it's not.
*
@@ -99,14 +110,13 @@ let
invalidNameMsg =
"Device `${type}.${name}' does not exist in `config.storage.*'.";
syntaxError = builtins.trace syntaxErrorMsg false;
- typeAndName = builtins.match "([a-z]+)\\.([a-zA-Z0-9_-]+)" spec;
- type = lib.head typeAndName;
- name = lib.last typeAndName;
+ decoded = decodeSpec spec;
+ inherit (decoded) type name;
assertName = if (cfg.${type} or {}) ? ${name} then true
else builtins.trace invalidNameMsg false;
assertType = if lib.elem type validTypes then assertName
else builtins.trace invalidTypeMsg false;
- in if typeAndName == null then syntaxError else assertType;
+ in if decoded == null then syntaxError else assertType;
deviceSpecType = validTypes: lib.mkOptionType {
name = "deviceSpec";
@@ -127,13 +137,19 @@ in {
# wrap the deviceSpecType in any other container type in lib.types.
typeContainer = attrs.typeContainer or lib.id;
in typeContainer (deviceSpecType validDeviceTypes);
+ # `applyTypeContainer' is a function that's used to unpack the individual
+ # deviceSpecType from the typeContainer. So for example if typeContainer is
+ # `listOf', the applyTypeContainer function is "map".
+ apply = (attrs.applyTypeContainer or lib.id) decodeSpec;
description = attrs.description + ''
The device specification has to be in the form
<type>.<name> where type
is ${oneOf (attrs.validDeviceTypes or [])} and name is
the name in .
'';
- } // removeAttrs attrs [ "validDeviceTypes" "typeContainer" "description" ]);
+ } // removeAttrs attrs [
+ "validDeviceTypes" "typeContainer" "applyTypeContainer" "description"
+ ]);
types = {
size = lib.mkOptionType {