treewide: format all files
This commit is contained in:
143
cli.nix
143
cli.nix
@@ -1,12 +1,13 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, lib ? pkgs.lib
|
pkgs ? import <nixpkgs> { },
|
||||||
, mode ? "mount"
|
lib ? pkgs.lib,
|
||||||
, flake ? null
|
mode ? "mount",
|
||||||
, flakeAttr ? null
|
flake ? null,
|
||||||
, diskoFile ? null
|
flakeAttr ? null,
|
||||||
, rootMountPoint ? "/mnt"
|
diskoFile ? null,
|
||||||
, noDeps ? false
|
rootMountPoint ? "/mnt",
|
||||||
, ...
|
noDeps ? false,
|
||||||
|
...
|
||||||
}@args:
|
}@args:
|
||||||
let
|
let
|
||||||
disko = import ./. {
|
disko = import ./. {
|
||||||
@@ -17,66 +18,77 @@ let
|
|||||||
hasDiskoFile = diskoFile != null;
|
hasDiskoFile = diskoFile != null;
|
||||||
|
|
||||||
diskoAttr =
|
diskoAttr =
|
||||||
(if noDeps then
|
(
|
||||||
(if hasDiskoFile then
|
if noDeps then
|
||||||
{
|
(
|
||||||
destroy = "_cliDestroyNoDeps";
|
if hasDiskoFile then
|
||||||
format = "_cliFormatNoDeps";
|
{
|
||||||
mount = "_cliMountNoDeps";
|
destroy = "_cliDestroyNoDeps";
|
||||||
unmount = "_cliUnmountNoDeps";
|
format = "_cliFormatNoDeps";
|
||||||
|
mount = "_cliMountNoDeps";
|
||||||
|
unmount = "_cliUnmountNoDeps";
|
||||||
|
|
||||||
"format,mount" = "_cliFormatMountNoDeps";
|
"format,mount" = "_cliFormatMountNoDeps";
|
||||||
"destroy,format,mount" = "_cliDestroyFormatMountNoDeps";
|
"destroy,format,mount" = "_cliDestroyFormatMountNoDeps";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destroy = "destroyNoDeps";
|
||||||
|
format = "formatNoDeps";
|
||||||
|
mount = "mountNoDeps";
|
||||||
|
unmount = "unmountNoDeps";
|
||||||
|
|
||||||
|
"format,mount" = "formatMountNoDeps";
|
||||||
|
"destroy,format,mount" = "destroyFormatMountNoDeps";
|
||||||
|
}
|
||||||
|
)
|
||||||
|
// {
|
||||||
|
# legacy aliases
|
||||||
|
disko = "diskoScriptNoDeps";
|
||||||
|
create = "createScriptNoDeps";
|
||||||
|
zap_create_mount = "diskoScriptNoDeps";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
(
|
||||||
destroy = "destroyNoDeps";
|
if hasDiskoFile then
|
||||||
format = "formatNoDeps";
|
{
|
||||||
mount = "mountNoDeps";
|
destroy = "_cliDestroy";
|
||||||
unmount = "unmountNoDeps";
|
format = "_cliFormat";
|
||||||
|
mount = "_cliMount";
|
||||||
|
unmount = "_cliUnmount";
|
||||||
|
|
||||||
"format,mount" = "formatMountNoDeps";
|
"format,mount" = "_cliFormatMount";
|
||||||
"destroy,format,mount" = "destroyFormatMountNoDeps";
|
"destroy,format,mount" = "_cliDestroyFormatMount";
|
||||||
}) // {
|
}
|
||||||
# legacy aliases
|
else
|
||||||
disko = "diskoScriptNoDeps";
|
{
|
||||||
create = "createScriptNoDeps";
|
destroy = "destroy";
|
||||||
zap_create_mount = "diskoScriptNoDeps";
|
format = "format";
|
||||||
}
|
mount = "mount";
|
||||||
else
|
unmount = "unmount";
|
||||||
(if hasDiskoFile then
|
|
||||||
{
|
|
||||||
destroy = "_cliDestroy";
|
|
||||||
format = "_cliFormat";
|
|
||||||
mount = "_cliMount";
|
|
||||||
unmount = "_cliUnmount";
|
|
||||||
|
|
||||||
"format,mount" = "_cliFormatMount";
|
"format,mount" = "formatMount";
|
||||||
"destroy,format,mount" = "_cliDestroyFormatMount";
|
"destroy,format,mount" = "destroyFormatMount";
|
||||||
|
}
|
||||||
|
)
|
||||||
|
// {
|
||||||
|
# legacy aliases
|
||||||
|
disko = "diskoScript";
|
||||||
|
create = "createScript";
|
||||||
|
zap_create_mount = "diskoScript";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
destroy = "destroy";
|
|
||||||
format = "format";
|
|
||||||
mount = "mount";
|
|
||||||
unmount = "unmount";
|
|
||||||
|
|
||||||
"format,mount" = "formatMount";
|
|
||||||
"destroy,format,mount" = "destroyFormatMount";
|
|
||||||
}) // {
|
|
||||||
# legacy aliases
|
|
||||||
disko = "diskoScript";
|
|
||||||
create = "createScript";
|
|
||||||
zap_create_mount = "diskoScript";
|
|
||||||
}
|
|
||||||
).${mode};
|
).${mode};
|
||||||
|
|
||||||
hasDiskoConfigFlake =
|
hasDiskoConfigFlake =
|
||||||
hasDiskoFile || lib.hasAttrByPath [ "diskoConfigurations" flakeAttr ] (builtins.getFlake flake);
|
hasDiskoFile || lib.hasAttrByPath [ "diskoConfigurations" flakeAttr ] (builtins.getFlake flake);
|
||||||
|
|
||||||
hasDiskoModuleFlake =
|
hasDiskoModuleFlake = lib.hasAttrByPath [
|
||||||
lib.hasAttrByPath [ "nixosConfigurations" flakeAttr "config" "disko" "devices" ] (builtins.getFlake flake);
|
"nixosConfigurations"
|
||||||
|
flakeAttr
|
||||||
|
"config"
|
||||||
|
"disko"
|
||||||
|
"devices"
|
||||||
|
] (builtins.getFlake flake);
|
||||||
|
|
||||||
diskFormat =
|
diskFormat =
|
||||||
let
|
let
|
||||||
@@ -86,20 +98,16 @@ let
|
|||||||
else
|
else
|
||||||
(builtins.getFlake flake).diskoConfigurations.${flakeAttr};
|
(builtins.getFlake flake).diskoConfigurations.${flakeAttr};
|
||||||
in
|
in
|
||||||
if builtins.isFunction diskoConfig then
|
if builtins.isFunction diskoConfig then diskoConfig ({ inherit lib; } // args) else diskoConfig;
|
||||||
diskoConfig ({ inherit lib; } // args)
|
|
||||||
else
|
|
||||||
diskoConfig;
|
|
||||||
|
|
||||||
diskoEval =
|
diskoEval = disko.${diskoAttr} diskFormat pkgs;
|
||||||
disko.${diskoAttr} diskFormat pkgs;
|
|
||||||
|
|
||||||
diskoScript =
|
diskoScript =
|
||||||
if hasDiskoConfigFlake then
|
if hasDiskoConfigFlake then
|
||||||
diskoEval
|
diskoEval
|
||||||
else if hasDiskoModuleFlake then
|
else if hasDiskoModuleFlake then
|
||||||
(builtins.getFlake flake).nixosConfigurations.${flakeAttr}.config.system.build.${diskoAttr} or (
|
(builtins.getFlake flake).nixosConfigurations.${flakeAttr}.config.system.build.${diskoAttr}
|
||||||
pkgs.writeShellScriptBin "disko-compat-error" ''
|
or (pkgs.writeShellScriptBin "disko-compat-error" ''
|
||||||
echo 'Error: Attribute `nixosConfigurations.${flakeAttr}.config.system.build.${diskoAttr}` >&2
|
echo 'Error: Attribute `nixosConfigurations.${flakeAttr}.config.system.build.${diskoAttr}` >&2
|
||||||
echo ' not found in flake `${flake}`!' >&2
|
echo ' not found in flake `${flake}`!' >&2
|
||||||
echo ' This is probably caused by the locked version of disko in the flake' >&2
|
echo ' This is probably caused by the locked version of disko in the flake' >&2
|
||||||
@@ -107,8 +115,7 @@ let
|
|||||||
echo 'EITHER set the `disko` input of your flake to `github:nix-community/disko/latest`,' >&2
|
echo 'EITHER set the `disko` input of your flake to `github:nix-community/disko/latest`,' >&2
|
||||||
echo ' run `nix flake update disko` in the flake directory and then try again,' >&2
|
echo ' run `nix flake update disko` in the flake directory and then try again,' >&2
|
||||||
echo 'OR run `nix run github:nix-community/disko/v1.9.0 -- --help` and use one of its modes.' >&2
|
echo 'OR run `nix run github:nix-community/disko/v1.9.0 -- --help` and use one of its modes.' >&2
|
||||||
exit 1;''
|
exit 1;'')
|
||||||
)
|
|
||||||
else
|
else
|
||||||
(builtins.abort "couldn't find `diskoConfigurations.${flakeAttr}` or `nixosConfigurations.${flakeAttr}.config.disko.devices`");
|
(builtins.abort "couldn't find `diskoConfigurations.${flakeAttr}` or `nixosConfigurations.${flakeAttr}.config.disko.devices`");
|
||||||
|
|
||||||
|
107
default.nix
107
default.nix
@@ -1,64 +1,107 @@
|
|||||||
{ lib ? import <nixpkgs/lib>
|
{
|
||||||
, rootMountPoint ? "/mnt"
|
lib ? import <nixpkgs/lib>,
|
||||||
, checked ? false
|
rootMountPoint ? "/mnt",
|
||||||
, diskoLib ? import ./lib { inherit lib rootMountPoint; }
|
checked ? false,
|
||||||
|
diskoLib ? import ./lib { inherit lib rootMountPoint; },
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
eval = cfg: lib.evalModules {
|
eval =
|
||||||
modules = lib.singleton {
|
cfg:
|
||||||
# _file = toString input;
|
lib.evalModules {
|
||||||
imports = lib.singleton { disko.devices = cfg.disko.devices; };
|
modules = lib.singleton {
|
||||||
options = {
|
# _file = toString input;
|
||||||
disko.devices = lib.mkOption {
|
imports = lib.singleton { disko.devices = cfg.disko.devices; };
|
||||||
type = diskoLib.toplevel;
|
options = {
|
||||||
|
disko.devices = lib.mkOption {
|
||||||
|
type = diskoLib.toplevel;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
# We might instead reuse some of the deprecated output names to refer to the values the _cli* outputs currently do,
|
# We might instead reuse some of the deprecated output names to refer to the values the _cli* outputs currently do,
|
||||||
# but this warning allows us to get feedback from users early in case they have a use case we haven't considered.
|
# but this warning allows us to get feedback from users early in case they have a use case we haven't considered.
|
||||||
warnDeprecated = name: lib.warn "the ${name} output is deprecated and will be removed, please open an issue if you're using it!";
|
warnDeprecated =
|
||||||
|
name:
|
||||||
|
lib.warn "the ${name} output is deprecated and will be removed, please open an issue if you're using it!";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
lib = warnDeprecated ".lib.lib" diskoLib;
|
lib = warnDeprecated ".lib.lib" diskoLib;
|
||||||
|
|
||||||
_cliDestroy = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroy;
|
_cliDestroy =
|
||||||
_cliDestroyNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroyNoDeps;
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroy;
|
||||||
|
_cliDestroyNoDeps =
|
||||||
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroyNoDeps;
|
||||||
|
|
||||||
_cliFormat = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).format;
|
_cliFormat = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).format;
|
||||||
_cliFormatNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatNoDeps;
|
_cliFormatNoDeps =
|
||||||
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatNoDeps;
|
||||||
|
|
||||||
_cliMount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mount;
|
_cliMount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mount;
|
||||||
_cliMountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mountNoDeps;
|
_cliMountNoDeps =
|
||||||
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mountNoDeps;
|
||||||
|
|
||||||
_cliUnmount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).unmount;
|
_cliUnmount =
|
||||||
_cliUnmountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).unmountNoDeps;
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).unmount;
|
||||||
|
_cliUnmountNoDeps =
|
||||||
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).unmountNoDeps;
|
||||||
|
|
||||||
_cliFormatMount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatMount;
|
_cliFormatMount =
|
||||||
_cliFormatMountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatMountNoDeps;
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatMount;
|
||||||
|
_cliFormatMountNoDeps =
|
||||||
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatMountNoDeps;
|
||||||
|
|
||||||
_cliDestroyFormatMount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroyFormatMount;
|
_cliDestroyFormatMount =
|
||||||
_cliDestroyFormatMountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroyFormatMountNoDeps;
|
cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroyFormatMount;
|
||||||
|
_cliDestroyFormatMountNoDeps =
|
||||||
|
cfg: pkgs:
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroyFormatMountNoDeps;
|
||||||
|
|
||||||
# legacy aliases
|
# legacy aliases
|
||||||
create = cfg: warnDeprecated "create" (eval cfg).config.disko.devices._create;
|
create = cfg: warnDeprecated "create" (eval cfg).config.disko.devices._create;
|
||||||
createScript = cfg: pkgs: warnDeprecated "createScript" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScript;
|
createScript =
|
||||||
createScriptNoDeps = cfg: pkgs: warnDeprecated "createScriptNoDeps" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScriptNoDeps;
|
cfg: pkgs:
|
||||||
|
warnDeprecated "createScript"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScript;
|
||||||
|
createScriptNoDeps =
|
||||||
|
cfg: pkgs:
|
||||||
|
warnDeprecated "createScriptNoDeps"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScriptNoDeps;
|
||||||
|
|
||||||
format = cfg: warnDeprecated "format" (eval cfg).config.disko.devices._create;
|
format = cfg: warnDeprecated "format" (eval cfg).config.disko.devices._create;
|
||||||
formatScript = cfg: pkgs: warnDeprecated "formatScript" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScript;
|
formatScript =
|
||||||
formatScriptNoDeps = cfg: pkgs: warnDeprecated "formatScriptNoDeps" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScriptNoDeps;
|
cfg: pkgs:
|
||||||
|
warnDeprecated "formatScript"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScript;
|
||||||
|
formatScriptNoDeps =
|
||||||
|
cfg: pkgs:
|
||||||
|
warnDeprecated "formatScriptNoDeps"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScriptNoDeps;
|
||||||
|
|
||||||
mount = cfg: warnDeprecated "mount" (eval cfg).config.disko.devices._mount;
|
mount = cfg: warnDeprecated "mount" (eval cfg).config.disko.devices._mount;
|
||||||
mountScript = cfg: pkgs: warnDeprecated "mountScript" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mountScript;
|
mountScript =
|
||||||
mountScriptNoDeps = cfg: pkgs: warnDeprecated "mountScriptNoDeps" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mountScriptNoDeps;
|
cfg: pkgs:
|
||||||
|
warnDeprecated "mountScript"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mountScript;
|
||||||
|
mountScriptNoDeps =
|
||||||
|
cfg: pkgs:
|
||||||
|
warnDeprecated "mountScriptNoDeps"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mountScriptNoDeps;
|
||||||
|
|
||||||
disko = cfg: warnDeprecated "disko" (eval cfg).config.disko.devices._disko;
|
disko = cfg: warnDeprecated "disko" (eval cfg).config.disko.devices._disko;
|
||||||
diskoScript = cfg: pkgs: warnDeprecated "diskoScript" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).diskoScript;
|
diskoScript =
|
||||||
diskoScriptNoDeps = cfg: pkgs: warnDeprecated "diskoScriptNoDeps" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).diskoScriptNoDeps;
|
cfg: pkgs:
|
||||||
|
warnDeprecated "diskoScript"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).diskoScript;
|
||||||
|
diskoScriptNoDeps =
|
||||||
|
cfg: pkgs:
|
||||||
|
warnDeprecated "diskoScriptNoDeps"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).diskoScriptNoDeps;
|
||||||
|
|
||||||
# we keep this old output for backwards compatibility
|
# we keep this old output for backwards compatibility
|
||||||
diskoNoDeps = cfg: pkgs: warnDeprecated "diskoNoDeps" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).diskoScriptNoDeps;
|
diskoNoDeps =
|
||||||
|
cfg: pkgs:
|
||||||
|
warnDeprecated "diskoNoDeps"
|
||||||
|
((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).diskoScriptNoDeps;
|
||||||
|
|
||||||
config = cfg: (eval cfg).config.disko.devices._config;
|
config = cfg: (eval cfg).config.disko.devices._config;
|
||||||
packages = cfg: (eval cfg).config.disko.devices._packages;
|
packages = cfg: (eval cfg).config.disko.devices._packages;
|
||||||
|
28
doc.nix
28
doc.nix
@@ -1,4 +1,10 @@
|
|||||||
{ lib, nixosOptionsDoc, runCommand, fetchurl, pandoc }:
|
{
|
||||||
|
lib,
|
||||||
|
nixosOptionsDoc,
|
||||||
|
runCommand,
|
||||||
|
fetchurl,
|
||||||
|
pandoc,
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
diskoLib = import ./lib {
|
diskoLib = import ./lib {
|
||||||
@@ -21,16 +27,18 @@ let
|
|||||||
options = nixosOptionsDoc {
|
options = nixosOptionsDoc {
|
||||||
options = eval.options;
|
options = eval.options;
|
||||||
};
|
};
|
||||||
md = (runCommand "disko-options.md" { } ''
|
md =
|
||||||
cat >$out <<EOF
|
(runCommand "disko-options.md" { } ''
|
||||||
# Disko options
|
cat >$out <<EOF
|
||||||
|
# Disko options
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
cat ${options.optionsCommonMark} >>$out
|
cat ${options.optionsCommonMark} >>$out
|
||||||
'').overrideAttrs (_o: {
|
'').overrideAttrs
|
||||||
# Work around https://github.com/hercules-ci/hercules-ci-agent/issues/168
|
(_o: {
|
||||||
allowSubstitutes = true;
|
# Work around https://github.com/hercules-ci/hercules-ci-agent/issues/168
|
||||||
});
|
allowSubstitutes = true;
|
||||||
|
});
|
||||||
css = fetchurl {
|
css = fetchurl {
|
||||||
url = "https://gist.githubusercontent.com/killercup/5917178/raw/40840de5352083adb2693dc742e9f75dbb18650f/pandoc.css";
|
url = "https://gist.githubusercontent.com/killercup/5917178/raw/40840de5352083adb2693dc742e9f75dbb18650f/pandoc.css";
|
||||||
sha256 = "sha256-SzSvxBIrylxBF6B/mOImLlZ+GvCfpWNLzGFViLyOeTk=";
|
sha256 = "sha256-SzSvxBIrylxBF6B/mOImLlZ+GvCfpWNLzGFViLyOeTk=";
|
||||||
|
@@ -26,7 +26,10 @@
|
|||||||
type = "btrfs";
|
type = "btrfs";
|
||||||
extraArgs = [ "-f" ]; # Override existing partition
|
extraArgs = [ "-f" ]; # Override existing partition
|
||||||
mountpoint = "/";
|
mountpoint = "/";
|
||||||
mountOptions = [ "compress=zstd" "noatime" ];
|
mountOptions = [
|
||||||
|
"compress=zstd"
|
||||||
|
"noatime"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -35,4 +38,3 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,7 +41,10 @@
|
|||||||
"/home/user" = { };
|
"/home/user" = { };
|
||||||
# Parent is not mounted so the mountpoint must be set
|
# Parent is not mounted so the mountpoint must be set
|
||||||
"/nix" = {
|
"/nix" = {
|
||||||
mountOptions = [ "compress=zstd" "noatime" ];
|
mountOptions = [
|
||||||
|
"compress=zstd"
|
||||||
|
"noatime"
|
||||||
|
];
|
||||||
mountpoint = "/nix";
|
mountpoint = "/nix";
|
||||||
};
|
};
|
||||||
# This subvolume will be created but not mounted
|
# This subvolume will be created but not mounted
|
||||||
@@ -74,4 +77,3 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,4 +38,3 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,15 +35,24 @@
|
|||||||
subvolumes = {
|
subvolumes = {
|
||||||
"/root" = {
|
"/root" = {
|
||||||
mountpoint = "/";
|
mountpoint = "/";
|
||||||
mountOptions = [ "compress=zstd" "noatime" ];
|
mountOptions = [
|
||||||
|
"compress=zstd"
|
||||||
|
"noatime"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
"/home" = {
|
"/home" = {
|
||||||
mountpoint = "/home";
|
mountpoint = "/home";
|
||||||
mountOptions = [ "compress=zstd" "noatime" ];
|
mountOptions = [
|
||||||
|
"compress=zstd"
|
||||||
|
"noatime"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
"/nix" = {
|
"/nix" = {
|
||||||
mountpoint = "/nix";
|
mountpoint = "/nix";
|
||||||
mountOptions = [ "compress=zstd" "noatime" ];
|
mountOptions = [
|
||||||
|
"compress=zstd"
|
||||||
|
"noatime"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
"/swap" = {
|
"/swap" = {
|
||||||
mountpoint = "/.swapvol";
|
mountpoint = "/.swapvol";
|
||||||
|
@@ -56,4 +56,3 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
{ pkgs
|
{
|
||||||
, lib
|
pkgs,
|
||||||
, ...
|
lib,
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
# We just import from the repository for testing here:
|
# We just import from the repository for testing here:
|
||||||
|
@@ -1,5 +1,10 @@
|
|||||||
# Example to create a bios compatible gpt partition
|
# Example to create a bios compatible gpt partition
|
||||||
{ disks ? [ "/dev/vdb" ], lib, ... }: {
|
{
|
||||||
|
disks ? [ "/dev/vdb" ],
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
disko.devices = {
|
disko.devices = {
|
||||||
disk = lib.genAttrs disks (device: {
|
disk = lib.genAttrs disks (device: {
|
||||||
name = lib.replaceStrings [ "/" ] [ "_" ] device;
|
name = lib.replaceStrings [ "/" ] [ "_" ] device;
|
||||||
|
@@ -23,7 +23,10 @@
|
|||||||
type = "filesystem";
|
type = "filesystem";
|
||||||
format = "xfs";
|
format = "xfs";
|
||||||
mountpoint = "/";
|
mountpoint = "/";
|
||||||
mountOptions = [ "defaults" "pquota" ];
|
mountOptions = [
|
||||||
|
"defaults"
|
||||||
|
"pquota"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -251,14 +251,20 @@
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
mode = "mirror";
|
mode = "mirror";
|
||||||
members = [ "data2" "data3" ];
|
members = [
|
||||||
|
"data2"
|
||||||
|
"data3"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
spare = [ "spare" ];
|
spare = [ "spare" ];
|
||||||
log = [
|
log = [
|
||||||
{
|
{
|
||||||
mode = "mirror";
|
mode = "mirror";
|
||||||
members = [ "log1" "log2" ];
|
members = [
|
||||||
|
"log1"
|
||||||
|
"log2"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
members = [ "log3" ];
|
members = [ "log3" ];
|
||||||
@@ -267,7 +273,10 @@
|
|||||||
dedup = [
|
dedup = [
|
||||||
{
|
{
|
||||||
mode = "mirror";
|
mode = "mirror";
|
||||||
members = [ "dedup1" "dedup2" ];
|
members = [
|
||||||
|
"dedup1"
|
||||||
|
"dedup2"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
members = [ "dedup3" ];
|
members = [ "dedup3" ];
|
||||||
@@ -276,7 +285,10 @@
|
|||||||
special = [
|
special = [
|
||||||
{
|
{
|
||||||
mode = "mirror";
|
mode = "mirror";
|
||||||
members = [ "special1" "special2" ];
|
members = [
|
||||||
|
"special1"
|
||||||
|
"special2"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
members = [ "special3" ];
|
members = [ "special3" ];
|
||||||
|
50
flake.nix
50
flake.nix
@@ -6,7 +6,8 @@
|
|||||||
#inputs.nixpkgs.url = "nixpkgs";
|
#inputs.nixpkgs.url = "nixpkgs";
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
|
||||||
outputs = { self, nixpkgs, ... }:
|
outputs =
|
||||||
|
{ self, nixpkgs, ... }:
|
||||||
let
|
let
|
||||||
lib = nixpkgs.lib;
|
lib = nixpkgs.lib;
|
||||||
supportedSystems = [
|
supportedSystems = [
|
||||||
@@ -28,7 +29,8 @@
|
|||||||
nixosModules.default = self.nixosModules.disko; # convention
|
nixosModules.default = self.nixosModules.disko; # convention
|
||||||
nixosModules.disko = ./module.nix;
|
nixosModules.disko = ./module.nix;
|
||||||
lib = diskoLib;
|
lib = diskoLib;
|
||||||
packages = forAllSystems (system:
|
packages = forAllSystems (
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
in
|
in
|
||||||
@@ -41,27 +43,35 @@
|
|||||||
default = self.packages.${system}.disko;
|
default = self.packages.${system}.disko;
|
||||||
|
|
||||||
create-release = pkgs.callPackage ./scripts/create-release.nix { };
|
create-release = pkgs.callPackage ./scripts/create-release.nix { };
|
||||||
} // pkgs.lib.optionalAttrs (!pkgs.stdenv.buildPlatform.isRiscV64) {
|
}
|
||||||
|
// pkgs.lib.optionalAttrs (!pkgs.stdenv.buildPlatform.isRiscV64) {
|
||||||
disko-doc = pkgs.callPackage ./doc.nix { };
|
disko-doc = pkgs.callPackage ./doc.nix { };
|
||||||
});
|
}
|
||||||
|
);
|
||||||
# TODO: disable bios-related tests on aarch64...
|
# TODO: disable bios-related tests on aarch64...
|
||||||
# Run checks: nix flake check -L
|
# Run checks: nix flake check -L
|
||||||
checks = forAllSystems (system:
|
checks = forAllSystems (
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
# FIXME: aarch64-linux seems to hang on boot
|
# FIXME: aarch64-linux seems to hang on boot
|
||||||
nixosTests = lib.optionalAttrs pkgs.stdenv.hostPlatform.isx86_64 (import ./tests {
|
nixosTests = lib.optionalAttrs pkgs.stdenv.hostPlatform.isx86_64 (
|
||||||
inherit pkgs;
|
import ./tests {
|
||||||
makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix");
|
inherit pkgs;
|
||||||
eval-config = import (pkgs.path + "/nixos/lib/eval-config.nix");
|
makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix");
|
||||||
});
|
eval-config = import (pkgs.path + "/nixos/lib/eval-config.nix");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
disko-install = pkgs.callPackage ./tests/disko-install {
|
disko-install = pkgs.callPackage ./tests/disko-install {
|
||||||
inherit self;
|
inherit self;
|
||||||
diskoVersion = version;
|
diskoVersion = version;
|
||||||
};
|
};
|
||||||
|
|
||||||
jsonTypes = pkgs.writeTextFile { name = "jsonTypes"; text = (builtins.toJSON diskoLib.jsonTypes); };
|
jsonTypes = pkgs.writeTextFile {
|
||||||
|
name = "jsonTypes";
|
||||||
|
text = (builtins.toJSON diskoLib.jsonTypes);
|
||||||
|
};
|
||||||
|
|
||||||
treefmt = pkgs.runCommand "treefmt" { } ''
|
treefmt = pkgs.runCommand "treefmt" { } ''
|
||||||
${self.formatter.${system}}/bin/treefmt --ci --working-dir ${self}
|
${self.formatter.${system}}/bin/treefmt --ci --working-dir ${self}
|
||||||
@@ -69,11 +79,14 @@
|
|||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
# FIXME: aarch64-linux seems to hang on boot
|
# FIXME: aarch64-linux seems to hang on boot
|
||||||
lib.optionalAttrs pkgs.stdenv.hostPlatform.isx86_64 (nixosTests // { inherit disko-install; }) //
|
lib.optionalAttrs pkgs.stdenv.hostPlatform.isx86_64 (nixosTests // { inherit disko-install; })
|
||||||
pkgs.lib.optionalAttrs (!pkgs.stdenv.buildPlatform.isRiscV64 && !pkgs.stdenv.hostPlatform.isx86_32) {
|
//
|
||||||
inherit jsonTypes treefmt;
|
pkgs.lib.optionalAttrs (!pkgs.stdenv.buildPlatform.isRiscV64 && !pkgs.stdenv.hostPlatform.isx86_32)
|
||||||
inherit (self.packages.${system}) disko-doc;
|
{
|
||||||
});
|
inherit jsonTypes treefmt;
|
||||||
|
inherit (self.packages.${system}) disko-doc;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
nixosConfigurations.testmachine = lib.nixosSystem {
|
nixosConfigurations.testmachine = lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
@@ -83,7 +96,8 @@
|
|||||||
./module.nix
|
./module.nix
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
formatter = forAllSystems (system:
|
formatter = forAllSystems (
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
in
|
in
|
||||||
@@ -104,6 +118,6 @@
|
|||||||
self.formatter.${system}
|
self.formatter.${system}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
{ flake
|
{
|
||||||
, flakeAttr
|
flake,
|
||||||
, diskMappings
|
flakeAttr,
|
||||||
, extraSystemConfig ? "{}"
|
diskMappings,
|
||||||
, writeEfiBootEntries ? false
|
extraSystemConfig ? "{}",
|
||||||
, rootMountPoint ? "/mnt"
|
writeEfiBootEntries ? false,
|
||||||
,
|
rootMountPoint ? "/mnt",
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
originalSystem = (builtins.getFlake "${flake}").nixosConfigurations."${flakeAttr}";
|
originalSystem = (builtins.getFlake "${flake}").nixosConfigurations."${flakeAttr}";
|
||||||
@@ -17,21 +17,19 @@ let
|
|||||||
else
|
else
|
||||||
throw "No device passed for disk '${name}'. Pass `--disk ${name} /dev/name` via commandline";
|
throw "No device passed for disk '${name}'. Pass `--disk ${name} /dev/name` via commandline";
|
||||||
|
|
||||||
modifiedDisks = builtins.mapAttrs
|
modifiedDisks = builtins.mapAttrs (
|
||||||
(
|
name: value:
|
||||||
name: value:
|
let
|
||||||
let
|
dev = deviceName name;
|
||||||
dev = deviceName name;
|
in
|
||||||
in
|
value
|
||||||
value
|
// {
|
||||||
// {
|
device = dev;
|
||||||
device = dev;
|
content = value.content // {
|
||||||
content = value.content // {
|
device = dev;
|
||||||
device = dev;
|
};
|
||||||
};
|
}
|
||||||
}
|
) originalSystem.config.disko.devices.disk;
|
||||||
)
|
|
||||||
originalSystem.config.disko.devices.disk;
|
|
||||||
|
|
||||||
# filter all nixos module internal attributes
|
# filter all nixos module internal attributes
|
||||||
cleanedDisks = lib.filterAttrsRecursive (n: _: !lib.hasPrefix "_" n) modifiedDisks;
|
cleanedDisks = lib.filterAttrsRecursive (n: _: !lib.hasPrefix "_" n) modifiedDisks;
|
||||||
|
@@ -1,25 +1,33 @@
|
|||||||
{ lib, diskoLib, pkgs, imagePkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
pkgs,
|
||||||
|
imagePkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
# from https://github.com/NixOS/nixpkgs/blob/851f7fc119e9597c26cc43e10938ce7272d0af9d/nixos/modules/system/boot/binfmt.nix
|
# from https://github.com/NixOS/nixpkgs/blob/851f7fc119e9597c26cc43e10938ce7272d0af9d/nixos/modules/system/boot/binfmt.nix
|
||||||
makeBinfmtLine =
|
makeBinfmtLine =
|
||||||
{ name
|
{
|
||||||
, recognitionType
|
name,
|
||||||
, offset
|
recognitionType,
|
||||||
, magicOrExtension
|
offset,
|
||||||
, mask
|
magicOrExtension,
|
||||||
, preserveArgvZero
|
mask,
|
||||||
, openBinary
|
preserveArgvZero,
|
||||||
, matchCredentials
|
openBinary,
|
||||||
, fixBinary
|
matchCredentials,
|
||||||
, interpreter
|
fixBinary,
|
||||||
, ...
|
interpreter,
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
type = if recognitionType == "magic" then "M" else "E";
|
type = if recognitionType == "magic" then "M" else "E";
|
||||||
offset' = toString offset;
|
offset' = toString offset;
|
||||||
mask' = toString mask;
|
mask' = toString mask;
|
||||||
flags = with lib;
|
flags =
|
||||||
|
with lib;
|
||||||
if !(matchCredentials -> openBinary) then
|
if !(matchCredentials -> openBinary) then
|
||||||
throw "boot.binfmt.registrations.${name}: you can't specify openBinary = false when matchCredentials = true."
|
throw "boot.binfmt.registrations.${name}: you can't specify openBinary = false when matchCredentials = true."
|
||||||
else
|
else
|
||||||
@@ -144,29 +152,30 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
binfmtRegistration =
|
binfmtRegistration =
|
||||||
let
|
let
|
||||||
system = imagePkgs.stdenv.hostPlatform.system;
|
system = imagePkgs.stdenv.hostPlatform.system;
|
||||||
enabled = system != pkgs.stdenv.hostPlatform.system;
|
enabled = system != pkgs.stdenv.hostPlatform.system;
|
||||||
elaborated = lib.systems.elaborate { inherit system; };
|
elaborated = lib.systems.elaborate { inherit system; };
|
||||||
useStaticEmulator = true; # needed for chroot
|
useStaticEmulator = true; # needed for chroot
|
||||||
interpreter = elaborated.emulator (if useStaticEmulator then pkgs.pkgsStatic else pkgs);
|
interpreter = elaborated.emulator (if useStaticEmulator then pkgs.pkgsStatic else pkgs);
|
||||||
|
|
||||||
inherit (elaborated) qemuArch;
|
inherit (elaborated) qemuArch;
|
||||||
isQemu = "qemu-${qemuArch}" == baseNameOf interpreter;
|
isQemu = "qemu-${qemuArch}" == baseNameOf interpreter;
|
||||||
in makeBinfmtLine (
|
in
|
||||||
{
|
makeBinfmtLine (
|
||||||
name = system;
|
{
|
||||||
inherit interpreter;
|
name = system;
|
||||||
recognitionType = "magic";
|
inherit interpreter;
|
||||||
offset = null;
|
recognitionType = "magic";
|
||||||
openBinary = false;
|
offset = null;
|
||||||
matchCredentials = false;
|
openBinary = false;
|
||||||
|
matchCredentials = false;
|
||||||
|
|
||||||
preserveArgvZero = isQemu;
|
preserveArgvZero = isQemu;
|
||||||
|
|
||||||
fixBinary = useStaticEmulator;
|
fixBinary = useStaticEmulator;
|
||||||
}
|
}
|
||||||
// (magics.${system} or (throw "Cannot create binfmt registration for system ${system}"))
|
// (magics.${system} or (throw "Cannot create binfmt registration for system ${system}"))
|
||||||
);
|
);
|
||||||
systemsAreDifferent = imagePkgs.stdenv.hostPlatform.system != pkgs.stdenv.hostPlatform.system;
|
systemsAreDifferent = imagePkgs.stdenv.hostPlatform.system != pkgs.stdenv.hostPlatform.system;
|
||||||
}
|
}
|
||||||
|
891
lib/default.nix
891
lib/default.nix
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,30 @@
|
|||||||
{ diskoLib, modulesPath, config, pkgs, lib, ... }:
|
{
|
||||||
|
diskoLib,
|
||||||
|
modulesPath,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
vm_disko = (diskoLib.testLib.prepareDiskoConfig config diskoLib.testLib.devices).disko;
|
vm_disko = (diskoLib.testLib.prepareDiskoConfig config diskoLib.testLib.devices).disko;
|
||||||
cfg_ = (lib.evalModules {
|
cfg_ =
|
||||||
modules = lib.singleton {
|
(lib.evalModules {
|
||||||
# _file = toString input;
|
modules = lib.singleton {
|
||||||
imports = lib.singleton { disko.devices = vm_disko.devices; };
|
# _file = toString input;
|
||||||
options = {
|
imports = lib.singleton { disko.devices = vm_disko.devices; };
|
||||||
disko.devices = lib.mkOption {
|
options = {
|
||||||
type = diskoLib.toplevel;
|
disko.devices = lib.mkOption {
|
||||||
};
|
type = diskoLib.toplevel;
|
||||||
disko.testMode = lib.mkOption {
|
};
|
||||||
type = lib.types.bool;
|
disko.testMode = lib.mkOption {
|
||||||
default = true;
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
}).config;
|
||||||
}).config;
|
|
||||||
disks = lib.attrValues cfg_.disko.devices.disk;
|
disks = lib.attrValues cfg_.disko.devices.disk;
|
||||||
rootDisk = {
|
rootDisk = {
|
||||||
name = "root";
|
name = "root";
|
||||||
@@ -26,13 +34,11 @@ let
|
|||||||
deviceExtraOpts.bootindex = "1";
|
deviceExtraOpts.bootindex = "1";
|
||||||
deviceExtraOpts.serial = "root";
|
deviceExtraOpts.serial = "root";
|
||||||
};
|
};
|
||||||
otherDisks = map
|
otherDisks = map (disk: {
|
||||||
(disk: {
|
name = disk.name;
|
||||||
name = disk.name;
|
file = ''"$tmp"/${lib.escapeShellArg disk.name}.qcow2'';
|
||||||
file = ''"$tmp"/${lib.escapeShellArg disk.name}.qcow2'';
|
driveExtraOpts.werror = "report";
|
||||||
driveExtraOpts.werror = "report";
|
}) (builtins.tail disks);
|
||||||
})
|
|
||||||
(builtins.tail disks);
|
|
||||||
|
|
||||||
diskoBasedConfiguration = {
|
diskoBasedConfiguration = {
|
||||||
# generated from disko config
|
# generated from disko config
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
{ config
|
{
|
||||||
, diskoLib
|
config,
|
||||||
, lib
|
diskoLib,
|
||||||
, extendModules
|
lib,
|
||||||
, options
|
extendModules,
|
||||||
, imagePkgs
|
options,
|
||||||
, ...
|
imagePkgs,
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
diskoCfg = config.disko;
|
diskoCfg = config.disko;
|
||||||
@@ -13,33 +14,45 @@ let
|
|||||||
checked = diskoCfg.checkScripts;
|
checked = diskoCfg.checkScripts;
|
||||||
|
|
||||||
configSupportsZfs = config.boot.supportedFilesystems.zfs or false;
|
configSupportsZfs = config.boot.supportedFilesystems.zfs or false;
|
||||||
binfmt = diskoLib.binfmt { inherit diskoLib lib pkgs imagePkgs; };
|
binfmt = diskoLib.binfmt {
|
||||||
|
inherit
|
||||||
|
diskoLib
|
||||||
|
lib
|
||||||
|
pkgs
|
||||||
|
imagePkgs
|
||||||
|
;
|
||||||
|
};
|
||||||
binfmtSetup = lib.optionalString (cfg.enableBinfmt && binfmt.systemsAreDifferent) ''
|
binfmtSetup = lib.optionalString (cfg.enableBinfmt && binfmt.systemsAreDifferent) ''
|
||||||
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
||||||
${pkgs.systemdMinimal}/lib/systemd/systemd-binfmt <(echo ${lib.strings.escapeShellArg binfmt.binfmtRegistration})
|
${pkgs.systemdMinimal}/lib/systemd/systemd-binfmt <(echo ${lib.strings.escapeShellArg binfmt.binfmtRegistration})
|
||||||
'';
|
'';
|
||||||
|
|
||||||
vmTools = pkgs.vmTools.override
|
vmTools = pkgs.vmTools.override (
|
||||||
({
|
{
|
||||||
rootModules = [
|
rootModules =
|
||||||
"9p" "9pnet_virtio" # we can drop those in future if we stop supporting 24.11
|
[
|
||||||
|
"9p"
|
||||||
|
"9pnet_virtio" # we can drop those in future if we stop supporting 24.11
|
||||||
|
|
||||||
"virtiofs"
|
"virtiofs"
|
||||||
"virtio_pci"
|
"virtio_pci"
|
||||||
"virtio_blk"
|
"virtio_blk"
|
||||||
"virtio_balloon"
|
"virtio_balloon"
|
||||||
"virtio_rng"
|
"virtio_rng"
|
||||||
]
|
]
|
||||||
++ (lib.optional configSupportsZfs "zfs")
|
++ (lib.optional configSupportsZfs "zfs")
|
||||||
++ cfg.extraRootModules;
|
++ cfg.extraRootModules;
|
||||||
kernel = pkgs.aggregateModules
|
kernel = pkgs.aggregateModules (
|
||||||
([ cfg.kernelPackages.kernel ]
|
[ cfg.kernelPackages.kernel ]
|
||||||
++ lib.optional (lib.elem "zfs" cfg.extraRootModules || configSupportsZfs) cfg.kernelPackages.${config.boot.zfs.package.kernelModuleAttribute});
|
++ lib.optional (
|
||||||
|
lib.elem "zfs" cfg.extraRootModules || configSupportsZfs
|
||||||
|
) cfg.kernelPackages.${config.boot.zfs.package.kernelModuleAttribute}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (diskoLib.vmToolsSupportsCustomQemu lib)
|
// lib.optionalAttrs (diskoLib.vmToolsSupportsCustomQemu lib) {
|
||||||
{
|
|
||||||
customQemu = cfg.qemu;
|
customQemu = cfg.qemu;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
cleanedConfig = diskoLib.testLib.prepareDiskoConfig config diskoLib.testLib.devices;
|
cleanedConfig = diskoLib.testLib.prepareDiskoConfig config diskoLib.testLib.devices;
|
||||||
systemToInstall = extendModules {
|
systemToInstall = extendModules {
|
||||||
modules = [
|
modules = [
|
||||||
@@ -51,34 +64,41 @@ let
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
systemToInstallNative = if binfmt.systemsAreDifferent then extendModules {
|
systemToInstallNative =
|
||||||
modules = [
|
if binfmt.systemsAreDifferent then
|
||||||
cfg.extraConfig
|
extendModules {
|
||||||
{
|
modules = [
|
||||||
disko.testMode = true;
|
cfg.extraConfig
|
||||||
disko.devices = lib.mkForce cleanedConfig.disko.devices;
|
{
|
||||||
boot.loader.grub.devices = lib.mkForce cleanedConfig.boot.loader.grub.devices;
|
disko.testMode = true;
|
||||||
nixpkgs.hostPlatform = lib.mkForce pkgs.stdenv.hostPlatform;
|
disko.devices = lib.mkForce cleanedConfig.disko.devices;
|
||||||
|
boot.loader.grub.devices = lib.mkForce cleanedConfig.boot.loader.grub.devices;
|
||||||
|
nixpkgs.hostPlatform = lib.mkForce pkgs.stdenv.hostPlatform;
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
];
|
else
|
||||||
}
|
systemToInstall;
|
||||||
else systemToInstall;
|
dependencies =
|
||||||
dependencies = with pkgs; [
|
with pkgs;
|
||||||
bash
|
[
|
||||||
coreutils
|
bash
|
||||||
gnused
|
coreutils
|
||||||
parted # for partprobe
|
gnused
|
||||||
systemdMinimal
|
parted # for partprobe
|
||||||
nix
|
systemdMinimal
|
||||||
util-linux
|
nix
|
||||||
findutils
|
util-linux
|
||||||
kmod
|
findutils
|
||||||
] ++ cfg.extraDependencies;
|
kmod
|
||||||
|
]
|
||||||
|
++ cfg.extraDependencies;
|
||||||
preVM = ''
|
preVM = ''
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
mkdir -p "$out"
|
mkdir -p "$out"
|
||||||
${lib.concatMapStringsSep "\n" (disk:
|
${lib.concatMapStringsSep "\n" (
|
||||||
# shellcheck disable=SC2154
|
disk:
|
||||||
|
# shellcheck disable=SC2154
|
||||||
"${pkgs.qemu}/bin/qemu-img create -f ${imageFormat} \"$out/${disk.imageName}.${imageFormat}\" ${disk.imageSize}"
|
"${pkgs.qemu}/bin/qemu-img create -f ${imageFormat} \"$out/${disk.imageName}.${imageFormat}\" ${disk.imageSize}"
|
||||||
) (lib.attrValues diskoCfg.devices.disk)}
|
) (lib.attrValues diskoCfg.devices.disk)}
|
||||||
# This makes disko work, when canTouchEfiVariables is set to true.
|
# This makes disko work, when canTouchEfiVariables is set to true.
|
||||||
@@ -127,24 +147,26 @@ let
|
|||||||
umount -Rv ${systemToInstall.config.disko.rootMountPoint}
|
umount -Rv ${systemToInstall.config.disko.rootMountPoint}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
QEMU_OPTS = lib.concatStringsSep " " ([
|
QEMU_OPTS = lib.concatStringsSep " " (
|
||||||
"-drive if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware}"
|
[
|
||||||
"-drive if=pflash,format=raw,unit=1,file=efivars.fd"
|
"-drive if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware}"
|
||||||
] ++ builtins.map
|
"-drive if=pflash,format=raw,unit=1,file=efivars.fd"
|
||||||
(disk:
|
]
|
||||||
|
++ builtins.map (
|
||||||
|
disk:
|
||||||
"-drive file=\"$out\"/${disk.imageName}.${imageFormat},if=virtio,cache=unsafe,werror=report,format=${imageFormat}"
|
"-drive file=\"$out\"/${disk.imageName}.${imageFormat},if=virtio,cache=unsafe,werror=report,format=${imageFormat}"
|
||||||
)
|
) (lib.attrValues diskoCfg.devices.disk)
|
||||||
(lib.attrValues diskoCfg.devices.disk));
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
system.build.diskoImages = vmTools.runInLinuxVM (pkgs.runCommand cfg.name
|
system.build.diskoImages = vmTools.runInLinuxVM (
|
||||||
{
|
pkgs.runCommand cfg.name {
|
||||||
buildInputs = dependencies;
|
buildInputs = dependencies;
|
||||||
inherit preVM QEMU_OPTS;
|
inherit preVM QEMU_OPTS;
|
||||||
postVM = cfg.extraPostVM;
|
postVM = cfg.extraPostVM;
|
||||||
inherit (diskoCfg) memSize;
|
inherit (diskoCfg) memSize;
|
||||||
}
|
} (binfmtSetup + partitioner + installer)
|
||||||
(binfmtSetup + partitioner + installer));
|
);
|
||||||
|
|
||||||
system.build.diskoImagesScript = diskoLib.writeCheckedBash { inherit checked pkgs; } cfg.name ''
|
system.build.diskoImagesScript = diskoLib.writeCheckedBash { inherit checked pkgs; } cfg.name ''
|
||||||
set -efu
|
set -efu
|
||||||
@@ -209,32 +231,34 @@ in
|
|||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
export preVM=${diskoLib.writeCheckedBash { inherit pkgs checked; } "preVM.sh" ''
|
export preVM=${
|
||||||
set -efu
|
diskoLib.writeCheckedBash { inherit pkgs checked; } "preVM.sh" ''
|
||||||
mv copy_before_disko copy_after_disko xchg/
|
set -efu
|
||||||
origBuilder=${pkgs.writeScript "disko-builder" ''
|
mv copy_before_disko copy_after_disko xchg/
|
||||||
set -eu
|
origBuilder=${pkgs.writeScript "disko-builder" ''
|
||||||
export PATH=${lib.makeBinPath dependencies}
|
set -eu
|
||||||
for src in /tmp/xchg/copy_before_disko/*; do
|
export PATH=${lib.makeBinPath dependencies}
|
||||||
[ -e "$src" ] || continue
|
for src in /tmp/xchg/copy_before_disko/*; do
|
||||||
dst=$(basename "$src" | base64 -d)
|
[ -e "$src" ] || continue
|
||||||
mkdir -p "$(dirname "$dst")"
|
dst=$(basename "$src" | base64 -d)
|
||||||
cp -r "$src" "$dst"
|
mkdir -p "$(dirname "$dst")"
|
||||||
done
|
cp -r "$src" "$dst"
|
||||||
set -f
|
done
|
||||||
${partitioner}
|
set -f
|
||||||
set +f
|
${partitioner}
|
||||||
for src in /tmp/xchg/copy_after_disko/*; do
|
set +f
|
||||||
[ -e "$src" ] || continue
|
for src in /tmp/xchg/copy_after_disko/*; do
|
||||||
dst=/mnt/$(basename "$src" | base64 -d)
|
[ -e "$src" ] || continue
|
||||||
mkdir -p "$(dirname "$dst")"
|
dst=/mnt/$(basename "$src" | base64 -d)
|
||||||
cp -r "$src" "$dst"
|
mkdir -p "$(dirname "$dst")"
|
||||||
done
|
cp -r "$src" "$dst"
|
||||||
${installer}
|
done
|
||||||
''}
|
${installer}
|
||||||
echo "export origBuilder=$origBuilder" >> xchg/saved-env
|
''}
|
||||||
${preVM}
|
echo "export origBuilder=$origBuilder" >> xchg/saved-env
|
||||||
''}
|
${preVM}
|
||||||
|
''
|
||||||
|
}
|
||||||
export postVM=${diskoLib.writeCheckedBash { inherit pkgs checked; } "postVM.sh" cfg.extraPostVM}
|
export postVM=${diskoLib.writeCheckedBash { inherit pkgs checked; } "postVM.sh" cfg.extraPostVM}
|
||||||
|
|
||||||
build_memory=''${build_memory:-${builtins.toString diskoCfg.memSize}}
|
build_memory=''${build_memory:-${builtins.toString diskoCfg.memSize}}
|
||||||
|
527
lib/tests.nix
527
lib/tests.nix
@@ -1,37 +1,48 @@
|
|||||||
{ lib
|
{
|
||||||
, makeTest
|
lib,
|
||||||
, eval-config
|
makeTest,
|
||||||
, ...
|
eval-config,
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
testLib = {
|
testLib = {
|
||||||
# this takes a nixos config and changes the disk devices so we can run them inside the qemu test runner
|
# this takes a nixos config and changes the disk devices so we can run them inside the qemu test runner
|
||||||
# basically changes all the disk.*.devices to something like /dev/vda or /dev/vdb etc.
|
# basically changes all the disk.*.devices to something like /dev/vda or /dev/vdb etc.
|
||||||
prepareDiskoConfig = cfg: devices:
|
prepareDiskoConfig =
|
||||||
|
cfg: devices:
|
||||||
let
|
let
|
||||||
cleanedTopLevel = lib.filterAttrsRecursive (n: _: !lib.hasPrefix "_" n) cfg;
|
cleanedTopLevel = lib.filterAttrsRecursive (n: _: !lib.hasPrefix "_" n) cfg;
|
||||||
|
|
||||||
preparedDisks = lib.foldlAttrs
|
preparedDisks =
|
||||||
(acc: n: v: {
|
lib.foldlAttrs
|
||||||
devices = lib.tail acc.devices;
|
(acc: n: v: {
|
||||||
grub-devices = acc.grub-devices ++ (lib.optional (lib.any (part: (part.type or "") == "EF02") (lib.attrValues (v.content.partitions or { }))) (lib.head acc.devices));
|
devices = lib.tail acc.devices;
|
||||||
disks = acc.disks // {
|
grub-devices =
|
||||||
"${n}" = v // {
|
acc.grub-devices
|
||||||
device = lib.head acc.devices;
|
++ (lib.optional (lib.any (part: (part.type or "") == "EF02") (
|
||||||
content = v.content // { device = lib.head acc.devices; };
|
lib.attrValues (v.content.partitions or { })
|
||||||
|
)) (lib.head acc.devices));
|
||||||
|
disks = acc.disks // {
|
||||||
|
"${n}" = v // {
|
||||||
|
device = lib.head acc.devices;
|
||||||
|
content = v.content // {
|
||||||
|
device = lib.head acc.devices;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
})
|
||||||
})
|
{
|
||||||
{
|
inherit devices;
|
||||||
inherit devices;
|
grub-devices = [ ];
|
||||||
grub-devices = [ ];
|
disks = { };
|
||||||
disks = { };
|
}
|
||||||
}
|
cleanedTopLevel.disko.devices.disk;
|
||||||
cleanedTopLevel.disko.devices.disk;
|
|
||||||
in
|
in
|
||||||
cleanedTopLevel // {
|
cleanedTopLevel
|
||||||
boot.loader.grub.devices = if (preparedDisks.grub-devices != [ ]) then preparedDisks.grub-devices else [ "nodev" ];
|
// {
|
||||||
|
boot.loader.grub.devices =
|
||||||
|
if (preparedDisks.grub-devices != [ ]) then preparedDisks.grub-devices else [ "nodev" ];
|
||||||
disko.devices = cleanedTopLevel.disko.devices // {
|
disko.devices = cleanedTopLevel.disko.devices // {
|
||||||
disk = preparedDisks.disks;
|
disk = preparedDisks.disks;
|
||||||
};
|
};
|
||||||
@@ -58,33 +69,31 @@ let
|
|||||||
|
|
||||||
# This is the test generator for a disko test
|
# This is the test generator for a disko test
|
||||||
makeDiskoTest =
|
makeDiskoTest =
|
||||||
{ name
|
{
|
||||||
, disko-config
|
name,
|
||||||
, extendModules ? null
|
disko-config,
|
||||||
, pkgs ? import <nixpkgs> { }
|
extendModules ? null,
|
||||||
, extraTestScript ? ""
|
pkgs ? import <nixpkgs> { },
|
||||||
, bootCommands ? ""
|
extraTestScript ? "",
|
||||||
, extraInstallerConfig ? { }
|
bootCommands ? "",
|
||||||
, extraSystemConfig ? { }
|
extraInstallerConfig ? { },
|
||||||
, efi ? !pkgs.stdenv.hostPlatform.isRiscV64
|
extraSystemConfig ? { },
|
||||||
, postDisko ? ""
|
efi ? !pkgs.stdenv.hostPlatform.isRiscV64,
|
||||||
, testMode ? "module" # can be one of direct module cli
|
postDisko ? "",
|
||||||
, testBoot ? true # if we actually want to test booting or just create/mount
|
testMode ? "module", # can be one of direct module cli
|
||||||
, enableOCR ? false
|
testBoot ? true, # if we actually want to test booting or just create/mount
|
||||||
|
enableOCR ? false,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
makeTest' = args:
|
makeTest' =
|
||||||
|
args:
|
||||||
makeTest args {
|
makeTest args {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
inherit (pkgs) system;
|
inherit (pkgs) system;
|
||||||
};
|
};
|
||||||
# for installation we skip /dev/vda because it is the test runner disk
|
# for installation we skip /dev/vda because it is the test runner disk
|
||||||
|
|
||||||
importedDiskoConfig =
|
importedDiskoConfig = if builtins.isPath disko-config then import disko-config else disko-config;
|
||||||
if builtins.isPath disko-config then
|
|
||||||
import disko-config
|
|
||||||
else
|
|
||||||
disko-config;
|
|
||||||
|
|
||||||
diskoConfigWithArgs =
|
diskoConfigWithArgs =
|
||||||
if builtins.isFunction importedDiskoConfig then
|
if builtins.isFunction importedDiskoConfig then
|
||||||
@@ -104,79 +113,93 @@ let
|
|||||||
tsp-config = tsp-generator.config testConfigBooted;
|
tsp-config = tsp-generator.config testConfigBooted;
|
||||||
num-disks = builtins.length (lib.attrNames testConfigBooted.disko.devices.disk);
|
num-disks = builtins.length (lib.attrNames testConfigBooted.disko.devices.disk);
|
||||||
|
|
||||||
installed-system = { config, ... }: {
|
installed-system =
|
||||||
imports = [
|
{ config, ... }:
|
||||||
(lib.optionalAttrs (testMode == "direct") tsp-config)
|
{
|
||||||
(lib.optionalAttrs (testMode == "module") {
|
imports = [
|
||||||
disko.enableConfig = true;
|
(lib.optionalAttrs (testMode == "direct") tsp-config)
|
||||||
imports = [
|
(lib.optionalAttrs (testMode == "module") {
|
||||||
../module.nix
|
disko.enableConfig = true;
|
||||||
testConfigBooted
|
imports = [
|
||||||
];
|
../module.nix
|
||||||
})
|
testConfigBooted
|
||||||
];
|
];
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
# config for tests to make them run faster or work at all
|
# config for tests to make them run faster or work at all
|
||||||
documentation.enable = false;
|
documentation.enable = false;
|
||||||
hardware.enableAllFirmware = lib.mkForce false;
|
hardware.enableAllFirmware = lib.mkForce false;
|
||||||
# FIXME: we don't have an systemd in stage-1 equialvent for this
|
# FIXME: we don't have an systemd in stage-1 equialvent for this
|
||||||
boot.initrd.preDeviceCommands = lib.mkIf (!config.boot.initrd.systemd.enable) ''
|
boot.initrd.preDeviceCommands = lib.mkIf (!config.boot.initrd.systemd.enable) ''
|
||||||
echo -n 'secretsecret' > /tmp/secret.key
|
echo -n 'secretsecret' > /tmp/secret.key
|
||||||
'';
|
'';
|
||||||
boot.consoleLogLevel = lib.mkForce 100;
|
boot.consoleLogLevel = lib.mkForce 100;
|
||||||
boot.loader.systemd-boot.enable = lib.mkDefault efi;
|
boot.loader.systemd-boot.enable = lib.mkDefault efi;
|
||||||
};
|
};
|
||||||
|
|
||||||
installed-system-eval = eval-config {
|
installed-system-eval = eval-config {
|
||||||
modules = [ installed-system ];
|
modules = [ installed-system ];
|
||||||
inherit (pkgs) system;
|
inherit (pkgs) system;
|
||||||
};
|
};
|
||||||
|
|
||||||
installedTopLevel = ((if extendModules != null then extendModules else installed-system-eval.extendModules) {
|
installedTopLevel =
|
||||||
modules = [
|
((if extendModules != null then extendModules else installed-system-eval.extendModules) {
|
||||||
({ config, ... }: {
|
modules = [
|
||||||
imports = [
|
(
|
||||||
extraSystemConfig
|
{ config, ... }:
|
||||||
({ modulesPath, ... }: {
|
|
||||||
imports = [
|
|
||||||
(modulesPath + "/testing/test-instrumentation.nix") # we need these 2 modules always to be able to run the tests
|
|
||||||
(modulesPath + "/profiles/qemu-guest.nix")
|
|
||||||
];
|
|
||||||
disko.devices = lib.mkForce testConfigBooted.disko.devices;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
# since we boot on a different machine, the efi payload needs to be portable
|
|
||||||
boot.loader.grub.efiInstallAsRemovable = efi;
|
|
||||||
boot.loader.grub.efiSupport = efi;
|
|
||||||
boot.loader.systemd-boot.graceful = true;
|
|
||||||
|
|
||||||
# we always want the bind-mounted nix store. otherwise tests take forever
|
|
||||||
fileSystems."/nix/store" = lib.mkForce {
|
|
||||||
device = "nix-store";
|
|
||||||
fsType = "9p";
|
|
||||||
neededForBoot = true;
|
|
||||||
options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
|
|
||||||
};
|
|
||||||
boot.zfs.devNodes = "/dev/disk/by-uuid"; # needed because /dev/disk/by-id is empty in qemu-vms
|
|
||||||
|
|
||||||
# grub will install to these devices, we need to force those or we are offset by 1
|
|
||||||
# we use mkOveride 70, so that users can override this with mkForce in case they are testing grub mirrored boots
|
|
||||||
boot.loader.grub.devices = lib.mkOverride 70 testConfigInstall.boot.loader.grub.devices;
|
|
||||||
|
|
||||||
assertions = [
|
|
||||||
{
|
{
|
||||||
assertion = builtins.length config.boot.loader.grub.mirroredBoots > 1 -> config.boot.loader.grub.devices == [ ];
|
imports = [
|
||||||
message = ''
|
extraSystemConfig
|
||||||
When using `--vm-test` in combination with `mirroredBoots`,
|
(
|
||||||
it is necessary to configure `boot.loader.grub.devices` as an empty list by setting `boot.loader.grub.devices = lib.mkForce [];`.
|
{ modulesPath, ... }:
|
||||||
This adjustment is crucial because the `--vm-test` mechanism automatically overrides the grub boot devices as part of the virtual machine test.
|
{
|
||||||
'';
|
imports = [
|
||||||
|
(modulesPath + "/testing/test-instrumentation.nix") # we need these 2 modules always to be able to run the tests
|
||||||
|
(modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
];
|
||||||
|
disko.devices = lib.mkForce testConfigBooted.disko.devices;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
# since we boot on a different machine, the efi payload needs to be portable
|
||||||
|
boot.loader.grub.efiInstallAsRemovable = efi;
|
||||||
|
boot.loader.grub.efiSupport = efi;
|
||||||
|
boot.loader.systemd-boot.graceful = true;
|
||||||
|
|
||||||
|
# we always want the bind-mounted nix store. otherwise tests take forever
|
||||||
|
fileSystems."/nix/store" = lib.mkForce {
|
||||||
|
device = "nix-store";
|
||||||
|
fsType = "9p";
|
||||||
|
neededForBoot = true;
|
||||||
|
options = [
|
||||||
|
"trans=virtio"
|
||||||
|
"version=9p2000.L"
|
||||||
|
"cache=loose"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
boot.zfs.devNodes = "/dev/disk/by-uuid"; # needed because /dev/disk/by-id is empty in qemu-vms
|
||||||
|
|
||||||
|
# grub will install to these devices, we need to force those or we are offset by 1
|
||||||
|
# we use mkOveride 70, so that users can override this with mkForce in case they are testing grub mirrored boots
|
||||||
|
boot.loader.grub.devices = lib.mkOverride 70 testConfigInstall.boot.loader.grub.devices;
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion =
|
||||||
|
builtins.length config.boot.loader.grub.mirroredBoots > 1 -> config.boot.loader.grub.devices == [ ];
|
||||||
|
message = ''
|
||||||
|
When using `--vm-test` in combination with `mirroredBoots`,
|
||||||
|
it is necessary to configure `boot.loader.grub.devices` as an empty list by setting `boot.loader.grub.devices = lib.mkForce [];`.
|
||||||
|
This adjustment is crucial because the `--vm-test` mechanism automatically overrides the grub boot devices as part of the virtual machine test.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
];
|
)
|
||||||
})
|
];
|
||||||
];
|
}).config.system.build.toplevel;
|
||||||
}).config.system.build.toplevel;
|
|
||||||
|
|
||||||
in
|
in
|
||||||
makeTest' {
|
makeTest' {
|
||||||
@@ -184,153 +207,177 @@ let
|
|||||||
meta.timeout = 600; # 10 minutes
|
meta.timeout = 600; # 10 minutes
|
||||||
inherit enableOCR;
|
inherit enableOCR;
|
||||||
|
|
||||||
nodes.machine = { pkgs, ... }: {
|
nodes.machine =
|
||||||
imports = [
|
{ pkgs, ... }:
|
||||||
(lib.optionalAttrs (testMode == "module") {
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../module.nix
|
(lib.optionalAttrs (testMode == "module") {
|
||||||
];
|
imports = [
|
||||||
disko = {
|
../module.nix
|
||||||
enableConfig = false;
|
];
|
||||||
checkScripts = true;
|
disko = {
|
||||||
devices = testConfigInstall.disko.devices;
|
enableConfig = false;
|
||||||
};
|
checkScripts = true;
|
||||||
})
|
devices = testConfigInstall.disko.devices;
|
||||||
extraInstallerConfig
|
};
|
||||||
|
})
|
||||||
|
extraInstallerConfig
|
||||||
|
|
||||||
# from base.nix
|
# from base.nix
|
||||||
({ config, ... }: {
|
(
|
||||||
boot.supportedFilesystems =
|
{ config, ... }:
|
||||||
[ "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";
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
(if lib.versionAtLeast (lib.versions.majorMinor lib.version) "23.11" then {
|
(
|
||||||
boot.swraid.enable = true;
|
if lib.versionAtLeast (lib.versions.majorMinor lib.version) "23.11" then
|
||||||
} else {
|
{
|
||||||
boot.initrd.services.swraid.enable = true;
|
boot.swraid.enable = true;
|
||||||
})
|
}
|
||||||
];
|
else
|
||||||
|
{
|
||||||
|
boot.initrd.services.swraid.enable = true;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
systemd.services.mdmonitor.enable = false; # silence some weird warnings
|
systemd.services.mdmonitor.enable = false; # silence some weird warnings
|
||||||
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
pkgs.jq
|
pkgs.jq
|
||||||
];
|
];
|
||||||
|
|
||||||
# speed-up eval
|
# speed-up eval
|
||||||
documentation.enable = false;
|
documentation.enable = false;
|
||||||
|
|
||||||
nix.settings = {
|
nix.settings = {
|
||||||
substituters = lib.mkForce [ ];
|
substituters = lib.mkForce [ ];
|
||||||
hashed-mirrors = null;
|
hashed-mirrors = null;
|
||||||
connect-timeout = 1;
|
connect-timeout = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.hostId = lib.mkIf (
|
||||||
|
(testConfigInstall ? networking.hostId) && (testConfigInstall.networking.hostId != null)
|
||||||
|
) testConfigInstall.networking.hostId;
|
||||||
|
|
||||||
|
virtualisation.emptyDiskImages = builtins.genList (_: 4096) num-disks;
|
||||||
|
|
||||||
|
# useful for debugging via repl
|
||||||
|
system.build.systemToInstall = installed-system-eval;
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.hostId = lib.mkIf
|
testScript =
|
||||||
(
|
{ nodes, ... }:
|
||||||
(testConfigInstall ? networking.hostId) && (testConfigInstall.networking.hostId != null)
|
''
|
||||||
)
|
def disks(oldmachine, num_disks):
|
||||||
testConfigInstall.networking.hostId;
|
disk_flags = []
|
||||||
|
for i in range(num_disks):
|
||||||
|
disk_flags += [
|
||||||
|
'-drive',
|
||||||
|
f"file={oldmachine.state_dir}/empty{i}.qcow2,id=drive{i + 1},if=none,index={i + 1},werror=report",
|
||||||
|
'-device',
|
||||||
|
f"virtio-blk-pci,drive=drive{i + 1}"
|
||||||
|
]
|
||||||
|
return disk_flags
|
||||||
|
|
||||||
virtualisation.emptyDiskImages = builtins.genList (_: 4096) num-disks;
|
def create_test_machine(
|
||||||
|
oldmachine=None, **kwargs
|
||||||
# useful for debugging via repl
|
): # taken from <nixpkgs/nixos/tests/installer.nix>
|
||||||
system.build.systemToInstall = installed-system-eval;
|
start_command = [
|
||||||
};
|
"${pkgs.qemu_test}/bin/qemu-kvm",
|
||||||
|
"-cpu",
|
||||||
testScript = { nodes, ... }: ''
|
"max",
|
||||||
def disks(oldmachine, num_disks):
|
"-m",
|
||||||
disk_flags = []
|
"1024",
|
||||||
for i in range(num_disks):
|
"-virtfs",
|
||||||
disk_flags += [
|
"local,path=/nix/store,security_model=none,mount_tag=nix-store",
|
||||||
'-drive',
|
*disks(oldmachine, ${toString num-disks})
|
||||||
f"file={oldmachine.state_dir}/empty{i}.qcow2,id=drive{i + 1},if=none,index={i + 1},werror=report",
|
|
||||||
'-device',
|
|
||||||
f"virtio-blk-pci,drive=drive{i + 1}"
|
|
||||||
]
|
|
||||||
return disk_flags
|
|
||||||
|
|
||||||
def create_test_machine(
|
|
||||||
oldmachine=None, **kwargs
|
|
||||||
): # taken from <nixpkgs/nixos/tests/installer.nix>
|
|
||||||
start_command = [
|
|
||||||
"${pkgs.qemu_test}/bin/qemu-kvm",
|
|
||||||
"-cpu",
|
|
||||||
"max",
|
|
||||||
"-m",
|
|
||||||
"1024",
|
|
||||||
"-virtfs",
|
|
||||||
"local,path=/nix/store,security_model=none,mount_tag=nix-store",
|
|
||||||
*disks(oldmachine, ${toString num-disks})
|
|
||||||
]
|
|
||||||
${lib.optionalString efi ''
|
|
||||||
start_command += ["-drive",
|
|
||||||
"if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware}",
|
|
||||||
"-drive",
|
|
||||||
"if=pflash,format=raw,unit=1,readonly=on,file=${pkgs.OVMF.variables}"
|
|
||||||
]
|
]
|
||||||
''}
|
${lib.optionalString efi ''
|
||||||
machine = create_machine(start_command=" ".join(start_command), **kwargs)
|
start_command += ["-drive",
|
||||||
driver.machines.append(machine)
|
"if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware}",
|
||||||
return machine
|
"-drive",
|
||||||
|
"if=pflash,format=raw,unit=1,readonly=on,file=${pkgs.OVMF.variables}"
|
||||||
|
]
|
||||||
|
''}
|
||||||
|
machine = create_machine(start_command=" ".join(start_command), **kwargs)
|
||||||
|
driver.machines.append(machine)
|
||||||
|
return machine
|
||||||
|
|
||||||
machine.start()
|
|
||||||
machine.succeed("echo -n 'additionalSecret' > /tmp/additionalSecret.key")
|
|
||||||
machine.succeed("echo -n 'secretsecret' > /tmp/secret.key")
|
|
||||||
${lib.optionalString (testMode == "direct") ''
|
|
||||||
# running direct mode
|
|
||||||
machine.succeed("${lib.getExe tsp-format}")
|
|
||||||
machine.succeed("${lib.getExe tsp-mount}")
|
|
||||||
machine.succeed("${lib.getExe tsp-mount}") # verify that mount is idempotent
|
|
||||||
machine.succeed("${lib.getExe tsp-unmount}")
|
|
||||||
machine.succeed("${lib.getExe tsp-unmount}") # verify that umount is idempotent
|
|
||||||
machine.succeed("${lib.getExe tsp-mount}") # verify that mount is idempotent
|
|
||||||
machine.succeed("${lib.getExe tsp-disko} --yes-wipe-all-disks") # verify that we can destroy and recreate
|
|
||||||
machine.succeed("mkdir -p /mnt/home")
|
|
||||||
machine.succeed("touch /mnt/home/testfile")
|
|
||||||
machine.succeed("${lib.getExe tsp-format}") # verify that format is idempotent
|
|
||||||
machine.succeed("test -e /mnt/home/testfile")
|
|
||||||
''}
|
|
||||||
${lib.optionalString (testMode == "module") ''
|
|
||||||
# running module mode
|
|
||||||
machine.succeed("${lib.getExe nodes.machine.system.build.format}")
|
|
||||||
machine.succeed("${lib.getExe nodes.machine.system.build.mount}")
|
|
||||||
machine.succeed("${lib.getExe nodes.machine.system.build.mount}") # verify that mount is idempotent
|
|
||||||
machine.succeed("${lib.getExe nodes.machine.system.build.destroyFormatMount} --yes-wipe-all-disks") # verify that we can destroy and recreate again
|
|
||||||
machine.succeed("mkdir -p /mnt/home")
|
|
||||||
machine.succeed("touch /mnt/home/testfile")
|
|
||||||
machine.succeed("${lib.getExe nodes.machine.system.build.format}") # verify that format is idempotent
|
|
||||||
machine.succeed("test -e /mnt/home/testfile")
|
|
||||||
''}
|
|
||||||
|
|
||||||
${postDisko}
|
|
||||||
|
|
||||||
${lib.optionalString testBoot ''
|
|
||||||
# mount nix-store in /mnt
|
|
||||||
machine.succeed("mkdir -p /mnt/nix/store")
|
|
||||||
machine.succeed("mount --bind /nix/store /mnt/nix/store")
|
|
||||||
|
|
||||||
machine.succeed("nix-store --load-db < ${pkgs.closureInfo {rootPaths = [installedTopLevel];}}/registration")
|
|
||||||
|
|
||||||
# fix "this is not a NixOS installation"
|
|
||||||
machine.succeed("mkdir -p /mnt/etc")
|
|
||||||
machine.succeed("touch /mnt/etc/NIXOS")
|
|
||||||
|
|
||||||
machine.succeed("mkdir -p /mnt/nix/var/nix/profiles")
|
|
||||||
machine.succeed("nix-env -p /mnt/nix/var/nix/profiles/system --set ${installedTopLevel}")
|
|
||||||
machine.succeed("NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root /mnt -- ${installedTopLevel}/bin/switch-to-configuration boot")
|
|
||||||
machine.succeed("sync")
|
|
||||||
machine.shutdown()
|
|
||||||
|
|
||||||
machine = create_test_machine(oldmachine=machine, name="booted_machine")
|
|
||||||
machine.start()
|
machine.start()
|
||||||
${bootCommands}
|
machine.succeed("echo -n 'additionalSecret' > /tmp/additionalSecret.key")
|
||||||
machine.wait_for_unit("local-fs.target")
|
machine.succeed("echo -n 'secretsecret' > /tmp/secret.key")
|
||||||
''}
|
${lib.optionalString (testMode == "direct") ''
|
||||||
|
# running direct mode
|
||||||
|
machine.succeed("${lib.getExe tsp-format}")
|
||||||
|
machine.succeed("${lib.getExe tsp-mount}")
|
||||||
|
machine.succeed("${lib.getExe tsp-mount}") # verify that mount is idempotent
|
||||||
|
machine.succeed("${lib.getExe tsp-unmount}")
|
||||||
|
machine.succeed("${lib.getExe tsp-unmount}") # verify that umount is idempotent
|
||||||
|
machine.succeed("${lib.getExe tsp-mount}") # verify that mount is idempotent
|
||||||
|
machine.succeed("${lib.getExe tsp-disko} --yes-wipe-all-disks") # verify that we can destroy and recreate
|
||||||
|
machine.succeed("mkdir -p /mnt/home")
|
||||||
|
machine.succeed("touch /mnt/home/testfile")
|
||||||
|
machine.succeed("${lib.getExe tsp-format}") # verify that format is idempotent
|
||||||
|
machine.succeed("test -e /mnt/home/testfile")
|
||||||
|
''}
|
||||||
|
${lib.optionalString (testMode == "module") ''
|
||||||
|
# running module mode
|
||||||
|
machine.succeed("${lib.getExe nodes.machine.system.build.format}")
|
||||||
|
machine.succeed("${lib.getExe nodes.machine.system.build.mount}")
|
||||||
|
machine.succeed("${lib.getExe nodes.machine.system.build.mount}") # verify that mount is idempotent
|
||||||
|
machine.succeed("${lib.getExe nodes.machine.system.build.destroyFormatMount} --yes-wipe-all-disks") # verify that we can destroy and recreate again
|
||||||
|
machine.succeed("mkdir -p /mnt/home")
|
||||||
|
machine.succeed("touch /mnt/home/testfile")
|
||||||
|
machine.succeed("${lib.getExe nodes.machine.system.build.format}") # verify that format is idempotent
|
||||||
|
machine.succeed("test -e /mnt/home/testfile")
|
||||||
|
''}
|
||||||
|
|
||||||
${extraTestScript}
|
${postDisko}
|
||||||
'';
|
|
||||||
|
${lib.optionalString testBoot ''
|
||||||
|
# mount nix-store in /mnt
|
||||||
|
machine.succeed("mkdir -p /mnt/nix/store")
|
||||||
|
machine.succeed("mount --bind /nix/store /mnt/nix/store")
|
||||||
|
|
||||||
|
machine.succeed("nix-store --load-db < ${
|
||||||
|
pkgs.closureInfo { rootPaths = [ installedTopLevel ]; }
|
||||||
|
}/registration")
|
||||||
|
|
||||||
|
# fix "this is not a NixOS installation"
|
||||||
|
machine.succeed("mkdir -p /mnt/etc")
|
||||||
|
machine.succeed("touch /mnt/etc/NIXOS")
|
||||||
|
|
||||||
|
machine.succeed("mkdir -p /mnt/nix/var/nix/profiles")
|
||||||
|
machine.succeed("nix-env -p /mnt/nix/var/nix/profiles/system --set ${installedTopLevel}")
|
||||||
|
machine.succeed("NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root /mnt -- ${installedTopLevel}/bin/switch-to-configuration boot")
|
||||||
|
machine.succeed("sync")
|
||||||
|
machine.shutdown()
|
||||||
|
|
||||||
|
machine = create_test_machine(oldmachine=machine, name="booted_machine")
|
||||||
|
machine.start()
|
||||||
|
${bootCommands}
|
||||||
|
machine.wait_for_unit("local-fs.target")
|
||||||
|
''}
|
||||||
|
|
||||||
|
${extraTestScript}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
@@ -1,60 +1,71 @@
|
|||||||
{ config, options, diskoLib, lib, rootMountPoint, parent, device, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
diskoLib,
|
||||||
|
lib,
|
||||||
|
rootMountPoint,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
swapType = lib.mkOption {
|
swapType = lib.mkOption {
|
||||||
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
|
type = lib.types.attrsOf (
|
||||||
options = {
|
lib.types.submodule (
|
||||||
size = lib.mkOption {
|
{ name, ... }:
|
||||||
type = lib.types.strMatching "^([0-9]+[KMGTP])?$";
|
{
|
||||||
description = "Size of the swap file (e.g. 2G)";
|
options = {
|
||||||
};
|
size = lib.mkOption {
|
||||||
|
type = lib.types.strMatching "^([0-9]+[KMGTP])?$";
|
||||||
|
description = "Size of the swap file (e.g. 2G)";
|
||||||
|
};
|
||||||
|
|
||||||
path = lib.mkOption {
|
path = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = name;
|
default = name;
|
||||||
description = "Path to the swap file (relative to the mountpoint)";
|
description = "Path to the swap file (relative to the mountpoint)";
|
||||||
};
|
};
|
||||||
|
|
||||||
priority = lib.mkOption {
|
priority = lib.mkOption {
|
||||||
type = lib.types.nullOr lib.types.int;
|
type = lib.types.nullOr lib.types.int;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
Specify the priority of the swap file. Priority is a value between 0 and 32767.
|
Specify the priority of the swap file. Priority is a value between 0 and 32767.
|
||||||
Higher numbers indicate higher priority.
|
Higher numbers indicate higher priority.
|
||||||
null lets the kernel choose a priority, which will show up as a negative value.
|
null lets the kernel choose a priority, which will show up as a negative value.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
options = lib.mkOption {
|
options = lib.mkOption {
|
||||||
type = lib.types.listOf lib.types.nonEmptyStr;
|
type = lib.types.listOf lib.types.nonEmptyStr;
|
||||||
default = [ "defaults" ];
|
default = [ "defaults" ];
|
||||||
example = [ "nofail" ];
|
example = [ "nofail" ];
|
||||||
description = "Options used to mount the swap.";
|
description = "Options used to mount the swap.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
default = { };
|
default = { };
|
||||||
description = "Swap files";
|
description = "Swap files";
|
||||||
};
|
};
|
||||||
|
|
||||||
swapConfig = { mountpoint, swap }:
|
swapConfig =
|
||||||
|
{ mountpoint, swap }:
|
||||||
{
|
{
|
||||||
swapDevices = builtins.map
|
swapDevices = builtins.map (file: {
|
||||||
(file: {
|
device = "${mountpoint}/${file.path}";
|
||||||
device = "${mountpoint}/${file.path}";
|
inherit (file) priority options;
|
||||||
inherit (file) priority options;
|
}) (lib.attrValues swap);
|
||||||
})
|
|
||||||
(lib.attrValues swap);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
swapCreate = mountpoint: swap:
|
swapCreate =
|
||||||
lib.concatMapStringsSep
|
mountpoint: swap:
|
||||||
"\n"
|
lib.concatMapStringsSep "\n" (file: ''
|
||||||
(file: ''
|
if ! test -e "${mountpoint}/${file.path}"; then
|
||||||
if ! test -e "${mountpoint}/${file.path}"; then
|
btrfs filesystem mkswapfile --size ${file.size} "${mountpoint}/${file.path}"
|
||||||
btrfs filesystem mkswapfile --size ${file.size} "${mountpoint}/${file.path}"
|
fi
|
||||||
fi
|
'') (lib.attrValues swap);
|
||||||
'')
|
|
||||||
(lib.attrValues swap);
|
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -80,37 +91,42 @@ in
|
|||||||
description = "A list of options to pass to mount.";
|
description = "A list of options to pass to mount.";
|
||||||
};
|
};
|
||||||
subvolumes = lib.mkOption {
|
subvolumes = lib.mkOption {
|
||||||
type = lib.types.attrsOf (lib.types.submodule ({ config, ... }: {
|
type = lib.types.attrsOf (
|
||||||
options = {
|
lib.types.submodule (
|
||||||
name = lib.mkOption {
|
{ config, ... }:
|
||||||
type = lib.types.str;
|
{
|
||||||
default = config._module.args.name;
|
options = {
|
||||||
description = "Name of the BTRFS subvolume.";
|
name = lib.mkOption {
|
||||||
};
|
type = lib.types.str;
|
||||||
type = lib.mkOption {
|
default = config._module.args.name;
|
||||||
type = lib.types.enum [ "btrfs_subvol" ];
|
description = "Name of the BTRFS subvolume.";
|
||||||
default = "btrfs_subvol";
|
};
|
||||||
internal = true;
|
type = lib.mkOption {
|
||||||
description = "Type";
|
type = lib.types.enum [ "btrfs_subvol" ];
|
||||||
};
|
default = "btrfs_subvol";
|
||||||
extraArgs = lib.mkOption {
|
internal = true;
|
||||||
type = lib.types.listOf lib.types.str;
|
description = "Type";
|
||||||
default = [ ];
|
};
|
||||||
description = "Extra arguments";
|
extraArgs = lib.mkOption {
|
||||||
};
|
type = lib.types.listOf lib.types.str;
|
||||||
mountOptions = lib.mkOption {
|
default = [ ];
|
||||||
type = lib.types.listOf lib.types.str;
|
description = "Extra arguments";
|
||||||
default = [ "defaults" ];
|
};
|
||||||
description = "Options to pass to mount";
|
mountOptions = lib.mkOption {
|
||||||
};
|
type = lib.types.listOf lib.types.str;
|
||||||
mountpoint = lib.mkOption {
|
default = [ "defaults" ];
|
||||||
type = lib.types.nullOr diskoLib.optionTypes.absolute-pathname;
|
description = "Options to pass to mount";
|
||||||
default = null;
|
};
|
||||||
description = "Location to mount the subvolume to.";
|
mountpoint = lib.mkOption {
|
||||||
};
|
type = lib.types.nullOr diskoLib.optionTypes.absolute-pathname;
|
||||||
swap = swapType;
|
default = null;
|
||||||
};
|
description = "Location to mount the subvolume to.";
|
||||||
}));
|
};
|
||||||
|
swap = swapType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
default = { };
|
default = { };
|
||||||
description = "Subvolumes to define for BTRFS.";
|
description = "Subvolumes to define for BTRFS.";
|
||||||
};
|
};
|
||||||
@@ -138,9 +154,9 @@ in
|
|||||||
if ! (blkid "${config.device}" -o export | grep -q '^TYPE='); then
|
if ! (blkid "${config.device}" -o export | grep -q '^TYPE='); then
|
||||||
mkfs.btrfs "${config.device}" ${toString config.extraArgs}
|
mkfs.btrfs "${config.device}" ${toString config.extraArgs}
|
||||||
fi
|
fi
|
||||||
${lib.optionalString (config.swap != {} || config.subvolumes != {}) ''
|
${lib.optionalString (config.swap != { } || config.subvolumes != { }) ''
|
||||||
if (blkid "${config.device}" -o export | grep -q '^TYPE=btrfs$'); then
|
if (blkid "${config.device}" -o export | grep -q '^TYPE=btrfs$'); then
|
||||||
${lib.optionalString (config.swap != {}) ''
|
${lib.optionalString (config.swap != { }) ''
|
||||||
(
|
(
|
||||||
MNTPOINT=$(mktemp -d)
|
MNTPOINT=$(mktemp -d)
|
||||||
mount ${device} "$MNTPOINT" -o subvol=/
|
mount ${device} "$MNTPOINT" -o subvol=/
|
||||||
@@ -169,79 +185,84 @@ in
|
|||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default =
|
||||||
let
|
let
|
||||||
subvolMounts = lib.concatMapAttrs
|
subvolMounts = lib.concatMapAttrs (
|
||||||
(_: subvol:
|
_: subvol:
|
||||||
lib.warnIf (subvol.mountOptions != (options.subvolumes.type.getSubOptions [ ]).mountOptions.default && subvol.mountpoint == null)
|
lib.warnIf
|
||||||
"Subvolume ${subvol.name} has mountOptions but no mountpoint. See upgrade guide (2023-07-09 121df48)."
|
(
|
||||||
lib.optionalAttrs
|
subvol.mountOptions != (options.subvolumes.type.getSubOptions [ ]).mountOptions.default
|
||||||
(subvol.mountpoint != null)
|
&& subvol.mountpoint == null
|
||||||
{
|
)
|
||||||
${subvol.mountpoint} = ''
|
"Subvolume ${subvol.name} has mountOptions but no mountpoint. See upgrade guide (2023-07-09 121df48)."
|
||||||
if ! findmnt "${config.device}" "${rootMountPoint}${subvol.mountpoint}" > /dev/null 2>&1; then
|
lib.optionalAttrs
|
||||||
mount "${config.device}" "${rootMountPoint}${subvol.mountpoint}" \
|
(subvol.mountpoint != null)
|
||||||
${lib.concatMapStringsSep " " (opt: "-o ${opt}") (subvol.mountOptions ++ [ "subvol=${subvol.name}" ])} \
|
{
|
||||||
-o X-mount.mkdir
|
${subvol.mountpoint} = ''
|
||||||
fi
|
if ! findmnt "${config.device}" "${rootMountPoint}${subvol.mountpoint}" > /dev/null 2>&1; then
|
||||||
'';
|
mount "${config.device}" "${rootMountPoint}${subvol.mountpoint}" \
|
||||||
}
|
${
|
||||||
)
|
lib.concatMapStringsSep " " (opt: "-o ${opt}") (subvol.mountOptions ++ [ "subvol=${subvol.name}" ])
|
||||||
config.subvolumes;
|
} \
|
||||||
|
-o X-mount.mkdir
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
) config.subvolumes;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
fs = subvolMounts // lib.optionalAttrs (config.mountpoint != null) {
|
fs =
|
||||||
${config.mountpoint} = ''
|
subvolMounts
|
||||||
if ! findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
|
// lib.optionalAttrs (config.mountpoint != null) {
|
||||||
mount "${config.device}" "${rootMountPoint}${config.mountpoint}" \
|
${config.mountpoint} = ''
|
||||||
${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \
|
if ! findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
|
||||||
-o X-mount.mkdir
|
mount "${config.device}" "${rootMountPoint}${config.mountpoint}" \
|
||||||
fi
|
${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \
|
||||||
'';
|
-o X-mount.mkdir
|
||||||
};
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
_unmount = diskoLib.mkUnmountOption {
|
_unmount = diskoLib.mkUnmountOption {
|
||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default =
|
||||||
let
|
let
|
||||||
subvolMounts = lib.concatMapAttrs
|
subvolMounts = lib.concatMapAttrs (
|
||||||
(_: subvol:
|
_: subvol:
|
||||||
lib.optionalAttrs
|
lib.optionalAttrs (subvol.mountpoint != null) {
|
||||||
(subvol.mountpoint != null)
|
${subvol.mountpoint} = ''
|
||||||
{
|
if findmnt "${config.device}" "${rootMountPoint}${subvol.mountpoint}" > /dev/null 2>&1; then
|
||||||
${subvol.mountpoint} = ''
|
umount "${rootMountPoint}${subvol.mountpoint}"
|
||||||
if findmnt "${config.device}" "${rootMountPoint}${subvol.mountpoint}" > /dev/null 2>&1; then
|
fi
|
||||||
umount "${rootMountPoint}${subvol.mountpoint}"
|
'';
|
||||||
fi
|
}
|
||||||
'';
|
) config.subvolumes;
|
||||||
}
|
|
||||||
)
|
|
||||||
config.subvolumes;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
fs = subvolMounts // lib.optionalAttrs (config.mountpoint != null) {
|
fs =
|
||||||
${config.mountpoint} = ''
|
subvolMounts
|
||||||
if findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
|
// lib.optionalAttrs (config.mountpoint != null) {
|
||||||
umount "${rootMountPoint}${config.mountpoint}"
|
${config.mountpoint} = ''
|
||||||
fi
|
if findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
|
||||||
'';
|
umount "${rootMountPoint}${config.mountpoint}"
|
||||||
};
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = [
|
default = [
|
||||||
(map
|
(map (
|
||||||
(subvol:
|
subvol:
|
||||||
lib.optional (subvol.mountpoint != null) {
|
lib.optional (subvol.mountpoint != null) {
|
||||||
fileSystems.${subvol.mountpoint} = {
|
fileSystems.${subvol.mountpoint} = {
|
||||||
device = config.device;
|
device = config.device;
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = subvol.mountOptions ++ [ "subvol=${subvol.name}" ];
|
options = subvol.mountOptions ++ [ "subvol=${subvol.name}" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
) (lib.attrValues config.subvolumes))
|
||||||
(lib.attrValues config.subvolumes))
|
|
||||||
(lib.optional (config.mountpoint != null) {
|
(lib.optional (config.mountpoint != null) {
|
||||||
fileSystems.${config.mountpoint} = {
|
fileSystems.${config.mountpoint} = {
|
||||||
device = config.device;
|
device = config.device;
|
||||||
@@ -249,11 +270,12 @@ in
|
|||||||
options = config.mountOptions;
|
options = config.mountOptions;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(map
|
(map (
|
||||||
(subvol: swapConfig {
|
subvol:
|
||||||
|
swapConfig {
|
||||||
inherit (subvol) mountpoint swap;
|
inherit (subvol) mountpoint swap;
|
||||||
})
|
}
|
||||||
(lib.attrValues config.subvolumes))
|
) (lib.attrValues config.subvolumes))
|
||||||
(swapConfig {
|
(swapConfig {
|
||||||
inherit (config) mountpoint swap;
|
inherit (config) mountpoint swap;
|
||||||
})
|
})
|
||||||
@@ -264,8 +286,10 @@ in
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs:
|
default = pkgs: [
|
||||||
[ pkgs.btrfs-progs pkgs.gnugrep ];
|
pkgs.btrfs-progs
|
||||||
|
pkgs.gnugrep
|
||||||
|
];
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
{ config, options, lib, diskoLib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
name = lib.mkOption {
|
name = lib.mkOption {
|
||||||
@@ -32,13 +38,20 @@
|
|||||||
'';
|
'';
|
||||||
default = "2G";
|
default = "2G";
|
||||||
};
|
};
|
||||||
content = diskoLib.deviceType { parent = config; device = config.device; };
|
content = diskoLib.deviceType {
|
||||||
|
parent = config;
|
||||||
|
device = config.device;
|
||||||
|
};
|
||||||
_meta = lib.mkOption {
|
_meta = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = diskoLib.jsonType;
|
type = diskoLib.jsonType;
|
||||||
default =
|
default = lib.optionalAttrs (config.content != null) (
|
||||||
lib.optionalAttrs (config.content != null) (config.content._meta [ "disk" config.device ]);
|
config.content._meta [
|
||||||
|
"disk"
|
||||||
|
config.device
|
||||||
|
]
|
||||||
|
);
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
_create = diskoLib.mkCreateOption {
|
||||||
@@ -56,8 +69,7 @@
|
|||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default =
|
default = lib.optional (config.content != null) config.content._config;
|
||||||
lib.optional (config.content != null) config.content._config;
|
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
_pkgs = lib.mkOption {
|
_pkgs = lib.mkOption {
|
||||||
|
@@ -1,4 +1,13 @@
|
|||||||
{ config, options, lib, diskoLib, rootMountPoint, parent, device, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
rootMountPoint,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
type = lib.mkOption {
|
type = lib.mkOption {
|
||||||
@@ -90,18 +99,32 @@
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
# type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
# type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs:
|
default =
|
||||||
[ pkgs.util-linux pkgs.gnugrep ] ++ (
|
pkgs:
|
||||||
|
[
|
||||||
|
pkgs.util-linux
|
||||||
|
pkgs.gnugrep
|
||||||
|
]
|
||||||
|
++ (
|
||||||
# TODO add many more
|
# TODO add many more
|
||||||
if (config.format == "xfs") then [ pkgs.xfsprogs ]
|
if (config.format == "xfs") then
|
||||||
else if (config.format == "btrfs") then [ pkgs.btrfs-progs ]
|
[ pkgs.xfsprogs ]
|
||||||
else if (config.format == "vfat") then [ pkgs.dosfstools ]
|
else if (config.format == "btrfs") then
|
||||||
else if (config.format == "ext2") then [ pkgs.e2fsprogs ]
|
[ pkgs.btrfs-progs ]
|
||||||
else if (config.format == "ext3") then [ pkgs.e2fsprogs ]
|
else if (config.format == "vfat") then
|
||||||
else if (config.format == "ext4") then [ pkgs.e2fsprogs ]
|
[ pkgs.dosfstools ]
|
||||||
else if (config.format == "bcachefs") then [ pkgs.bcachefs-tools ]
|
else if (config.format == "ext2") then
|
||||||
else if (config.format == "f2fs") then [ pkgs.f2fs-tools ]
|
[ pkgs.e2fsprogs ]
|
||||||
else [ ]
|
else if (config.format == "ext3") then
|
||||||
|
[ pkgs.e2fsprogs ]
|
||||||
|
else if (config.format == "ext4") then
|
||||||
|
[ pkgs.e2fsprogs ]
|
||||||
|
else if (config.format == "bcachefs") then
|
||||||
|
[ pkgs.bcachefs-tools ]
|
||||||
|
else if (config.format == "f2fs") then
|
||||||
|
[ pkgs.f2fs-tools ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
);
|
);
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
{ config, options, lib, diskoLib, parent, device, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
sortedPartitions = lib.sort (x: y: x.priority < y.priority) (lib.attrValues config.partitions);
|
sortedPartitions = lib.sort (x: y: x.priority < y.priority) (lib.attrValues config.partitions);
|
||||||
sortedHybridPartitions = lib.filter (p: p.hybrid != null) sortedPartitions;
|
sortedHybridPartitions = lib.filter (p: p.hybrid != null) sortedPartitions;
|
||||||
@@ -16,171 +24,210 @@ in
|
|||||||
description = "Device to use for the partition table";
|
description = "Device to use for the partition table";
|
||||||
};
|
};
|
||||||
partitions = lib.mkOption {
|
partitions = lib.mkOption {
|
||||||
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@partition: {
|
type = lib.types.attrsOf (
|
||||||
options = {
|
lib.types.submodule (
|
||||||
type = lib.mkOption {
|
{ name, ... }@partition:
|
||||||
type =
|
{
|
||||||
let
|
options = {
|
||||||
hexPattern = len: "[A-Fa-f0-9]{${toString len}}";
|
type = lib.mkOption {
|
||||||
in
|
type =
|
||||||
lib.types.either
|
let
|
||||||
(lib.types.strMatching (hexPattern 4))
|
hexPattern = len: "[A-Fa-f0-9]{${toString len}}";
|
||||||
(lib.types.strMatching (lib.concatMapStringsSep "-" hexPattern [ 8 4 4 4 12 ]));
|
in
|
||||||
default = if partition.config.content != null && partition.config.content.type == "swap" then "8200" else "8300";
|
lib.types.either (lib.types.strMatching (hexPattern 4)) (
|
||||||
defaultText = ''8300 (Linux filesystem) normally, 8200 (Linux swap) if content.type is "swap"'';
|
lib.types.strMatching (
|
||||||
description = ''
|
lib.concatMapStringsSep "-" hexPattern [
|
||||||
Filesystem type to use.
|
8
|
||||||
This can either be an sgdisk-specific short code (run sgdisk -L to see what is available),
|
4
|
||||||
or a fully specified GUID (see https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs).
|
4
|
||||||
'';
|
4
|
||||||
};
|
12
|
||||||
device = lib.mkOption {
|
]
|
||||||
type = lib.types.str;
|
)
|
||||||
default =
|
);
|
||||||
if partition.config.uuid != null then
|
default =
|
||||||
"/dev/disk/by-partuuid/${partition.config.uuid}"
|
if partition.config.content != null && partition.config.content.type == "swap" then
|
||||||
else if config._parent.type == "mdadm" then
|
"8200"
|
||||||
# workaround because mdadm partlabel do not appear in /dev/disk/by-partlabel
|
else
|
||||||
"/dev/disk/by-id/md-name-any:${config._parent.name}-part${toString partition.config._index}"
|
"8300";
|
||||||
else
|
defaultText = ''8300 (Linux filesystem) normally, 8200 (Linux swap) if content.type is "swap"'';
|
||||||
"/dev/disk/by-partlabel/${diskoLib.hexEscapeUdevSymlink partition.config.label}";
|
description = ''
|
||||||
defaultText = ''
|
Filesystem type to use.
|
||||||
if `uuid` is provided:
|
This can either be an sgdisk-specific short code (run sgdisk -L to see what is available),
|
||||||
/dev/disk/by-partuuid/''${partition.config.uuid}
|
or a fully specified GUID (see https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs).
|
||||||
|
'';
|
||||||
otherwise, if the parent is an mdadm device:
|
|
||||||
/dev/disk/by-id/md-name-any:''${config._parent.name}-part''${toString partition.config._index}
|
|
||||||
|
|
||||||
otherwise:
|
|
||||||
/dev/disk/by-partlabel/''${diskoLib.hexEscapeUdevSymlink partition.config.label}
|
|
||||||
'';
|
|
||||||
description = "Device to use for the partition";
|
|
||||||
};
|
|
||||||
priority = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default =
|
|
||||||
if partition.config.size or "" == "100%" then
|
|
||||||
9001
|
|
||||||
else if partition.config.type == "EF02" then
|
|
||||||
# Boot partition should be created first, because some BIOS implementations require it.
|
|
||||||
# Priority defaults to 100 here to support any potential use-case for placing partitions prior to EF02
|
|
||||||
100
|
|
||||||
else
|
|
||||||
1000;
|
|
||||||
defaultText = ''
|
|
||||||
1000: normal partitions
|
|
||||||
9001: partitions with 100% size
|
|
||||||
100: boot partitions (EF02)
|
|
||||||
'';
|
|
||||||
description = "Priority of the partition, smaller values are created first";
|
|
||||||
};
|
|
||||||
name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
description = "Name of the partition";
|
|
||||||
default = name;
|
|
||||||
};
|
|
||||||
uuid = lib.mkOption {
|
|
||||||
type = lib.types.nullOr (lib.types.strMatching "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}");
|
|
||||||
default = null;
|
|
||||||
defaultText = "`null` - generate a UUID when creating the partition";
|
|
||||||
example = "809b3a2b-828a-4730-95e1-75b6343e415a";
|
|
||||||
description = ''
|
|
||||||
The UUID (also known as GUID) of the partition. Note that this is distinct from the UUID of the filesystem.
|
|
||||||
|
|
||||||
You can generate a UUID with the command `uuidgen -r`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
label = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default =
|
|
||||||
let
|
|
||||||
# 72 bytes is the maximum length of a GPT partition name
|
|
||||||
# the labels seem to be in UTF-16, so 2 bytes per character
|
|
||||||
limit = 36;
|
|
||||||
label = "${config._parent.type}-${config._parent.name}-${partition.config.name}";
|
|
||||||
in
|
|
||||||
if (lib.stringLength label) > limit then
|
|
||||||
builtins.substring 0 limit (builtins.hashString "sha256" label)
|
|
||||||
else
|
|
||||||
label;
|
|
||||||
defaultText = ''
|
|
||||||
''${config._parent.type}-''${config._parent.name}-''${partition.config.name}
|
|
||||||
|
|
||||||
or a truncated hash of the above if it is longer than 36 characters
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
size = lib.mkOption {
|
|
||||||
type = lib.types.either (lib.types.enum [ "100%" ]) (lib.types.strMatching "[0-9]+[KMGTP]?");
|
|
||||||
default = "0";
|
|
||||||
description = ''
|
|
||||||
Size of the partition, in sgdisk format.
|
|
||||||
sets end automatically with the + prefix
|
|
||||||
can be 100% for the whole remaining disk, will be done last in that case.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
alignment = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = if (builtins.substring (builtins.stringLength partition.config.start - 1) 1 partition.config.start == "s" || (builtins.substring (builtins.stringLength partition.config.end - 1) 1 partition.config.end == "s")) then 1 else 0;
|
|
||||||
defaultText = "1 if the unit of start or end is sectors, 0 otherwise";
|
|
||||||
description = "Alignment of the partition, if sectors are used as start or end it can be aligned to 1";
|
|
||||||
};
|
|
||||||
start = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "0";
|
|
||||||
description = "Start of the partition, in sgdisk format, use 0 for next available range";
|
|
||||||
};
|
|
||||||
end = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = if partition.config.size == "100%" then "-0" else "+${partition.config.size}";
|
|
||||||
defaultText = ''
|
|
||||||
if partition.config.size == "100%" then "-0" else "+''${partition.config.size}";
|
|
||||||
'';
|
|
||||||
description = ''
|
|
||||||
End of the partition, in sgdisk format.
|
|
||||||
Use + for relative sizes from the partitions start
|
|
||||||
or - for relative sizes from the disks end
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
content = diskoLib.partitionType { parent = config; device = partition.config.device; };
|
|
||||||
hybrid = lib.mkOption {
|
|
||||||
type = lib.types.nullOr (lib.types.submodule ({ ... } @ hp: {
|
|
||||||
options = {
|
|
||||||
mbrPartitionType = lib.mkOption {
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
|
||||||
default = null;
|
|
||||||
description = "MBR type code";
|
|
||||||
};
|
|
||||||
mbrBootableFlag = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
description = "Set the bootable flag (aka the active flag) on any or all of your hybridized partitions";
|
|
||||||
};
|
|
||||||
_create = diskoLib.mkCreateOption {
|
|
||||||
inherit config options;
|
|
||||||
default = ''
|
|
||||||
${lib.optionalString (hp.config.mbrPartitionType != null) ''
|
|
||||||
sfdisk --label-nested dos --part-type "${parent.device}" ${(toString partition.config._index)} ${hp.config.mbrPartitionType}
|
|
||||||
udevadm trigger --subsystem-match=block
|
|
||||||
udevadm settle
|
|
||||||
''}
|
|
||||||
${lib.optionalString hp.config.mbrBootableFlag ''
|
|
||||||
sfdisk --label-nested dos --activate "${parent.device}" ${(toString partition.config._index)}
|
|
||||||
''}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}));
|
device = lib.mkOption {
|
||||||
default = null;
|
type = lib.types.str;
|
||||||
description = "Entry to add to the Hybrid MBR table";
|
default =
|
||||||
};
|
if partition.config.uuid != null then
|
||||||
_index = lib.mkOption {
|
"/dev/disk/by-partuuid/${partition.config.uuid}"
|
||||||
type = lib.types.int;
|
else if config._parent.type == "mdadm" then
|
||||||
internal = true;
|
# workaround because mdadm partlabel do not appear in /dev/disk/by-partlabel
|
||||||
default = diskoLib.indexOf (x: x.name == partition.config.name) sortedPartitions 0;
|
"/dev/disk/by-id/md-name-any:${config._parent.name}-part${toString partition.config._index}"
|
||||||
defaultText = null;
|
else
|
||||||
};
|
"/dev/disk/by-partlabel/${diskoLib.hexEscapeUdevSymlink partition.config.label}";
|
||||||
};
|
defaultText = ''
|
||||||
}));
|
if `uuid` is provided:
|
||||||
|
/dev/disk/by-partuuid/''${partition.config.uuid}
|
||||||
|
|
||||||
|
otherwise, if the parent is an mdadm device:
|
||||||
|
/dev/disk/by-id/md-name-any:''${config._parent.name}-part''${toString partition.config._index}
|
||||||
|
|
||||||
|
otherwise:
|
||||||
|
/dev/disk/by-partlabel/''${diskoLib.hexEscapeUdevSymlink partition.config.label}
|
||||||
|
'';
|
||||||
|
description = "Device to use for the partition";
|
||||||
|
};
|
||||||
|
priority = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default =
|
||||||
|
if partition.config.size or "" == "100%" then
|
||||||
|
9001
|
||||||
|
else if partition.config.type == "EF02" then
|
||||||
|
# Boot partition should be created first, because some BIOS implementations require it.
|
||||||
|
# Priority defaults to 100 here to support any potential use-case for placing partitions prior to EF02
|
||||||
|
100
|
||||||
|
else
|
||||||
|
1000;
|
||||||
|
defaultText = ''
|
||||||
|
1000: normal partitions
|
||||||
|
9001: partitions with 100% size
|
||||||
|
100: boot partitions (EF02)
|
||||||
|
'';
|
||||||
|
description = "Priority of the partition, smaller values are created first";
|
||||||
|
};
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Name of the partition";
|
||||||
|
default = name;
|
||||||
|
};
|
||||||
|
uuid = lib.mkOption {
|
||||||
|
type = lib.types.nullOr (
|
||||||
|
lib.types.strMatching "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"
|
||||||
|
);
|
||||||
|
default = null;
|
||||||
|
defaultText = "`null` - generate a UUID when creating the partition";
|
||||||
|
example = "809b3a2b-828a-4730-95e1-75b6343e415a";
|
||||||
|
description = ''
|
||||||
|
The UUID (also known as GUID) of the partition. Note that this is distinct from the UUID of the filesystem.
|
||||||
|
|
||||||
|
You can generate a UUID with the command `uuidgen -r`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
label = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default =
|
||||||
|
let
|
||||||
|
# 72 bytes is the maximum length of a GPT partition name
|
||||||
|
# the labels seem to be in UTF-16, so 2 bytes per character
|
||||||
|
limit = 36;
|
||||||
|
label = "${config._parent.type}-${config._parent.name}-${partition.config.name}";
|
||||||
|
in
|
||||||
|
if (lib.stringLength label) > limit then
|
||||||
|
builtins.substring 0 limit (builtins.hashString "sha256" label)
|
||||||
|
else
|
||||||
|
label;
|
||||||
|
defaultText = ''
|
||||||
|
''${config._parent.type}-''${config._parent.name}-''${partition.config.name}
|
||||||
|
|
||||||
|
or a truncated hash of the above if it is longer than 36 characters
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
size = lib.mkOption {
|
||||||
|
type = lib.types.either (lib.types.enum [ "100%" ]) (lib.types.strMatching "[0-9]+[KMGTP]?");
|
||||||
|
default = "0";
|
||||||
|
description = ''
|
||||||
|
Size of the partition, in sgdisk format.
|
||||||
|
sets end automatically with the + prefix
|
||||||
|
can be 100% for the whole remaining disk, will be done last in that case.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
alignment = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default =
|
||||||
|
if
|
||||||
|
(
|
||||||
|
builtins.substring (builtins.stringLength partition.config.start - 1) 1 partition.config.start
|
||||||
|
== "s"
|
||||||
|
|| (
|
||||||
|
builtins.substring (builtins.stringLength partition.config.end - 1) 1 partition.config.end == "s"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
then
|
||||||
|
1
|
||||||
|
else
|
||||||
|
0;
|
||||||
|
defaultText = "1 if the unit of start or end is sectors, 0 otherwise";
|
||||||
|
description = "Alignment of the partition, if sectors are used as start or end it can be aligned to 1";
|
||||||
|
};
|
||||||
|
start = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "0";
|
||||||
|
description = "Start of the partition, in sgdisk format, use 0 for next available range";
|
||||||
|
};
|
||||||
|
end = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = if partition.config.size == "100%" then "-0" else "+${partition.config.size}";
|
||||||
|
defaultText = ''
|
||||||
|
if partition.config.size == "100%" then "-0" else "+''${partition.config.size}";
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
End of the partition, in sgdisk format.
|
||||||
|
Use + for relative sizes from the partitions start
|
||||||
|
or - for relative sizes from the disks end
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
content = diskoLib.partitionType {
|
||||||
|
parent = config;
|
||||||
|
device = partition.config.device;
|
||||||
|
};
|
||||||
|
hybrid = lib.mkOption {
|
||||||
|
type = lib.types.nullOr (
|
||||||
|
lib.types.submodule (
|
||||||
|
{ ... }@hp:
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
mbrPartitionType = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = "MBR type code";
|
||||||
|
};
|
||||||
|
mbrBootableFlag = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Set the bootable flag (aka the active flag) on any or all of your hybridized partitions";
|
||||||
|
};
|
||||||
|
_create = diskoLib.mkCreateOption {
|
||||||
|
inherit config options;
|
||||||
|
default = ''
|
||||||
|
${lib.optionalString (hp.config.mbrPartitionType != null) ''
|
||||||
|
sfdisk --label-nested dos --part-type "${parent.device}" ${(toString partition.config._index)} ${hp.config.mbrPartitionType}
|
||||||
|
udevadm trigger --subsystem-match=block
|
||||||
|
udevadm settle
|
||||||
|
''}
|
||||||
|
${lib.optionalString hp.config.mbrBootableFlag ''
|
||||||
|
sfdisk --label-nested dos --activate "${parent.device}" ${(toString partition.config._index)}
|
||||||
|
''}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
default = null;
|
||||||
|
description = "Entry to add to the Hybrid MBR table";
|
||||||
|
};
|
||||||
|
_index = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
internal = true;
|
||||||
|
default = diskoLib.indexOf (x: x.name == partition.config.name) sortedPartitions 0;
|
||||||
|
defaultText = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
default = { };
|
default = { };
|
||||||
description = "Attrs of partitions to add to the partition table";
|
description = "Attrs of partitions to add to the partition table";
|
||||||
};
|
};
|
||||||
@@ -197,12 +244,13 @@ in
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo diskoLib.jsonType;
|
type = lib.types.functionTo diskoLib.jsonType;
|
||||||
default = dev:
|
default =
|
||||||
lib.foldr lib.recursiveUpdate { } (map
|
dev:
|
||||||
(partition:
|
lib.foldr lib.recursiveUpdate { } (
|
||||||
lib.optionalAttrs (partition.content != null) (partition.content._meta dev)
|
map (partition: lib.optionalAttrs (partition.content != null) (partition.content._meta dev)) (
|
||||||
|
lib.attrValues config.partitions
|
||||||
)
|
)
|
||||||
(lib.attrValues config.partitions));
|
);
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
_create = diskoLib.mkCreateOption {
|
||||||
@@ -211,61 +259,63 @@ in
|
|||||||
if ! blkid "${config.device}" >&2; then
|
if ! blkid "${config.device}" >&2; then
|
||||||
sgdisk --clear "${config.device}"
|
sgdisk --clear "${config.device}"
|
||||||
fi
|
fi
|
||||||
${lib.concatMapStrings (partition:
|
${lib.concatMapStrings (
|
||||||
|
partition:
|
||||||
let
|
let
|
||||||
args = ''
|
args = ''
|
||||||
--partition-guid="${toString partition._index}:${if partition.uuid == null then "R" else partition.uuid}" \
|
--partition-guid="${toString partition._index}:${
|
||||||
|
if partition.uuid == null then "R" else partition.uuid
|
||||||
|
}" \
|
||||||
--change-name="${toString partition._index}:${partition.label}" \
|
--change-name="${toString partition._index}:${partition.label}" \
|
||||||
--typecode=${toString partition._index}:${partition.type} \
|
--typecode=${toString partition._index}:${partition.type} \
|
||||||
"${config.device}" \
|
"${config.device}" \
|
||||||
'';
|
'';
|
||||||
createArgs = ''
|
createArgs = ''
|
||||||
--align-end ${lib.optionalString (partition.alignment != 0) ''--set-alignment=${builtins.toString partition.alignment}''} \
|
--align-end ${
|
||||||
|
lib.optionalString (
|
||||||
|
partition.alignment != 0
|
||||||
|
) ''--set-alignment=${builtins.toString partition.alignment}''
|
||||||
|
} \
|
||||||
--new=${toString partition._index}:${partition.start}:${partition.end} \
|
--new=${toString partition._index}:${partition.start}:${partition.end} \
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
''
|
''
|
||||||
# try to create the partition, if it fails, try to change the type and name
|
# try to create the partition, if it fails, try to change the type and name
|
||||||
if ! sgdisk ${createArgs} ${args}
|
if ! sgdisk ${createArgs} ${args}
|
||||||
then
|
then
|
||||||
sgdisk ${args}
|
sgdisk ${args}
|
||||||
fi
|
fi
|
||||||
# ensure /dev/disk/by-path/..-partN exists before continuing
|
# ensure /dev/disk/by-path/..-partN exists before continuing
|
||||||
partprobe "${config.device}" || : # sometimes partprobe fails, but the partitions are still up2date
|
partprobe "${config.device}" || : # sometimes partprobe fails, but the partitions are still up2date
|
||||||
udevadm trigger --subsystem-match=block
|
udevadm trigger --subsystem-match=block
|
||||||
udevadm settle
|
udevadm settle
|
||||||
''
|
''
|
||||||
) sortedPartitions}
|
) sortedPartitions}
|
||||||
|
|
||||||
${
|
${lib.optionalString (sortedHybridPartitions != [ ]) (
|
||||||
lib.optionalString (sortedHybridPartitions != [])
|
"sgdisk -h "
|
||||||
("sgdisk -h "
|
+ (lib.concatStringsSep ":" (map (p: (toString p._index)) sortedHybridPartitions))
|
||||||
+ (lib.concatStringsSep ":" (map (p: (toString p._index)) sortedHybridPartitions))
|
+ (lib.optionalString (!config.efiGptPartitionFirst) ":EE ")
|
||||||
+ (
|
+ ''"${parent.device}"''
|
||||||
lib.optionalString (!config.efiGptPartitionFirst) ":EE "
|
)}
|
||||||
)
|
${lib.concatMapStrings (p: p.hybrid._create) sortedHybridPartitions}
|
||||||
+ ''"${parent.device}"'')
|
|
||||||
}
|
|
||||||
${lib.concatMapStrings (p:
|
|
||||||
p.hybrid._create
|
|
||||||
)
|
|
||||||
sortedHybridPartitions
|
|
||||||
}
|
|
||||||
|
|
||||||
${lib.concatStrings (map (partition: ''
|
${lib.concatStrings (
|
||||||
${lib.optionalString (partition.content != null) partition.content._create}
|
map (partition: ''
|
||||||
'') sortedPartitions)}
|
${lib.optionalString (partition.content != null) partition.content._create}
|
||||||
|
'') sortedPartitions
|
||||||
|
)}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
_mount = diskoLib.mkMountOption {
|
_mount = diskoLib.mkMountOption {
|
||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default =
|
||||||
let
|
let
|
||||||
partMounts = lib.foldr lib.recursiveUpdate { } (map
|
partMounts = lib.foldr lib.recursiveUpdate { } (
|
||||||
(partition:
|
map (partition: lib.optionalAttrs (partition.content != null) partition.content._mount) (
|
||||||
lib.optionalAttrs (partition.content != null) partition.content._mount
|
lib.attrValues config.partitions
|
||||||
)
|
)
|
||||||
(lib.attrValues config.partitions));
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
dev = partMounts.dev or "";
|
dev = partMounts.dev or "";
|
||||||
@@ -276,11 +326,11 @@ in
|
|||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default =
|
||||||
let
|
let
|
||||||
partMounts = lib.foldr lib.recursiveUpdate { } (map
|
partMounts = lib.foldr lib.recursiveUpdate { } (
|
||||||
(partition:
|
map (partition: lib.optionalAttrs (partition.content != null) partition.content._unmount) (
|
||||||
lib.optionalAttrs (partition.content != null) partition.content._unmount
|
lib.attrValues config.partitions
|
||||||
)
|
)
|
||||||
(lib.attrValues config.partitions));
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
dev = partMounts.dev or "";
|
dev = partMounts.dev or "";
|
||||||
@@ -290,30 +340,31 @@ in
|
|||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = (map
|
default =
|
||||||
(partition:
|
(map (partition: lib.optional (partition.content != null) partition.content._config) (
|
||||||
lib.optional (partition.content != null) partition.content._config
|
lib.attrValues config.partitions
|
||||||
)
|
))
|
||||||
(lib.attrValues config.partitions))
|
++ (lib.optional (lib.any (part: part.type == "EF02") (lib.attrValues config.partitions)) {
|
||||||
++ (lib.optional (lib.any (part: part.type == "EF02") (lib.attrValues config.partitions)) {
|
boot.loader.grub.devices = [ config.device ];
|
||||||
boot.loader.grub.devices = [ config.device ];
|
});
|
||||||
});
|
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
_pkgs = lib.mkOption {
|
_pkgs = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs:
|
default =
|
||||||
|
pkgs:
|
||||||
[
|
[
|
||||||
pkgs.gptfdisk
|
pkgs.gptfdisk
|
||||||
pkgs.systemdMinimal
|
pkgs.systemdMinimal
|
||||||
pkgs.parted # for partprobe
|
pkgs.parted # for partprobe
|
||||||
] ++ lib.flatten (map
|
]
|
||||||
(partition:
|
++ lib.flatten (
|
||||||
lib.optional (partition.content != null) (partition.content._pkgs pkgs)
|
map (partition: lib.optional (partition.content != null) (partition.content._pkgs pkgs)) (
|
||||||
|
lib.attrValues config.partitions
|
||||||
)
|
)
|
||||||
(lib.attrValues config.partitions));
|
);
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,20 +1,30 @@
|
|||||||
{ config, options, lib, diskoLib, parent, device, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
keyFile =
|
keyFile =
|
||||||
if config.settings ? "keyFile"
|
if config.settings ? "keyFile" then
|
||||||
then config.settings.keyFile
|
config.settings.keyFile
|
||||||
else if config.askPassword
|
else if config.askPassword then
|
||||||
then ''<(set +x; echo -n "$password"; set -x)''
|
''<(set +x; echo -n "$password"; set -x)''
|
||||||
else if config.passwordFile != null
|
else if
|
||||||
|
config.passwordFile != null
|
||||||
# do not print the password to the console
|
# do not print the password to the console
|
||||||
then ''<(set +x; echo -n "$(cat ${config.passwordFile})"; set -x)''
|
|
||||||
else if config.keyFile != null
|
|
||||||
then
|
then
|
||||||
lib.warn
|
''<(set +x; echo -n "$(cat ${config.passwordFile})"; set -x)''
|
||||||
("The option `keyFile` is deprecated."
|
else if config.keyFile != null then
|
||||||
+ "Use passwordFile instead if you want to use interactive login or settings.keyFile if you want to use key file login")
|
lib.warn (
|
||||||
config.keyFile
|
"The option `keyFile` is deprecated."
|
||||||
else null;
|
+ "Use passwordFile instead if you want to use interactive login or settings.keyFile if you want to use key file login"
|
||||||
|
) config.keyFile
|
||||||
|
else
|
||||||
|
null;
|
||||||
keyFileArgs = ''
|
keyFileArgs = ''
|
||||||
${lib.optionalString (keyFile != null) "--key-file ${keyFile}"} \
|
${lib.optionalString (keyFile != null) "--key-file ${keyFile}"} \
|
||||||
${lib.optionalString (lib.hasAttr "keyFileSize" config.settings) "--keyfile-size ${builtins.toString config.settings.keyFileSize}"} \
|
${lib.optionalString (lib.hasAttr "keyFileSize" config.settings) "--keyfile-size ${builtins.toString config.settings.keyFileSize}"} \
|
||||||
@@ -23,7 +33,10 @@ let
|
|||||||
cryptsetupOpen = ''
|
cryptsetupOpen = ''
|
||||||
cryptsetup open "${config.device}" "${config.name}" \
|
cryptsetup open "${config.device}" "${config.name}" \
|
||||||
${lib.optionalString (config.settings.allowDiscards or false) "--allow-discards"} \
|
${lib.optionalString (config.settings.allowDiscards or false) "--allow-discards"} \
|
||||||
${lib.optionalString (config.settings.bypassWorkqueues or false) "--perf-no_read_workqueue --perf-no_write_workqueue"} \
|
${
|
||||||
|
lib.optionalString (config.settings.bypassWorkqueues or false
|
||||||
|
) "--perf-no_read_workqueue --perf-no_write_workqueue"
|
||||||
|
} \
|
||||||
${toString config.extraOpenArgs} \
|
${toString config.extraOpenArgs} \
|
||||||
${keyFileArgs} \
|
${keyFileArgs} \
|
||||||
'';
|
'';
|
||||||
@@ -58,7 +71,7 @@ in
|
|||||||
};
|
};
|
||||||
askPassword = lib.mkOption {
|
askPassword = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = config.keyFile == null && config.passwordFile == null && (! config.settings ? "keyFile");
|
default = config.keyFile == null && config.passwordFile == null && (!config.settings ? "keyFile");
|
||||||
defaultText = "true if neither keyFile nor passwordFile are set";
|
defaultText = "true if neither keyFile nor passwordFile are set";
|
||||||
description = "Whether to ask for a password for initial encryption";
|
description = "Whether to ask for a password for initial encryption";
|
||||||
};
|
};
|
||||||
@@ -66,13 +79,14 @@ in
|
|||||||
type = lib.types.attrsOf lib.types.anything;
|
type = lib.types.attrsOf lib.types.anything;
|
||||||
default = { };
|
default = { };
|
||||||
description = "LUKS settings (as defined in configuration.nix in boot.initrd.luks.devices.<name>)";
|
description = "LUKS settings (as defined in configuration.nix in boot.initrd.luks.devices.<name>)";
|
||||||
example = ''{
|
example = ''
|
||||||
keyFile = "/tmp/disk.key";
|
{
|
||||||
keyFileSize = 2048;
|
keyFile = "/tmp/disk.key";
|
||||||
keyFileOffset = 1024;
|
keyFileSize = 2048;
|
||||||
fallbackToPassword = true;
|
keyFileOffset = 1024;
|
||||||
allowDiscards = true;
|
fallbackToPassword = true;
|
||||||
};
|
allowDiscards = true;
|
||||||
|
};
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
additionalKeyFiles = lib.mkOption {
|
additionalKeyFiles = lib.mkOption {
|
||||||
@@ -98,7 +112,10 @@ in
|
|||||||
description = "Extra arguments to pass to `cryptsetup luksOpen` when opening";
|
description = "Extra arguments to pass to `cryptsetup luksOpen` when opening";
|
||||||
example = [ "--timeout 10" ];
|
example = [ "--timeout 10" ];
|
||||||
};
|
};
|
||||||
content = diskoLib.deviceType { parent = config; device = "/dev/mapper/${config.name}"; };
|
content = diskoLib.deviceType {
|
||||||
|
parent = config;
|
||||||
|
device = "/dev/mapper/${config.name}";
|
||||||
|
};
|
||||||
_parent = lib.mkOption {
|
_parent = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
default = parent;
|
default = parent;
|
||||||
@@ -107,8 +124,7 @@ in
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo diskoLib.jsonType;
|
type = lib.types.functionTo diskoLib.jsonType;
|
||||||
default = dev:
|
default = dev: lib.optionalAttrs (config.content != null) (config.content._meta dev);
|
||||||
lib.optionalAttrs (config.content != null) (config.content._meta dev);
|
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
_create = diskoLib.mkCreateOption {
|
||||||
@@ -136,9 +152,11 @@ in
|
|||||||
''}
|
''}
|
||||||
cryptsetup -q luksFormat "${config.device}" ${toString config.extraFormatArgs} ${keyFileArgs}
|
cryptsetup -q luksFormat "${config.device}" ${toString config.extraFormatArgs} ${keyFileArgs}
|
||||||
${cryptsetupOpen} --persistent
|
${cryptsetupOpen} --persistent
|
||||||
${toString (lib.forEach config.additionalKeyFiles (keyFile: ''
|
${toString (
|
||||||
cryptsetup luksAddKey "${config.device}" ${keyFile} ${keyFileArgs}
|
lib.forEach config.additionalKeyFiles (keyFile: ''
|
||||||
''))}
|
cryptsetup luksAddKey "${config.device}" ${keyFile} ${keyFileArgs}
|
||||||
|
'')
|
||||||
|
)}
|
||||||
fi
|
fi
|
||||||
${lib.optionalString (config.content != null) config.content._create}
|
${lib.optionalString (config.content != null) config.content._create}
|
||||||
'';
|
'';
|
||||||
@@ -176,34 +194,42 @@ in
|
|||||||
let
|
let
|
||||||
contentUnmount = config.content._unmount;
|
contentUnmount = config.content._unmount;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
dev = ''
|
dev = ''
|
||||||
${lib.optionalString (config.content != null) contentUnmount.dev or ""}
|
${lib.optionalString (config.content != null) contentUnmount.dev or ""}
|
||||||
if cryptsetup status "${config.name}" >/dev/null 2>/dev/null; then
|
if cryptsetup status "${config.name}" >/dev/null 2>/dev/null; then
|
||||||
cryptsetup close "${config.name}"
|
cryptsetup close "${config.name}"
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = [ ]
|
default =
|
||||||
|
[ ]
|
||||||
# If initrdUnlock is true, then add a device entry to the initrd.luks.devices config.
|
# If initrdUnlock is true, then add a device entry to the initrd.luks.devices config.
|
||||||
++ (lib.optional config.initrdUnlock [
|
++ (lib.optional config.initrdUnlock [
|
||||||
{
|
{
|
||||||
boot.initrd.luks.devices.${config.name} = {
|
boot.initrd.luks.devices.${config.name} = {
|
||||||
inherit (config) device;
|
inherit (config) device;
|
||||||
} // config.settings;
|
} // config.settings;
|
||||||
}
|
}
|
||||||
]) ++ (lib.optional (config.content != null) config.content._config);
|
])
|
||||||
|
++ (lib.optional (config.content != null) config.content._config);
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
_pkgs = lib.mkOption {
|
_pkgs = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs: [ pkgs.gnugrep pkgs.cryptsetup ] ++ (lib.optionals (config.content != null) (config.content._pkgs pkgs));
|
default =
|
||||||
|
pkgs:
|
||||||
|
[
|
||||||
|
pkgs.gnugrep
|
||||||
|
pkgs.cryptsetup
|
||||||
|
]
|
||||||
|
++ (lib.optionals (config.content != null) (config.content._pkgs pkgs));
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
{ config, options, lib, diskoLib, parent, device, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
type = lib.mkOption {
|
type = lib.mkOption {
|
||||||
@@ -55,7 +63,10 @@
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs: [ pkgs.gnugrep pkgs.lvm2 ];
|
default = pkgs: [
|
||||||
|
pkgs.gnugrep
|
||||||
|
pkgs.lvm2
|
||||||
|
];
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,14 +1,22 @@
|
|||||||
{ config, options, lib, diskoLib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
# Load kernel modules to ensure device mapper types are available
|
# Load kernel modules to ensure device mapper types are available
|
||||||
kernelModules =
|
kernelModules =
|
||||||
[
|
[
|
||||||
# Prevent unbootable systems if LVM snapshots are present at boot time.
|
# Prevent unbootable systems if LVM snapshots are present at boot time.
|
||||||
"dm-snapshot"
|
"dm-snapshot"
|
||||||
] ++
|
]
|
||||||
lib.filter (x: x != "") (map
|
++ lib.filter (x: x != "") (
|
||||||
(lv: lib.optionalString (lv.lvm_type != null && lv.lvm_type != "thinlv") "dm-${lv.lvm_type}")
|
map (lv: lib.optionalString (lv.lvm_type != null && lv.lvm_type != "thinlv") "dm-${lv.lvm_type}") (
|
||||||
(lib.attrValues config.lvs));
|
lib.attrValues config.lvs
|
||||||
|
)
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
@@ -23,44 +31,65 @@ in
|
|||||||
description = "Type";
|
description = "Type";
|
||||||
};
|
};
|
||||||
lvs = lib.mkOption {
|
lvs = lib.mkOption {
|
||||||
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@lv: {
|
type = lib.types.attrsOf (
|
||||||
options = {
|
lib.types.submodule (
|
||||||
name = lib.mkOption {
|
{ name, ... }@lv:
|
||||||
type = lib.types.str;
|
{
|
||||||
default = name;
|
options = {
|
||||||
description = "Name of the logical volume";
|
name = lib.mkOption {
|
||||||
};
|
type = lib.types.str;
|
||||||
priority = lib.mkOption {
|
default = name;
|
||||||
type = lib.types.int;
|
description = "Name of the logical volume";
|
||||||
default = (if lv.config.lvm_type == "thin-pool" then 501 else 1000) + (if lib.hasInfix "100%" lv.config.size then 251 else 0);
|
};
|
||||||
defaultText = lib.literalExpression ''
|
priority = lib.mkOption {
|
||||||
if (lib.hasInfix "100%" lv.config.size) then 9001 else 1000
|
type = lib.types.int;
|
||||||
'';
|
default =
|
||||||
description = "Priority of the logical volume, smaller values are created first";
|
(if lv.config.lvm_type == "thin-pool" then 501 else 1000)
|
||||||
};
|
+ (if lib.hasInfix "100%" lv.config.size then 251 else 0);
|
||||||
size = lib.mkOption {
|
defaultText = lib.literalExpression ''
|
||||||
type = lib.types.str; # TODO lvm size type
|
if (lib.hasInfix "100%" lv.config.size) then 9001 else 1000
|
||||||
description = "Size of the logical volume";
|
'';
|
||||||
};
|
description = "Priority of the logical volume, smaller values are created first";
|
||||||
lvm_type = lib.mkOption {
|
};
|
||||||
# TODO: add raid10
|
size = lib.mkOption {
|
||||||
type = lib.types.nullOr (lib.types.enum [ "mirror" "raid0" "raid1" "raid4" "raid5" "raid6" "thin-pool" "thinlv" ]); # TODO add all lib.types
|
type = lib.types.str; # TODO lvm size type
|
||||||
default = null; # maybe there is always a default type?
|
description = "Size of the logical volume";
|
||||||
description = "LVM type";
|
};
|
||||||
};
|
lvm_type = lib.mkOption {
|
||||||
extraArgs = lib.mkOption {
|
# TODO: add raid10
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.nullOr (
|
||||||
default = [ ];
|
lib.types.enum [
|
||||||
description = "Extra arguments";
|
"mirror"
|
||||||
};
|
"raid0"
|
||||||
pool = lib.mkOption {
|
"raid1"
|
||||||
type = lib.types.nullOr lib.types.str;
|
"raid4"
|
||||||
default = null;
|
"raid5"
|
||||||
description = "Name of pool LV that this LV belongs to";
|
"raid6"
|
||||||
};
|
"thin-pool"
|
||||||
content = diskoLib.partitionType { parent = config; device = "/dev/${config.name}/${lv.config.name}"; };
|
"thinlv"
|
||||||
};
|
]
|
||||||
}));
|
); # 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";
|
||||||
|
};
|
||||||
|
pool = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Name of pool LV that this LV belongs to";
|
||||||
|
};
|
||||||
|
content = diskoLib.partitionType {
|
||||||
|
parent = config;
|
||||||
|
device = "/dev/${config.name}/${lv.config.name}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
default = { };
|
default = { };
|
||||||
description = "LVS for the volume group";
|
description = "LVS for the volume group";
|
||||||
};
|
};
|
||||||
@@ -68,12 +97,15 @@ in
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = diskoLib.jsonType;
|
type = diskoLib.jsonType;
|
||||||
default =
|
default = diskoLib.deepMergeMap (
|
||||||
diskoLib.deepMergeMap
|
lv:
|
||||||
(lv:
|
lib.optionalAttrs (lv.content != null) (
|
||||||
lib.optionalAttrs (lv.content != null) (lv.content._meta [ "lvm_vg" config.name ])
|
lv.content._meta [
|
||||||
)
|
"lvm_vg"
|
||||||
(lib.attrValues config.lvs);
|
config.name
|
||||||
|
]
|
||||||
|
)
|
||||||
|
) (lib.attrValues config.lvs);
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
_create = diskoLib.mkCreateOption {
|
||||||
@@ -93,8 +125,14 @@ in
|
|||||||
if ! lvdisplay "${config.name}/${lv.name}"; then
|
if ! lvdisplay "${config.name}/${lv.name}"; then
|
||||||
lvcreate \
|
lvcreate \
|
||||||
--yes \
|
--yes \
|
||||||
${if (lv.lvm_type == "thinlv") then "-V"
|
${
|
||||||
else if lib.hasInfix "%" lv.size then "-l" else "-L"} \
|
if (lv.lvm_type == "thinlv") then
|
||||||
|
"-V"
|
||||||
|
else if lib.hasInfix "%" lv.size then
|
||||||
|
"-l"
|
||||||
|
else
|
||||||
|
"-L"
|
||||||
|
} \
|
||||||
${if lib.hasSuffix "%" lv.size then "${lv.size}FREE" else lv.size} \
|
${if lib.hasSuffix "%" lv.size then "${lv.size}FREE" else lv.size} \
|
||||||
-n "${lv.name}" \
|
-n "${lv.name}" \
|
||||||
${lib.optionalString (lv.lvm_type == "thinlv") "--thinpool=${lv.pool}"} \
|
${lib.optionalString (lv.lvm_type == "thinlv") "--thinpool=${lv.pool}"} \
|
||||||
@@ -113,11 +151,9 @@ in
|
|||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default =
|
||||||
let
|
let
|
||||||
lvMounts = diskoLib.deepMergeMap
|
lvMounts = diskoLib.deepMergeMap (lv: lib.optionalAttrs (lv.content != null) lv.content._mount) (
|
||||||
(lv:
|
lib.attrValues config.lvs
|
||||||
lib.optionalAttrs (lv.content != null) lv.content._mount
|
);
|
||||||
)
|
|
||||||
(lib.attrValues config.lvs);
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
dev = ''
|
dev = ''
|
||||||
@@ -131,12 +167,11 @@ in
|
|||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default =
|
||||||
let
|
let
|
||||||
lvMounts = diskoLib.deepMergeMap
|
lvMounts = diskoLib.deepMergeMap (lv: lib.optionalAttrs (lv.content != null) lv.content._unmount) (
|
||||||
(lv:
|
lib.attrValues config.lvs
|
||||||
lib.optionalAttrs (lv.content != null) lv.content._unmount
|
);
|
||||||
)
|
in
|
||||||
(lib.attrValues config.lvs);
|
{
|
||||||
in {
|
|
||||||
dev = ''
|
dev = ''
|
||||||
${lib.concatMapStrings (x: x.dev or "") (lib.attrValues lvMounts)}
|
${lib.concatMapStrings (x: x.dev or "") (lib.attrValues lvMounts)}
|
||||||
vgchange -a n
|
vgchange -a n
|
||||||
@@ -147,36 +182,35 @@ in
|
|||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = [{ boot.initrd.kernelModules = kernelModules; }] ++
|
default =
|
||||||
map
|
[ { boot.initrd.kernelModules = kernelModules; } ]
|
||||||
(lv: [
|
++ map (lv: [
|
||||||
(lib.optional (lv.content != null) lv.content._config)
|
(lib.optional (lv.content != null) lv.content._config)
|
||||||
(lib.optional (lv.lvm_type != null) {
|
(lib.optional (lv.lvm_type != null) {
|
||||||
boot.initrd.kernelModules = [
|
boot.initrd.kernelModules =
|
||||||
|
[
|
||||||
(if lv.lvm_type == "mirror" then "dm-mirror" else "dm-raid")
|
(if lv.lvm_type == "mirror" then "dm-mirror" else "dm-raid")
|
||||||
]
|
]
|
||||||
++ lib.optional (lv.lvm_type == "raid0") "raid0"
|
++ lib.optional (lv.lvm_type == "raid0") "raid0"
|
||||||
++ lib.optional (lv.lvm_type == "raid1") "raid1"
|
++ lib.optional (lv.lvm_type == "raid1") "raid1"
|
||||||
# ++ lib.optional (lv.lvm_type == "raid10") "raid10"
|
# ++ lib.optional (lv.lvm_type == "raid10") "raid10"
|
||||||
++ lib.optional
|
++ lib.optional (
|
||||||
(lv.lvm_type == "raid4" ||
|
lv.lvm_type == "raid4" || lv.lvm_type == "raid5" || lv.lvm_type == "raid6"
|
||||||
lv.lvm_type == "raid5" ||
|
) "raid456";
|
||||||
lv.lvm_type == "raid6") "raid456";
|
|
||||||
|
|
||||||
})
|
})
|
||||||
])
|
]) (lib.attrValues config.lvs);
|
||||||
(lib.attrValues config.lvs);
|
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
_pkgs = lib.mkOption {
|
_pkgs = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs: lib.flatten (map
|
default =
|
||||||
(lv:
|
pkgs:
|
||||||
lib.optional (lv.content != null) (lv.content._pkgs pkgs)
|
lib.flatten (
|
||||||
)
|
map (lv: lib.optional (lv.content != null) (lv.content._pkgs pkgs)) (lib.attrValues config.lvs)
|
||||||
(lib.attrValues config.lvs));
|
);
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
{ config, options, lib, diskoLib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
name = lib.mkOption {
|
name = lib.mkOption {
|
||||||
@@ -18,17 +24,32 @@
|
|||||||
description = "mdadm level";
|
description = "mdadm level";
|
||||||
};
|
};
|
||||||
metadata = lib.mkOption {
|
metadata = lib.mkOption {
|
||||||
type = lib.types.enum [ "1" "1.0" "1.1" "1.2" "default" "ddf" "imsm" ];
|
type = lib.types.enum [
|
||||||
|
"1"
|
||||||
|
"1.0"
|
||||||
|
"1.1"
|
||||||
|
"1.2"
|
||||||
|
"default"
|
||||||
|
"ddf"
|
||||||
|
"imsm"
|
||||||
|
];
|
||||||
default = "default";
|
default = "default";
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
content = diskoLib.deviceType { parent = config; device = "/dev/md/${config.name}"; };
|
content = diskoLib.deviceType {
|
||||||
|
parent = config;
|
||||||
|
device = "/dev/md/${config.name}";
|
||||||
|
};
|
||||||
_meta = lib.mkOption {
|
_meta = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = diskoLib.jsonType;
|
type = diskoLib.jsonType;
|
||||||
default =
|
default = lib.optionalAttrs (config.content != null) (
|
||||||
lib.optionalAttrs (config.content != null) (config.content._meta [ "mdadm" config.name ]);
|
config.content._meta [
|
||||||
|
"mdadm"
|
||||||
|
config.name
|
||||||
|
]
|
||||||
|
);
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
_create = diskoLib.mkCreateOption {
|
||||||
@@ -54,45 +75,52 @@
|
|||||||
};
|
};
|
||||||
_mount = diskoLib.mkMountOption {
|
_mount = diskoLib.mkMountOption {
|
||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default = lib.optionalAttrs (config.content != null) config.content._mount;
|
||||||
lib.optionalAttrs (config.content != null) config.content._mount;
|
|
||||||
# TODO we probably need to assemble the mdadm somehow
|
# TODO we probably need to assemble the mdadm somehow
|
||||||
};
|
};
|
||||||
_unmount = diskoLib.mkUnmountOption {
|
_unmount = diskoLib.mkUnmountOption {
|
||||||
inherit config options;
|
inherit config options;
|
||||||
default = let
|
default =
|
||||||
content = lib.optionalAttrs (config.content != null) config.content._unmount;
|
let
|
||||||
in {
|
content = lib.optionalAttrs (config.content != null) config.content._unmount;
|
||||||
fs = content.fs;
|
in
|
||||||
dev = ''
|
{
|
||||||
${content.dev or ""}
|
fs = content.fs;
|
||||||
if [ -e "/dev/md/${config.name}" ]; then
|
dev = ''
|
||||||
mdadm --stop "/dev/md/${config.name}"
|
${content.dev or ""}
|
||||||
fi
|
if [ -e "/dev/md/${config.name}" ]; then
|
||||||
'';
|
mdadm --stop "/dev/md/${config.name}"
|
||||||
};
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default =
|
default = [
|
||||||
[
|
(
|
||||||
(if lib.versionAtLeast (lib.versions.majorMinor lib.version) "23.11" then {
|
if lib.versionAtLeast (lib.versions.majorMinor lib.version) "23.11" then
|
||||||
boot.swraid.enable = true;
|
{
|
||||||
} else {
|
boot.swraid.enable = true;
|
||||||
boot.initrd.services.swraid.enable = true;
|
}
|
||||||
})
|
else
|
||||||
] ++
|
{
|
||||||
lib.optional (config.content != null) config.content._config;
|
boot.initrd.services.swraid.enable = true;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
] ++ lib.optional (config.content != null) config.content._config;
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
_pkgs = lib.mkOption {
|
_pkgs = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs: [
|
default =
|
||||||
pkgs.parted # for partprobe
|
pkgs:
|
||||||
] ++ (lib.optionals (config.content != null) (config.content._pkgs pkgs));
|
[
|
||||||
|
pkgs.parted # for partprobe
|
||||||
|
]
|
||||||
|
++ (lib.optionals (config.content != null) (config.content._pkgs pkgs));
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
{ config, options, lib, diskoLib, parent, device, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
type = lib.mkOption {
|
type = lib.mkOption {
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
{ lib, config, options, diskoLib, rootMountPoint, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
diskoLib,
|
||||||
|
rootMountPoint,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
type = lib.mkOption {
|
type = lib.mkOption {
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
{ diskoLib, config, options, lib, parent, device, ... }:
|
{
|
||||||
|
diskoLib,
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
type = lib.mkOption {
|
type = lib.mkOption {
|
||||||
@@ -14,7 +22,13 @@
|
|||||||
discardPolicy = lib.mkOption {
|
discardPolicy = lib.mkOption {
|
||||||
default = null;
|
default = null;
|
||||||
example = "once";
|
example = "once";
|
||||||
type = lib.types.nullOr (lib.types.enum [ "once" "pages" "both" ]);
|
type = lib.types.nullOr (
|
||||||
|
lib.types.enum [
|
||||||
|
"once"
|
||||||
|
"pages"
|
||||||
|
"both"
|
||||||
|
]
|
||||||
|
);
|
||||||
description = ''
|
description = ''
|
||||||
Specify the discard policy for the swap device. If "once", then the
|
Specify the discard policy for the swap device. If "once", then the
|
||||||
whole swap space is discarded at swapon invocation. If "pages",
|
whole swap space is discarded at swapon invocation. If "pages",
|
||||||
@@ -83,12 +97,8 @@
|
|||||||
if test "''${DISKO_SKIP_SWAP:-}" != 1 && ! swapon --show | grep -q "^$(readlink -f "${config.device}") "; then
|
if test "''${DISKO_SKIP_SWAP:-}" != 1 && ! swapon --show | grep -q "^$(readlink -f "${config.device}") "; then
|
||||||
swapon ${
|
swapon ${
|
||||||
lib.optionalString (config.discardPolicy != null)
|
lib.optionalString (config.discardPolicy != null)
|
||||||
"--discard${lib.optionalString (config.discardPolicy != "both")
|
"--discard${lib.optionalString (config.discardPolicy != "both") "=${config.discardPolicy}"}"
|
||||||
"=${config.discardPolicy}"
|
} ${lib.optionalString (config.priority != null) "--priority=${toString config.priority}"} \
|
||||||
}"} ${
|
|
||||||
lib.optionalString (config.priority != null)
|
|
||||||
"--priority=${toString config.priority}"
|
|
||||||
} \
|
|
||||||
--options=${lib.concatStringsSep "," config.mountOptions} \
|
--options=${lib.concatStringsSep "," config.mountOptions} \
|
||||||
"${config.device}"
|
"${config.device}"
|
||||||
fi
|
fi
|
||||||
@@ -108,26 +118,33 @@
|
|||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = [{
|
default = [
|
||||||
swapDevices = [{
|
{
|
||||||
device = config.device;
|
swapDevices = [
|
||||||
inherit (config) discardPolicy priority;
|
{
|
||||||
randomEncryption = {
|
device = config.device;
|
||||||
enable = config.randomEncryption;
|
inherit (config) discardPolicy priority;
|
||||||
# forward discard/TRIM attempts through dm-crypt
|
randomEncryption = {
|
||||||
allowDiscards = config.discardPolicy != null;
|
enable = config.randomEncryption;
|
||||||
};
|
# forward discard/TRIM attempts through dm-crypt
|
||||||
options = config.mountOptions;
|
allowDiscards = config.discardPolicy != null;
|
||||||
}];
|
};
|
||||||
boot.resumeDevice = lib.mkIf config.resumeDevice config.device;
|
options = config.mountOptions;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
boot.resumeDevice = lib.mkIf config.resumeDevice config.device;
|
||||||
|
}
|
||||||
|
];
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
_pkgs = lib.mkOption {
|
_pkgs = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs: [ pkgs.gnugrep pkgs.util-linux ];
|
default = pkgs: [
|
||||||
|
pkgs.gnugrep
|
||||||
|
pkgs.util-linux
|
||||||
|
];
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,179 +1,227 @@
|
|||||||
{ config, options, lib, diskoLib, parent, device, ... }:
|
|
||||||
{
|
{
|
||||||
options = lib.warn ''
|
config,
|
||||||
The legacy table is outdated and should not be used. We recommend using the gpt type instead.
|
options,
|
||||||
Please note that certain features, such as the test framework, may not function properly with the legacy table type.
|
lib,
|
||||||
If you encounter errors similar to:
|
diskoLib,
|
||||||
"error: The option `disko.devices.disk.disk1.content.partitions."[definition 1-entry 1]".content._config` is read-only, but it's set multiple times,"
|
parent,
|
||||||
this is likely due to the use of the legacy table type.
|
device,
|
||||||
for a migration you can follow the guide at https://github.com/nix-community/disko/blob/master/docs/table-to-gpt.md
|
...
|
||||||
''
|
}:
|
||||||
{
|
{
|
||||||
type = lib.mkOption {
|
options =
|
||||||
type = lib.types.enum [ "table" ];
|
lib.warn
|
||||||
internal = true;
|
''
|
||||||
description = "Partition table";
|
The legacy table is outdated and should not be used. We recommend using the gpt type instead.
|
||||||
};
|
Please note that certain features, such as the test framework, may not function properly with the legacy table type.
|
||||||
device = lib.mkOption {
|
If you encounter errors similar to:
|
||||||
type = lib.types.str;
|
"error: The option `disko.devices.disk.disk1.content.partitions."[definition 1-entry 1]".content._config` is read-only, but it's set multiple times,"
|
||||||
default = device;
|
this is likely due to the use of the legacy table type.
|
||||||
description = "Device to partition";
|
for a migration you can follow the guide at https://github.com/nix-community/disko/blob/master/docs/table-to-gpt.md
|
||||||
};
|
''
|
||||||
format = lib.mkOption {
|
{
|
||||||
type = lib.types.enum [ "gpt" "msdos" ];
|
type = lib.mkOption {
|
||||||
default = "gpt";
|
type = lib.types.enum [ "table" ];
|
||||||
description = "The kind of partition table";
|
internal = true;
|
||||||
};
|
description = "Partition table";
|
||||||
partitions = lib.mkOption {
|
};
|
||||||
type = lib.types.listOf (lib.types.submodule ({ name, ... }@partition: {
|
device = lib.mkOption {
|
||||||
options = {
|
type = lib.types.str;
|
||||||
part-type = lib.mkOption {
|
default = device;
|
||||||
type = lib.types.enum [ "primary" "logical" "extended" ];
|
description = "Device to partition";
|
||||||
default = "primary";
|
};
|
||||||
description = "Partition type";
|
format = lib.mkOption {
|
||||||
};
|
type = lib.types.enum [
|
||||||
fs-type = lib.mkOption {
|
"gpt"
|
||||||
type = lib.types.nullOr (lib.types.enum [ "btrfs" "ext2" "ext3" "ext4" "fat16" "fat32" "hfs" "hfs+" "linux-swap" "ntfs" "reiserfs" "udf" "xfs" ]);
|
"msdos"
|
||||||
default = null;
|
];
|
||||||
description = "Filesystem type to use";
|
default = "gpt";
|
||||||
};
|
description = "The kind of partition table";
|
||||||
name = lib.mkOption {
|
};
|
||||||
type = lib.types.nullOr lib.types.str;
|
partitions = lib.mkOption {
|
||||||
description = "Name of the partition";
|
type = lib.types.listOf (
|
||||||
};
|
lib.types.submodule (
|
||||||
start = lib.mkOption {
|
{ name, ... }@partition:
|
||||||
type = lib.types.str;
|
{
|
||||||
default = "0%";
|
options = {
|
||||||
description = "Start of the partition";
|
part-type = lib.mkOption {
|
||||||
};
|
type = lib.types.enum [
|
||||||
end = lib.mkOption {
|
"primary"
|
||||||
type = lib.types.str;
|
"logical"
|
||||||
default = "100%";
|
"extended"
|
||||||
description = "End of the partition";
|
];
|
||||||
};
|
default = "primary";
|
||||||
flags = lib.mkOption {
|
description = "Partition type";
|
||||||
type = lib.types.listOf lib.types.str;
|
};
|
||||||
default = [ ];
|
fs-type = lib.mkOption {
|
||||||
description = "Partition flags";
|
type = lib.types.nullOr (
|
||||||
};
|
lib.types.enum [
|
||||||
bootable = lib.mkOption {
|
"btrfs"
|
||||||
type = lib.types.bool;
|
"ext2"
|
||||||
default = false;
|
"ext3"
|
||||||
description = "Whether to make the partition bootable";
|
"ext4"
|
||||||
};
|
"fat16"
|
||||||
content = diskoLib.partitionType { parent = config; device = diskoLib.deviceNumbering config.device partition.config._index; };
|
"fat32"
|
||||||
_index = lib.mkOption {
|
"hfs"
|
||||||
type = lib.types.int;
|
"hfs+"
|
||||||
internal = true;
|
"linux-swap"
|
||||||
default = lib.toInt (lib.head (builtins.match ".*entry ([[:digit:]]+)]" name));
|
"ntfs"
|
||||||
defaultText = null;
|
"reiserfs"
|
||||||
};
|
"udf"
|
||||||
};
|
"xfs"
|
||||||
}));
|
]
|
||||||
default = [ ];
|
);
|
||||||
description = "List of partitions to add to the partition table";
|
default = null;
|
||||||
};
|
description = "Filesystem type to use";
|
||||||
_parent = lib.mkOption {
|
};
|
||||||
internal = true;
|
name = lib.mkOption {
|
||||||
default = parent;
|
type = lib.types.nullOr lib.types.str;
|
||||||
};
|
description = "Name of the partition";
|
||||||
_meta = lib.mkOption {
|
};
|
||||||
internal = true;
|
start = lib.mkOption {
|
||||||
readOnly = true;
|
type = lib.types.str;
|
||||||
type = lib.types.functionTo diskoLib.jsonType;
|
default = "0%";
|
||||||
default = dev:
|
description = "Start of the partition";
|
||||||
lib.foldr lib.recursiveUpdate { } (lib.imap
|
};
|
||||||
(_index: partition:
|
end = lib.mkOption {
|
||||||
lib.optionalAttrs (partition.content != null) (partition.content._meta dev)
|
type = lib.types.str;
|
||||||
|
default = "100%";
|
||||||
|
description = "End 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 {
|
||||||
|
parent = config;
|
||||||
|
device = diskoLib.deviceNumbering config.device partition.config._index;
|
||||||
|
};
|
||||||
|
_index = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
internal = true;
|
||||||
|
default = lib.toInt (lib.head (builtins.match ".*entry ([[:digit:]]+)]" name));
|
||||||
|
defaultText = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
)
|
)
|
||||||
config.partitions);
|
);
|
||||||
description = "Metadata";
|
default = [ ];
|
||||||
|
description = "List of partitions to add to the partition table";
|
||||||
|
};
|
||||||
|
_parent = lib.mkOption {
|
||||||
|
internal = true;
|
||||||
|
default = parent;
|
||||||
|
};
|
||||||
|
_meta = lib.mkOption {
|
||||||
|
internal = true;
|
||||||
|
readOnly = true;
|
||||||
|
type = lib.types.functionTo diskoLib.jsonType;
|
||||||
|
default =
|
||||||
|
dev:
|
||||||
|
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 = ''
|
||||||
|
if ! blkid "${config.device}" >/dev/null; then
|
||||||
|
parted -s "${config.device}" -- mklabel ${config.format}
|
||||||
|
${lib.concatStrings (
|
||||||
|
map (partition: ''
|
||||||
|
${lib.optionalString (config.format == "gpt") ''
|
||||||
|
parted -s "${config.device}" -- mkpart "${diskoLib.hexEscapeUdevSymlink partition.name}" ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end}
|
||||||
|
''}
|
||||||
|
${lib.optionalString (config.format == "msdos") ''
|
||||||
|
parted -s "${config.device}" -- mkpart ${partition.part-type} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end}
|
||||||
|
''}
|
||||||
|
# ensure /dev/disk/by-path/..-partN exists before continuing
|
||||||
|
partprobe "${config.device}"
|
||||||
|
udevadm trigger --subsystem-match=block
|
||||||
|
udevadm settle
|
||||||
|
${lib.optionalString partition.bootable ''
|
||||||
|
parted -s "${config.device}" -- set ${toString partition._index} boot on
|
||||||
|
''}
|
||||||
|
${lib.concatMapStringsSep "" (flag: ''
|
||||||
|
parted -s "${config.device}" -- set ${toString partition._index} ${flag} on
|
||||||
|
'') partition.flags}
|
||||||
|
# ensure further operations can detect new partitions
|
||||||
|
partprobe "${config.device}"
|
||||||
|
udevadm trigger --subsystem-match=block
|
||||||
|
udevadm settle
|
||||||
|
'') config.partitions
|
||||||
|
)}
|
||||||
|
fi
|
||||||
|
${lib.concatStrings (
|
||||||
|
map (partition: ''
|
||||||
|
${lib.optionalString (partition.content != null) partition.content._create}
|
||||||
|
'') config.partitions
|
||||||
|
)}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
_mount = diskoLib.mkMountOption {
|
||||||
|
inherit config options;
|
||||||
|
default =
|
||||||
|
let
|
||||||
|
partMounts = lib.foldr lib.recursiveUpdate { } (
|
||||||
|
map (
|
||||||
|
partition: lib.optionalAttrs (partition.content != null) partition.content._mount
|
||||||
|
) config.partitions
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
dev = partMounts.dev or "";
|
||||||
|
fs = partMounts.fs or { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_unmount = diskoLib.mkUnmountOption {
|
||||||
|
inherit config options;
|
||||||
|
default =
|
||||||
|
let
|
||||||
|
partMounts = lib.foldr lib.recursiveUpdate { } (
|
||||||
|
map (
|
||||||
|
partition: lib.optionalAttrs (partition.content != null) partition.content._unmount
|
||||||
|
) config.partitions
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
dev = partMounts.dev or "";
|
||||||
|
fs = partMounts.fs or { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_config = lib.mkOption {
|
||||||
|
internal = true;
|
||||||
|
readOnly = true;
|
||||||
|
default = map (
|
||||||
|
partition: lib.optional (partition.content != null) partition.content._config
|
||||||
|
) config.partitions;
|
||||||
|
description = "NixOS configuration";
|
||||||
|
};
|
||||||
|
_pkgs = lib.mkOption {
|
||||||
|
internal = true;
|
||||||
|
readOnly = true;
|
||||||
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
|
default =
|
||||||
|
pkgs:
|
||||||
|
[
|
||||||
|
pkgs.parted
|
||||||
|
pkgs.systemdMinimal
|
||||||
|
]
|
||||||
|
++ lib.flatten (
|
||||||
|
map (
|
||||||
|
partition: lib.optional (partition.content != null) (partition.content._pkgs pkgs)
|
||||||
|
) config.partitions
|
||||||
|
);
|
||||||
|
description = "Packages";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
|
||||||
inherit config options;
|
|
||||||
default = ''
|
|
||||||
if ! blkid "${config.device}" >/dev/null; then
|
|
||||||
parted -s "${config.device}" -- mklabel ${config.format}
|
|
||||||
${lib.concatStrings (map (partition: ''
|
|
||||||
${lib.optionalString (config.format == "gpt") ''
|
|
||||||
parted -s "${config.device}" -- mkpart "${diskoLib.hexEscapeUdevSymlink partition.name}" ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end}
|
|
||||||
''}
|
|
||||||
${lib.optionalString (config.format == "msdos") ''
|
|
||||||
parted -s "${config.device}" -- mkpart ${partition.part-type} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end}
|
|
||||||
''}
|
|
||||||
# ensure /dev/disk/by-path/..-partN exists before continuing
|
|
||||||
partprobe "${config.device}"
|
|
||||||
udevadm trigger --subsystem-match=block
|
|
||||||
udevadm settle
|
|
||||||
${lib.optionalString partition.bootable ''
|
|
||||||
parted -s "${config.device}" -- set ${toString partition._index} boot on
|
|
||||||
''}
|
|
||||||
${lib.concatMapStringsSep "" (flag: ''
|
|
||||||
parted -s "${config.device}" -- set ${toString partition._index} ${flag} on
|
|
||||||
'') partition.flags}
|
|
||||||
# ensure further operations can detect new partitions
|
|
||||||
partprobe "${config.device}"
|
|
||||||
udevadm trigger --subsystem-match=block
|
|
||||||
udevadm settle
|
|
||||||
'') config.partitions)}
|
|
||||||
fi
|
|
||||||
${lib.concatStrings (map (partition: ''
|
|
||||||
${lib.optionalString (partition.content != null) partition.content._create}
|
|
||||||
'') config.partitions)}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
_mount = diskoLib.mkMountOption {
|
|
||||||
inherit config options;
|
|
||||||
default =
|
|
||||||
let
|
|
||||||
partMounts = lib.foldr lib.recursiveUpdate { } (map
|
|
||||||
(partition:
|
|
||||||
lib.optionalAttrs (partition.content != null) partition.content._mount
|
|
||||||
)
|
|
||||||
config.partitions);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
dev = partMounts.dev or "";
|
|
||||||
fs = partMounts.fs or { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
_unmount = diskoLib.mkUnmountOption {
|
|
||||||
inherit config options;
|
|
||||||
default =
|
|
||||||
let
|
|
||||||
partMounts = lib.foldr lib.recursiveUpdate { } (map
|
|
||||||
(partition:
|
|
||||||
lib.optionalAttrs (partition.content != null) partition.content._unmount
|
|
||||||
)
|
|
||||||
config.partitions);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
dev = partMounts.dev or "";
|
|
||||||
fs = partMounts.fs or { };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
_config = lib.mkOption {
|
|
||||||
internal = true;
|
|
||||||
readOnly = true;
|
|
||||||
default =
|
|
||||||
map
|
|
||||||
(partition:
|
|
||||||
lib.optional (partition.content != null) partition.content._config
|
|
||||||
)
|
|
||||||
config.partitions;
|
|
||||||
description = "NixOS configuration";
|
|
||||||
};
|
|
||||||
_pkgs = lib.mkOption {
|
|
||||||
internal = true;
|
|
||||||
readOnly = true;
|
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
|
||||||
default = pkgs:
|
|
||||||
[ pkgs.parted pkgs.systemdMinimal ] ++ lib.flatten (map
|
|
||||||
(partition:
|
|
||||||
lib.optional (partition.content != null) (partition.content._pkgs pkgs)
|
|
||||||
)
|
|
||||||
config.partitions);
|
|
||||||
description = "Packages";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
{ config, options, lib, diskoLib, parent, device, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
parent,
|
||||||
|
device,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
type = lib.mkOption {
|
type = lib.mkOption {
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
{ config, options, lib, diskoLib, rootMountPoint, parent, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
rootMountPoint,
|
||||||
|
parent,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
name = lib.mkOption {
|
name = lib.mkOption {
|
||||||
@@ -58,45 +66,53 @@
|
|||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
_create = diskoLib.mkCreateOption
|
_create = diskoLib.mkCreateOption {
|
||||||
{
|
inherit config options;
|
||||||
inherit config options;
|
# -u prevents mounting newly created datasets, which is
|
||||||
# -u prevents mounting newly created datasets, which is
|
# important to prevent accidental shadowing of mount points
|
||||||
# important to prevent accidental shadowing of mount points
|
# since (create order != mount order)
|
||||||
# since (create order != mount order)
|
# -p creates parents automatically
|
||||||
# -p creates parents automatically
|
default =
|
||||||
default =
|
let
|
||||||
let
|
createOptions =
|
||||||
createOptions = (lib.optionalAttrs (config.mountpoint != null) { mountpoint = config.mountpoint; }) // config.options;
|
(lib.optionalAttrs (config.mountpoint != null) { mountpoint = config.mountpoint; })
|
||||||
# All options defined as PROP_ONETIME or PROP_ONETIME_DEFAULT in https://github.com/openzfs/zfs/blob/master/module/zcommon/zfs_prop.c
|
// config.options;
|
||||||
onetimeProperties = [
|
# All options defined as PROP_ONETIME or PROP_ONETIME_DEFAULT in https://github.com/openzfs/zfs/blob/master/module/zcommon/zfs_prop.c
|
||||||
"encryption"
|
onetimeProperties = [
|
||||||
"casesensitivity"
|
"encryption"
|
||||||
"utf8only"
|
"casesensitivity"
|
||||||
"normalization"
|
"utf8only"
|
||||||
"volblocksize"
|
"normalization"
|
||||||
"pbkdf2iters"
|
"volblocksize"
|
||||||
"pbkdf2salt"
|
"pbkdf2iters"
|
||||||
"keyformat"
|
"pbkdf2salt"
|
||||||
];
|
"keyformat"
|
||||||
updateOptions = builtins.removeAttrs createOptions onetimeProperties;
|
];
|
||||||
in
|
updateOptions = builtins.removeAttrs createOptions onetimeProperties;
|
||||||
''
|
in
|
||||||
if ! zfs get type ${config._name} >/dev/null 2>&1; then
|
''
|
||||||
${if config._createFilesystem then ''
|
if ! zfs get type ${config._name} >/dev/null 2>&1; then
|
||||||
zfs create -up ${config._name} \
|
${
|
||||||
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") (createOptions))}
|
if config._createFilesystem then
|
||||||
'' else ''
|
''
|
||||||
# don't create anything for root dataset of zpools
|
zfs create -up ${config._name} \
|
||||||
true
|
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") (createOptions))}
|
||||||
''}
|
''
|
||||||
${lib.optionalString (updateOptions != {}) ''
|
else
|
||||||
|
''
|
||||||
|
# don't create anything for root dataset of zpools
|
||||||
|
true
|
||||||
|
''
|
||||||
|
}
|
||||||
|
${lib.optionalString (updateOptions != { }) ''
|
||||||
else
|
else
|
||||||
zfs set -u ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "${n}=${v}") updateOptions)} ${config._name}
|
zfs set -u ${
|
||||||
''}
|
lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "${n}=${v}") updateOptions)
|
||||||
fi
|
} ${config._name}
|
||||||
'';
|
''}
|
||||||
};
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
_mount = diskoLib.mkMountOption {
|
_mount = diskoLib.mkMountOption {
|
||||||
inherit config options;
|
inherit config options;
|
||||||
@@ -107,17 +123,20 @@
|
|||||||
zfs load-key ${config._name}
|
zfs load-key ${config._name}
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
}) // lib.optionalAttrs (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") {
|
})
|
||||||
fs.${config.mountpoint} = ''
|
// lib.optionalAttrs
|
||||||
if ! findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
|
(config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off")
|
||||||
mount ${config._name} "${rootMountPoint}${config.mountpoint}" \
|
{
|
||||||
-o X-mount.mkdir \
|
fs.${config.mountpoint} = ''
|
||||||
${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \
|
if ! findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
|
||||||
${lib.optionalString ((config.options.mountpoint or "") != "legacy") "-o zfsutil"} \
|
mount ${config._name} "${rootMountPoint}${config.mountpoint}" \
|
||||||
-t zfs
|
-o X-mount.mkdir \
|
||||||
fi
|
${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \
|
||||||
'';
|
${lib.optionalString ((config.options.mountpoint or "") != "legacy") "-o zfsutil"} \
|
||||||
};
|
-t zfs
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_unmount = diskoLib.mkUnmountOption {
|
_unmount = diskoLib.mkUnmountOption {
|
||||||
@@ -125,26 +144,32 @@
|
|||||||
default =
|
default =
|
||||||
(lib.optionalAttrs (config.options.keylocation or "none" != "none") {
|
(lib.optionalAttrs (config.options.keylocation or "none" != "none") {
|
||||||
dev = "zfs unload-key ${config.name}";
|
dev = "zfs unload-key ${config.name}";
|
||||||
}) // lib.optionalAttrs (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") {
|
})
|
||||||
fs.${config.mountpoint} = ''
|
// lib.optionalAttrs
|
||||||
if findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
|
(config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off")
|
||||||
umount "${rootMountPoint}${config.mountpoint}"
|
{
|
||||||
fi
|
fs.${config.mountpoint} = ''
|
||||||
'';
|
if findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
|
||||||
};
|
umount "${rootMountPoint}${config.mountpoint}"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default =
|
default =
|
||||||
lib.optional (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") {
|
lib.optional (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off")
|
||||||
fileSystems.${config.mountpoint} = {
|
{
|
||||||
device = "${config._name}";
|
fileSystems.${config.mountpoint} = {
|
||||||
fsType = "zfs";
|
device = "${config._name}";
|
||||||
options = config.mountOptions ++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil";
|
fsType = "zfs";
|
||||||
|
options =
|
||||||
|
config.mountOptions
|
||||||
|
++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,4 +182,3 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
{ config, options, lib, diskoLib, parent, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
parent,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
name = lib.mkOption {
|
name = lib.mkOption {
|
||||||
@@ -35,7 +42,10 @@
|
|||||||
description = "Size of the dataset";
|
description = "Size of the dataset";
|
||||||
};
|
};
|
||||||
|
|
||||||
content = diskoLib.partitionType { parent = config; device = "/dev/zvol/${config._parent.name}/${config.name}"; };
|
content = diskoLib.partitionType {
|
||||||
|
parent = config;
|
||||||
|
device = "/dev/zvol/${config._parent.name}/${config.name}";
|
||||||
|
};
|
||||||
|
|
||||||
_parent = lib.mkOption {
|
_parent = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
@@ -45,8 +55,7 @@
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo diskoLib.jsonType;
|
type = lib.types.functionTo diskoLib.jsonType;
|
||||||
default = dev:
|
default = dev: lib.optionalAttrs (config.content != null) (config.content._meta dev);
|
||||||
lib.optionalAttrs (config.content != null) (config.content._meta dev);
|
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
_create = diskoLib.mkCreateOption {
|
||||||
@@ -83,31 +92,34 @@
|
|||||||
inherit config options;
|
inherit config options;
|
||||||
default = {
|
default = {
|
||||||
dev = ''
|
dev = ''
|
||||||
${lib.optionalString (config.options.keylocation or "none" != "none") "zfs unload-key ${config.name}"}
|
${lib.optionalString (
|
||||||
|
config.options.keylocation or "none" != "none"
|
||||||
|
) "zfs unload-key ${config.name}"}
|
||||||
|
|
||||||
${config.content._unmount.dev or ""}
|
${config.content._unmount.dev or ""}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
fs = config.content._unmount.fs or {};
|
fs = config.content._unmount.fs or { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default =
|
default = lib.optional (config.content != null) config.content._config;
|
||||||
lib.optional (config.content != null) config.content._config;
|
|
||||||
description = "NixOS configuration";
|
description = "NixOS configuration";
|
||||||
};
|
};
|
||||||
_pkgs = lib.mkOption {
|
_pkgs = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs: [
|
default =
|
||||||
pkgs.util-linux
|
pkgs:
|
||||||
pkgs.parted # for partprobe
|
[
|
||||||
] ++ lib.optionals (config.content != null) (config.content._pkgs pkgs);
|
pkgs.util-linux
|
||||||
|
pkgs.parted # for partprobe
|
||||||
|
]
|
||||||
|
++ lib.optionals (config.content != null) (config.content._pkgs pkgs);
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
{ config, options, lib, diskoLib, rootMountPoint, ... }:
|
{
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
diskoLib,
|
||||||
|
rootMountPoint,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
# TODO: Consider expanding to handle `file` and `draid` mode options.
|
# TODO: Consider expanding to handle `file` and `draid` mode options.
|
||||||
modeOptions = [
|
modeOptions = [
|
||||||
@@ -63,134 +70,161 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
type = (lib.types.oneOf [
|
type = (
|
||||||
(lib.types.enum modeOptions)
|
lib.types.oneOf [
|
||||||
(lib.types.attrsOf (diskoLib.subType {
|
(lib.types.enum modeOptions)
|
||||||
types = {
|
(lib.types.attrsOf (
|
||||||
topology =
|
diskoLib.subType {
|
||||||
let
|
types = {
|
||||||
vdev = lib.types.submodule ({ ... }: {
|
topology =
|
||||||
options = {
|
let
|
||||||
mode = lib.mkOption {
|
vdev = lib.types.submodule (
|
||||||
type = lib.types.enum modeOptions;
|
{ ... }:
|
||||||
default = "";
|
{
|
||||||
description = "Mode of the zfs vdev";
|
options = {
|
||||||
};
|
mode = lib.mkOption {
|
||||||
members = lib.mkOption {
|
type = lib.types.enum modeOptions;
|
||||||
type = lib.types.listOf lib.types.str;
|
default = "";
|
||||||
description = "Members of the vdev";
|
description = "Mode of the zfs vdev";
|
||||||
};
|
};
|
||||||
};
|
members = lib.mkOption {
|
||||||
});
|
type = lib.types.listOf lib.types.str;
|
||||||
in
|
description = "Members of the vdev";
|
||||||
lib.types.submodule
|
};
|
||||||
({ ... }: {
|
};
|
||||||
options = {
|
}
|
||||||
type = lib.mkOption {
|
);
|
||||||
type = lib.types.enum [ "topology" ];
|
in
|
||||||
default = "topology";
|
lib.types.submodule (
|
||||||
internal = true;
|
{ ... }:
|
||||||
description = "Type";
|
{
|
||||||
};
|
options = {
|
||||||
# zfs device types
|
type = lib.mkOption {
|
||||||
vdev = lib.mkOption {
|
type = lib.types.enum [ "topology" ];
|
||||||
type = lib.types.listOf vdev;
|
default = "topology";
|
||||||
default = [ ];
|
internal = true;
|
||||||
description = ''
|
description = "Type";
|
||||||
A list of storage vdevs. See
|
};
|
||||||
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Virtual_Devices_(vdevs)
|
# zfs device types
|
||||||
for details.
|
vdev = lib.mkOption {
|
||||||
'';
|
type = lib.types.listOf vdev;
|
||||||
example = [
|
default = [ ];
|
||||||
{
|
description = ''
|
||||||
mode = "mirror";
|
A list of storage vdevs. See
|
||||||
members = [ "x" "y" ];
|
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Virtual_Devices_(vdevs)
|
||||||
}
|
for details.
|
||||||
{
|
'';
|
||||||
members = [ "z" ];
|
example = [
|
||||||
}
|
{
|
||||||
];
|
mode = "mirror";
|
||||||
};
|
members = [
|
||||||
spare = lib.mkOption {
|
"x"
|
||||||
type = lib.types.listOf lib.types.str;
|
"y"
|
||||||
default = [ ];
|
];
|
||||||
description = ''
|
}
|
||||||
A list of devices to use as hot spares. See
|
{
|
||||||
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Hot_Spares
|
members = [ "z" ];
|
||||||
for details.
|
}
|
||||||
'';
|
];
|
||||||
example = [ "x" "y" ];
|
};
|
||||||
};
|
spare = lib.mkOption {
|
||||||
log = lib.mkOption {
|
type = lib.types.listOf lib.types.str;
|
||||||
type = lib.types.listOf vdev;
|
default = [ ];
|
||||||
default = [ ];
|
description = ''
|
||||||
description = ''
|
A list of devices to use as hot spares. See
|
||||||
A list of vdevs used for the zfs intent log (ZIL). See
|
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Hot_Spares
|
||||||
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Intent_Log
|
for details.
|
||||||
for details.
|
'';
|
||||||
'';
|
example = [
|
||||||
example = [
|
"x"
|
||||||
{
|
"y"
|
||||||
mode = "mirror";
|
];
|
||||||
members = [ "x" "y" ];
|
};
|
||||||
}
|
log = lib.mkOption {
|
||||||
{
|
type = lib.types.listOf vdev;
|
||||||
members = [ "z" ];
|
default = [ ];
|
||||||
}
|
description = ''
|
||||||
];
|
A list of vdevs used for the zfs intent log (ZIL). See
|
||||||
};
|
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Intent_Log
|
||||||
dedup = lib.mkOption {
|
for details.
|
||||||
type = lib.types.listOf vdev;
|
'';
|
||||||
default = [ ];
|
example = [
|
||||||
description = ''
|
{
|
||||||
A list of vdevs used for the deduplication table. See
|
mode = "mirror";
|
||||||
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#dedup
|
members = [
|
||||||
for details.
|
"x"
|
||||||
'';
|
"y"
|
||||||
example = [
|
];
|
||||||
{
|
}
|
||||||
mode = "mirror";
|
{
|
||||||
members = [ "x" "y" ];
|
members = [ "z" ];
|
||||||
}
|
}
|
||||||
{
|
];
|
||||||
members = [ "z" ];
|
};
|
||||||
}
|
dedup = lib.mkOption {
|
||||||
];
|
type = lib.types.listOf vdev;
|
||||||
};
|
default = [ ];
|
||||||
special = lib.mkOption {
|
description = ''
|
||||||
type = lib.types.either (lib.types.listOf vdev) (lib.types.nullOr vdev);
|
A list of vdevs used for the deduplication table. See
|
||||||
default = [ ];
|
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#dedup
|
||||||
description = ''
|
for details.
|
||||||
A list of vdevs used as special devices. See
|
'';
|
||||||
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#special
|
example = [
|
||||||
for details.
|
{
|
||||||
'';
|
mode = "mirror";
|
||||||
example = [
|
members = [
|
||||||
{
|
"x"
|
||||||
mode = "mirror";
|
"y"
|
||||||
members = [ "x" "y" ];
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
members = [ "z" ];
|
members = [ "z" ];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
cache = lib.mkOption {
|
special = lib.mkOption {
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.either (lib.types.listOf vdev) (lib.types.nullOr vdev);
|
||||||
default = [ ];
|
default = [ ];
|
||||||
description = ''
|
description = ''
|
||||||
A dedicated zfs cache device (L2ARC). See
|
A list of vdevs used as special devices. See
|
||||||
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Cache_Devices
|
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#special
|
||||||
for details.
|
for details.
|
||||||
'';
|
'';
|
||||||
example = [ "x" "y" ];
|
example = [
|
||||||
};
|
{
|
||||||
};
|
mode = "mirror";
|
||||||
});
|
members = [
|
||||||
};
|
"x"
|
||||||
extraArgs.parent = config;
|
"y"
|
||||||
}))
|
];
|
||||||
]);
|
}
|
||||||
|
{
|
||||||
|
members = [ "z" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
cache = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
A dedicated zfs cache device (L2ARC). See
|
||||||
|
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Cache_Devices
|
||||||
|
for details.
|
||||||
|
'';
|
||||||
|
example = [
|
||||||
|
"x"
|
||||||
|
"y"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
extraArgs.parent = config;
|
||||||
|
}
|
||||||
|
))
|
||||||
|
]
|
||||||
|
);
|
||||||
description = "Mode of the ZFS pool";
|
description = "Mode of the ZFS pool";
|
||||||
};
|
};
|
||||||
options = lib.mkOption {
|
options = lib.mkOption {
|
||||||
@@ -214,18 +248,25 @@ in
|
|||||||
description = "Options to pass to mount";
|
description = "Options to pass to mount";
|
||||||
};
|
};
|
||||||
datasets = lib.mkOption {
|
datasets = lib.mkOption {
|
||||||
type = lib.types.attrsOf (diskoLib.subType {
|
type = lib.types.attrsOf (
|
||||||
types = { inherit (diskoLib.types) zfs_fs zfs_volume; };
|
diskoLib.subType {
|
||||||
extraArgs.parent = config;
|
types = { inherit (diskoLib.types) zfs_fs zfs_volume; };
|
||||||
});
|
extraArgs.parent = config;
|
||||||
|
}
|
||||||
|
);
|
||||||
description = "List of datasets to define";
|
description = "List of datasets to define";
|
||||||
};
|
};
|
||||||
_meta = lib.mkOption {
|
_meta = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = diskoLib.jsonType;
|
type = diskoLib.jsonType;
|
||||||
default =
|
default = diskoLib.deepMergeMap (
|
||||||
diskoLib.deepMergeMap (dataset: dataset._meta [ "zpool" config.name ]) (lib.attrValues config.datasets);
|
dataset:
|
||||||
|
dataset._meta [
|
||||||
|
"zpool"
|
||||||
|
config.name
|
||||||
|
]
|
||||||
|
) (lib.attrValues config.datasets);
|
||||||
description = "Metadata";
|
description = "Metadata";
|
||||||
};
|
};
|
||||||
_create = diskoLib.mkCreateOption {
|
_create = diskoLib.mkCreateOption {
|
||||||
@@ -234,14 +275,14 @@ in
|
|||||||
let
|
let
|
||||||
formatOutput = type: mode: members: ''
|
formatOutput = type: mode: members: ''
|
||||||
entries+=("${type} ${mode}=${
|
entries+=("${type} ${mode}=${
|
||||||
lib.concatMapStringsSep " "
|
lib.concatMapStringsSep " " (
|
||||||
(d: if lib.strings.hasPrefix "/" d then d else "/dev/disk/by-partlabel/disk-${d}-zfs") members
|
d: if lib.strings.hasPrefix "/" d then d else "/dev/disk/by-partlabel/disk-${d}-zfs"
|
||||||
|
) members
|
||||||
}")
|
}")
|
||||||
'';
|
'';
|
||||||
formatVdev = type: vdev: formatOutput type vdev.mode vdev.members;
|
formatVdev = type: vdev: formatOutput type vdev.mode vdev.members;
|
||||||
formatVdevList = type: vdevs: lib.concatMapStrings
|
formatVdevList =
|
||||||
(formatVdev type)
|
type: vdevs: lib.concatMapStrings (formatVdev type) (builtins.sort (a: _: a.mode == "") vdevs);
|
||||||
(builtins.sort (a: _: a.mode == "") vdevs);
|
|
||||||
hasTopology = !(builtins.isString config.mode);
|
hasTopology = !(builtins.isString config.mode);
|
||||||
mode = if hasTopology then "prescribed" else config.mode;
|
mode = if hasTopology then "prescribed" else config.mode;
|
||||||
topology = lib.optionalAttrs hasTopology config.mode.topology;
|
topology = lib.optionalAttrs hasTopology config.mode.topology;
|
||||||
@@ -281,18 +322,20 @@ in
|
|||||||
topology="${mode} ''${zfs_devices[*]}"
|
topology="${mode} ''${zfs_devices[*]}"
|
||||||
else
|
else
|
||||||
entries=()
|
entries=()
|
||||||
${lib.optionalString (hasTopology && topology.vdev != null)
|
${lib.optionalString (hasTopology && topology.vdev != null) (formatVdevList "" topology.vdev)}
|
||||||
(formatVdevList "" topology.vdev)}
|
${lib.optionalString (hasTopology && topology.spare != [ ]) (
|
||||||
${lib.optionalString (hasTopology && topology.spare != [])
|
formatOutput "spare" "" topology.spare
|
||||||
(formatOutput "spare" "" topology.spare)}
|
)}
|
||||||
${lib.optionalString (hasTopology && topology.log != [])
|
${lib.optionalString (hasTopology && topology.log != [ ]) (formatVdevList "log" topology.log)}
|
||||||
(formatVdevList "log" topology.log)}
|
${lib.optionalString (hasTopology && topology.dedup != [ ]) (
|
||||||
${lib.optionalString (hasTopology && topology.dedup != [])
|
formatVdevList "dedup" topology.dedup
|
||||||
(formatVdevList "dedup" topology.dedup)}
|
)}
|
||||||
${lib.optionalString (hasTopology && topology.special != null && topology.special != [])
|
${lib.optionalString (hasTopology && topology.special != null && topology.special != [ ]) (
|
||||||
(formatVdevList "special" (lib.lists.toList topology.special))}
|
formatVdevList "special" (lib.lists.toList topology.special)
|
||||||
${lib.optionalString (hasTopology && topology.cache != [])
|
)}
|
||||||
(formatOutput "cache" "" topology.cache)}
|
${lib.optionalString (hasTopology && topology.cache != [ ]) (
|
||||||
|
formatOutput "cache" "" topology.cache
|
||||||
|
)}
|
||||||
all_devices=()
|
all_devices=()
|
||||||
last_type=
|
last_type=
|
||||||
for line in "''${entries[@]}"; do
|
for line in "''${entries[@]}"; do
|
||||||
@@ -337,7 +380,9 @@ in
|
|||||||
inherit config options;
|
inherit config options;
|
||||||
default =
|
default =
|
||||||
let
|
let
|
||||||
datasetFilesystemsMounts = diskoLib.deepMergeMap (dataset: dataset._mount.fs or {}) (lib.attrValues config.datasets);
|
datasetFilesystemsMounts = diskoLib.deepMergeMap (dataset: dataset._mount.fs or { }) (
|
||||||
|
lib.attrValues config.datasets
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
dev = ''
|
dev = ''
|
||||||
@@ -359,7 +404,7 @@ in
|
|||||||
zpool export "${config.name}"
|
zpool export "${config.name}"
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
fs = diskoLib.deepMergeMap (dataset: dataset._unmount.fs or {}) (lib.attrValues config.datasets);
|
fs = diskoLib.deepMergeMap (dataset: dataset._unmount.fs or { }) (lib.attrValues config.datasets);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
_config = lib.mkOption {
|
_config = lib.mkOption {
|
||||||
@@ -372,7 +417,13 @@ in
|
|||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
type = lib.types.functionTo (lib.types.listOf lib.types.package);
|
||||||
default = pkgs: [ pkgs.gnugrep pkgs.util-linux ] ++ lib.flatten (map (dataset: dataset._pkgs pkgs) (lib.attrValues config.datasets));
|
default =
|
||||||
|
pkgs:
|
||||||
|
[
|
||||||
|
pkgs.gnugrep
|
||||||
|
pkgs.util-linux
|
||||||
|
]
|
||||||
|
++ lib.flatten (map (dataset: dataset._pkgs pkgs) (lib.attrValues config.datasets));
|
||||||
description = "Packages";
|
description = "Packages";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
81
module.nix
81
module.nix
@@ -1,4 +1,11 @@
|
|||||||
{ config, lib, pkgs, extendModules, diskoLib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
extendModules,
|
||||||
|
diskoLib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.disko;
|
cfg = config.disko;
|
||||||
|
|
||||||
@@ -107,7 +114,10 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
imageFormat = lib.mkOption {
|
imageFormat = lib.mkOption {
|
||||||
type = lib.types.enum [ "raw" "qcow2" ];
|
type = lib.types.enum [
|
||||||
|
"raw"
|
||||||
|
"qcow2"
|
||||||
|
];
|
||||||
description = "QEMU image format to use for the disk images";
|
description = "QEMU image format to use for the disk images";
|
||||||
default = "raw";
|
default = "raw";
|
||||||
};
|
};
|
||||||
@@ -239,38 +249,49 @@ in
|
|||||||
eval-config = import (pkgs.path + "/nixos/lib/eval-config.nix");
|
eval-config = import (pkgs.path + "/nixos/lib/eval-config.nix");
|
||||||
};
|
};
|
||||||
|
|
||||||
system.build = (cfg.devices._scripts { inherit pkgs; checked = cfg.checkScripts; }) // (
|
system.build =
|
||||||
let
|
(cfg.devices._scripts {
|
||||||
throwIfNoDisksDetected = _: v: if cfg.devices.disk == { } then throw "No disks defined, did you forget to import your disko config?" else v;
|
inherit pkgs;
|
||||||
in
|
checked = cfg.checkScripts;
|
||||||
lib.mapAttrs throwIfNoDisksDetected {
|
})
|
||||||
# we keep these old outputs for compatibility
|
// (
|
||||||
disko = builtins.trace "the .disko output is deprecated, please use .diskoScript instead" (cfg.devices._scripts { inherit pkgs; }).diskoScript;
|
let
|
||||||
diskoNoDeps = builtins.trace "the .diskoNoDeps output is deprecated, please use .diskoScriptNoDeps instead" (cfg.devices._scripts { inherit pkgs; }).diskoScriptNoDeps;
|
throwIfNoDisksDetected =
|
||||||
|
_: v:
|
||||||
|
if cfg.devices.disk == { } then
|
||||||
|
throw "No disks defined, did you forget to import your disko config?"
|
||||||
|
else
|
||||||
|
v;
|
||||||
|
in
|
||||||
|
lib.mapAttrs throwIfNoDisksDetected {
|
||||||
|
# we keep these old outputs for compatibility
|
||||||
|
disko =
|
||||||
|
builtins.trace "the .disko output is deprecated, please use .diskoScript instead"
|
||||||
|
(cfg.devices._scripts { inherit pkgs; }).diskoScript;
|
||||||
|
diskoNoDeps =
|
||||||
|
builtins.trace "the .diskoNoDeps output is deprecated, please use .diskoScriptNoDeps instead"
|
||||||
|
(cfg.devices._scripts { inherit pkgs; }).diskoScriptNoDeps;
|
||||||
|
|
||||||
installTest = diskoLib.testLib.makeDiskoTest {
|
installTest = diskoLib.testLib.makeDiskoTest {
|
||||||
inherit extendModules pkgs;
|
inherit extendModules pkgs;
|
||||||
name = "${config.networking.hostName}-disko";
|
name = "${config.networking.hostName}-disko";
|
||||||
disko-config = builtins.removeAttrs config [ "_module" ];
|
disko-config = builtins.removeAttrs config [ "_module" ];
|
||||||
testMode = "direct";
|
testMode = "direct";
|
||||||
bootCommands = cfg.tests.bootCommands;
|
bootCommands = cfg.tests.bootCommands;
|
||||||
efi = cfg.tests.efi;
|
efi = cfg.tests.efi;
|
||||||
enableOCR = cfg.tests.enableOCR;
|
enableOCR = cfg.tests.enableOCR;
|
||||||
extraSystemConfig = cfg.tests.extraConfig;
|
extraSystemConfig = cfg.tests.extraConfig;
|
||||||
extraTestScript = cfg.tests.extraChecks;
|
extraTestScript = cfg.tests.extraChecks;
|
||||||
};
|
};
|
||||||
|
|
||||||
vmWithDisko = lib.mkDefault config.virtualisation.vmVariantWithDisko.system.build.vmWithDisko;
|
vmWithDisko = lib.mkDefault config.virtualisation.vmVariantWithDisko.system.build.vmWithDisko;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
# we need to specify the keys here, so we don't get an infinite recursion error
|
# we need to specify the keys here, so we don't get an infinite recursion error
|
||||||
# Remember to add config keys here if they are added to types
|
# Remember to add config keys here if they are added to types
|
||||||
fileSystems = lib.mkIf
|
fileSystems = lib.mkIf cfg.enableConfig cfg.devices._config.fileSystems or { };
|
||||||
cfg.enableConfig cfg.devices._config.fileSystems or { };
|
boot = lib.mkIf cfg.enableConfig cfg.devices._config.boot or { };
|
||||||
boot = lib.mkIf
|
swapDevices = lib.mkIf cfg.enableConfig cfg.devices._config.swapDevices or [ ];
|
||||||
cfg.enableConfig cfg.devices._config.boot or { };
|
|
||||||
swapDevices = lib.mkIf
|
|
||||||
cfg.enableConfig cfg.devices._config.swapDevices or [ ];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
20
package.nix
20
package.nix
@@ -1,4 +1,14 @@
|
|||||||
{ stdenvNoCC, makeWrapper, lib, path, nix, coreutils, nixos-install-tools, binlore, diskoVersion }:
|
{
|
||||||
|
stdenvNoCC,
|
||||||
|
makeWrapper,
|
||||||
|
lib,
|
||||||
|
path,
|
||||||
|
nix,
|
||||||
|
coreutils,
|
||||||
|
nixos-install-tools,
|
||||||
|
binlore,
|
||||||
|
diskoVersion,
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
self = stdenvNoCC.mkDerivation (finalAttrs: {
|
self = stdenvNoCC.mkDerivation (finalAttrs: {
|
||||||
@@ -16,7 +26,13 @@ let
|
|||||||
chmod 755 "$out/bin/$i"
|
chmod 755 "$out/bin/$i"
|
||||||
wrapProgram "$out/bin/$i" \
|
wrapProgram "$out/bin/$i" \
|
||||||
--set DISKO_VERSION "${diskoVersion}" \
|
--set DISKO_VERSION "${diskoVersion}" \
|
||||||
--prefix PATH : ${lib.makeBinPath [ nix coreutils nixos-install-tools ]} \
|
--prefix PATH : ${
|
||||||
|
lib.makeBinPath [
|
||||||
|
nix
|
||||||
|
coreutils
|
||||||
|
nixos-install-tools
|
||||||
|
]
|
||||||
|
} \
|
||||||
--prefix NIX_PATH : "nixpkgs=${path}"
|
--prefix NIX_PATH : "nixpkgs=${path}"
|
||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#! /usr/bin/env bash
|
||||||
|
|
||||||
# Don't run directly! Instead, use
|
# Don't run directly! Instead, use
|
||||||
# nix run .#create-release
|
# nix run .#create-release
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -17,4 +18,3 @@ diskoLib.testLib.makeDiskoTest {
|
|||||||
machine.succeed("test -e /partition-root/swapfile1");
|
machine.succeed("test -e /partition-root/swapfile1");
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -26,7 +27,10 @@ diskoLib.testLib.makeDiskoTest {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
extraInstallerConfig = {
|
extraInstallerConfig = {
|
||||||
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
|
boot.kernelModules = [
|
||||||
|
"dm-raid"
|
||||||
|
"dm-mirror"
|
||||||
|
];
|
||||||
imports = [
|
imports = [
|
||||||
../module.nix
|
../module.nix
|
||||||
];
|
];
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -24,6 +25,9 @@ diskoLib.testLib.makeDiskoTest {
|
|||||||
machine.succeed("test -e /ext4_on_lvm/file-from-postMountHook");
|
machine.succeed("test -e /ext4_on_lvm/file-from-postMountHook");
|
||||||
'';
|
'';
|
||||||
extraInstallerConfig = {
|
extraInstallerConfig = {
|
||||||
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
|
boot.kernelModules = [
|
||||||
|
"dm-raid"
|
||||||
|
"dm-mirror"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,20 +1,28 @@
|
|||||||
{ makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>
|
{
|
||||||
, eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>
|
makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>,
|
||||||
, pkgs ? import <nixpkgs> { }
|
eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>,
|
||||||
|
pkgs ? import <nixpkgs> { },
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
lib = pkgs.lib;
|
lib = pkgs.lib;
|
||||||
diskoLib = import ../lib { inherit lib makeTest eval-config; };
|
diskoLib = import ../lib { inherit lib makeTest eval-config; };
|
||||||
|
|
||||||
allTestFilenames =
|
allTestFilenames = builtins.map (lib.removeSuffix ".nix") (
|
||||||
builtins.map (lib.removeSuffix ".nix") (
|
builtins.filter (x: lib.hasSuffix ".nix" x && x != "default.nix") (
|
||||||
builtins.filter
|
lib.attrNames (builtins.readDir ./.)
|
||||||
(x: lib.hasSuffix ".nix" x && x != "default.nix")
|
)
|
||||||
(lib.attrNames (builtins.readDir ./.))
|
);
|
||||||
);
|
incompatibleTests = lib.optionals pkgs.stdenv.buildPlatform.isRiscV64 [
|
||||||
incompatibleTests = lib.optionals pkgs.stdenv.buildPlatform.isRiscV64 [ "zfs" "zfs-over-legacy" "cli" "module" "complex" ];
|
"zfs"
|
||||||
|
"zfs-over-legacy"
|
||||||
|
"cli"
|
||||||
|
"module"
|
||||||
|
"complex"
|
||||||
|
];
|
||||||
allCompatibleFilenames = lib.subtractLists incompatibleTests allTestFilenames;
|
allCompatibleFilenames = lib.subtractLists incompatibleTests allTestFilenames;
|
||||||
|
|
||||||
allTests = lib.genAttrs allCompatibleFilenames (test: import (./. + "/${test}.nix") { inherit diskoLib pkgs; });
|
allTests = lib.genAttrs allCompatibleFilenames (
|
||||||
|
test: import (./. + "/${test}.nix") { inherit diskoLib pkgs; }
|
||||||
|
);
|
||||||
in
|
in
|
||||||
allTests
|
allTests
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
{ lib, pkgs, modulesPath, ... }: {
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
imports = [
|
imports = [
|
||||||
(modulesPath + "/testing/test-instrumentation.nix")
|
(modulesPath + "/testing/test-instrumentation.nix")
|
||||||
(modulesPath + "/profiles/qemu-guest.nix")
|
(modulesPath + "/profiles/qemu-guest.nix")
|
||||||
@@ -13,11 +19,15 @@
|
|||||||
hashed-mirrors = null;
|
hashed-mirrors = null;
|
||||||
connect-timeout = 3;
|
connect-timeout = 3;
|
||||||
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
|
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
|
||||||
experimental-features = [ "nix-command" "flakes" ];
|
experimental-features = [
|
||||||
|
"nix-command"
|
||||||
|
"flakes"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
boot.kernelParams = [ "console=tty0" ] ++
|
boot.kernelParams =
|
||||||
(lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200") ++
|
[ "console=tty0" ]
|
||||||
(lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200") ++
|
++ (lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200")
|
||||||
[ "console=ttyS0,115200" ];
|
++ (lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200")
|
||||||
|
++ [ "console=ttyS0,115200" ];
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }, self, diskoVersion }:
|
{
|
||||||
|
pkgs ? import <nixpkgs> { },
|
||||||
|
self,
|
||||||
|
diskoVersion,
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
disko = pkgs.callPackage ../../package.nix { inherit diskoVersion; };
|
disko = pkgs.callPackage ../../package.nix { inherit diskoVersion; };
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -9,7 +10,11 @@ diskoLib.testLib.makeDiskoTest {
|
|||||||
machine.succeed("mountpoint /home");
|
machine.succeed("mountpoint /home");
|
||||||
'';
|
'';
|
||||||
extraInstallerConfig = {
|
extraInstallerConfig = {
|
||||||
boot.kernelModules = [ "dm-raid" "raid0" "dm-mirror" ];
|
boot.kernelModules = [
|
||||||
|
"dm-raid"
|
||||||
|
"raid0"
|
||||||
|
"dm-mirror"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
extraSystemConfig = {
|
extraSystemConfig = {
|
||||||
# sadly systemd-boot fails to install to a raid /boot device
|
# sadly systemd-boot fails to install to a raid /boot device
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,13 +1,17 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, ...
|
pkgs ? import <nixpkgs> { },
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
(pkgs.nixos [
|
(pkgs.nixos [
|
||||||
../module.nix
|
../module.nix
|
||||||
../example/simple-efi.nix
|
../example/simple-efi.nix
|
||||||
({ config, ... }: {
|
(
|
||||||
documentation.enable = false;
|
{ config, ... }:
|
||||||
system.stateVersion = config.system.nixos.version;
|
{
|
||||||
disko.checkScripts = true;
|
documentation.enable = false;
|
||||||
})
|
system.stateVersion = config.system.nixos.version;
|
||||||
|
disko.checkScripts = true;
|
||||||
|
}
|
||||||
|
)
|
||||||
]).config.system.build.diskoImagesScript
|
]).config.system.build.diskoImagesScript
|
||||||
|
@@ -1,14 +1,18 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, ...
|
pkgs ? import <nixpkgs> { },
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
(pkgs.nixos [
|
(pkgs.nixos [
|
||||||
../module.nix
|
../module.nix
|
||||||
../example/simple-efi.nix
|
../example/simple-efi.nix
|
||||||
({ config, ... }: {
|
(
|
||||||
documentation.enable = false;
|
{ config, ... }:
|
||||||
system.stateVersion = config.system.nixos.version;
|
{
|
||||||
disko.memSize = 2048;
|
documentation.enable = false;
|
||||||
disko.checkScripts = true;
|
system.stateVersion = config.system.nixos.version;
|
||||||
})
|
disko.memSize = 2048;
|
||||||
|
disko.checkScripts = true;
|
||||||
|
}
|
||||||
|
)
|
||||||
]).config.system.build.diskoImages
|
]).config.system.build.diskoImages
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -21,6 +22,9 @@ diskoLib.testLib.makeDiskoTest {
|
|||||||
machine.succeed("mountpoint /ext4_on_lvm");
|
machine.succeed("mountpoint /ext4_on_lvm");
|
||||||
'';
|
'';
|
||||||
extraInstallerConfig = {
|
extraInstallerConfig = {
|
||||||
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
|
boot.kernelModules = [
|
||||||
|
"dm-raid"
|
||||||
|
"dm-mirror"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
# this is a regression test for https://github.com/nix-community/disko/issues/52
|
# this is a regression test for https://github.com/nix-community/disko/issues/52
|
||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
# this is a regression test for https://github.com/nix-community/disko/issues/52
|
# this is a regression test for https://github.com/nix-community/disko/issues/52
|
||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }, ... }:
|
{
|
||||||
|
pkgs ? import <nixpkgs> { },
|
||||||
|
...
|
||||||
|
}:
|
||||||
(pkgs.nixos [
|
(pkgs.nixos [
|
||||||
../example/stand-alone/configuration.nix
|
../example/stand-alone/configuration.nix
|
||||||
{ documentation.enable = false; }
|
{ documentation.enable = false; }
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,18 +1,17 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
name = "zfs-encrypted-root";
|
name = "zfs-encrypted-root";
|
||||||
extraInstallerConfig.networking.hostId = "8425e349";
|
extraInstallerConfig.networking.hostId = "8425e349";
|
||||||
extraSystemConfig.networking.hostId = "8425e349";
|
extraSystemConfig.networking.hostId = "8425e349";
|
||||||
disko-config =
|
disko-config = pkgs.lib.recursiveUpdate (import ../example/zfs-encrypted-root.nix) {
|
||||||
pkgs.lib.recursiveUpdate (import ../example/zfs-encrypted-root.nix) {
|
disko.devices.zpool.zroot.datasets.root.options.keylocation = "file:///tmp/secret.key";
|
||||||
disko.devices.zpool.zroot.datasets.root.options.keylocation = "file:///tmp/secret.key";
|
};
|
||||||
};
|
|
||||||
extraTestScript = ''
|
extraTestScript = ''
|
||||||
machine.succeed("mountpoint /");
|
machine.succeed("mountpoint /");
|
||||||
machine.succeed("mountpoint /nix");
|
machine.succeed("mountpoint /nix");
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -12,4 +13,3 @@ diskoLib.testLib.makeDiskoTest {
|
|||||||
machine.succeed("mountpoint /zfs_fs");
|
machine.succeed("mountpoint /zfs_fs");
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{ pkgs ? import <nixpkgs> { }
|
{
|
||||||
, diskoLib ? pkgs.callPackage ../lib { }
|
pkgs ? import <nixpkgs> { },
|
||||||
|
diskoLib ? pkgs.callPackage ../lib { },
|
||||||
}:
|
}:
|
||||||
diskoLib.testLib.makeDiskoTest {
|
diskoLib.testLib.makeDiskoTest {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
|
@@ -1 +1,4 @@
|
|||||||
{ version = "1.10.0"; released = false; }
|
{
|
||||||
|
version = "1.10.0";
|
||||||
|
released = false;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user