treewide: format all files

This commit is contained in:
DavHau
2025-02-15 16:12:27 +07:00
committed by lassulus
parent c23ac2891c
commit ff2d853a84
82 changed files with 2929 additions and 1993 deletions

61
cli.nix
View File

@@ -1,12 +1,13 @@
{ pkgs ? import <nixpkgs> { }
, lib ? pkgs.lib
, mode ? "mount"
, flake ? null
, flakeAttr ? null
, diskoFile ? null
, rootMountPoint ? "/mnt"
, noDeps ? false
, ...
{
pkgs ? import <nixpkgs> { },
lib ? pkgs.lib,
mode ? "mount",
flake ? null,
flakeAttr ? null,
diskoFile ? null,
rootMountPoint ? "/mnt",
noDeps ? false,
...
}@args:
let
disko = import ./. {
@@ -17,8 +18,10 @@ let
hasDiskoFile = diskoFile != null;
diskoAttr =
(if noDeps then
(if hasDiskoFile then
(
if noDeps then
(
if hasDiskoFile then
{
destroy = "_cliDestroyNoDeps";
format = "_cliFormatNoDeps";
@@ -37,14 +40,17 @@ let
"format,mount" = "formatMountNoDeps";
"destroy,format,mount" = "destroyFormatMountNoDeps";
}) // {
}
)
// {
# legacy aliases
disko = "diskoScriptNoDeps";
create = "createScriptNoDeps";
zap_create_mount = "diskoScriptNoDeps";
}
else
(if hasDiskoFile then
(
if hasDiskoFile then
{
destroy = "_cliDestroy";
format = "_cliFormat";
@@ -63,7 +69,9 @@ let
"format,mount" = "formatMount";
"destroy,format,mount" = "destroyFormatMount";
}) // {
}
)
// {
# legacy aliases
disko = "diskoScript";
create = "createScript";
@@ -74,9 +82,13 @@ let
hasDiskoConfigFlake =
hasDiskoFile || lib.hasAttrByPath [ "diskoConfigurations" flakeAttr ] (builtins.getFlake flake);
hasDiskoModuleFlake =
lib.hasAttrByPath [ "nixosConfigurations" flakeAttr "config" "disko" "devices" ] (builtins.getFlake flake);
hasDiskoModuleFlake = lib.hasAttrByPath [
"nixosConfigurations"
flakeAttr
"config"
"disko"
"devices"
] (builtins.getFlake flake);
diskFormat =
let
@@ -86,20 +98,16 @@ let
else
(builtins.getFlake flake).diskoConfigurations.${flakeAttr};
in
if builtins.isFunction diskoConfig then
diskoConfig ({ inherit lib; } // args)
else
diskoConfig;
if builtins.isFunction diskoConfig then diskoConfig ({ inherit lib; } // args) else diskoConfig;
diskoEval =
disko.${diskoAttr} diskFormat pkgs;
diskoEval = disko.${diskoAttr} diskFormat pkgs;
diskoScript =
if hasDiskoConfigFlake then
diskoEval
else if hasDiskoModuleFlake then
(builtins.getFlake flake).nixosConfigurations.${flakeAttr}.config.system.build.${diskoAttr} or (
pkgs.writeShellScriptBin "disko-compat-error" ''
(builtins.getFlake flake).nixosConfigurations.${flakeAttr}.config.system.build.${diskoAttr}
or (pkgs.writeShellScriptBin "disko-compat-error" ''
echo 'Error: Attribute `nixosConfigurations.${flakeAttr}.config.system.build.${diskoAttr}` >&2
echo ' not found in flake `${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 ' 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
exit 1;''
)
exit 1;'')
else
(builtins.abort "couldn't find `diskoConfigurations.${flakeAttr}` or `nixosConfigurations.${flakeAttr}.config.disko.devices`");

View File

@@ -1,10 +1,13 @@
{ lib ? import <nixpkgs/lib>
, rootMountPoint ? "/mnt"
, checked ? false
, diskoLib ? import ./lib { inherit lib rootMountPoint; }
{
lib ? import <nixpkgs/lib>,
rootMountPoint ? "/mnt",
checked ? false,
diskoLib ? import ./lib { inherit lib rootMountPoint; },
}:
let
eval = cfg: lib.evalModules {
eval =
cfg:
lib.evalModules {
modules = lib.singleton {
# _file = toString input;
imports = lib.singleton { disko.devices = cfg.disko.devices; };
@@ -17,48 +20,88 @@ let
};
# 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.
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
{
lib = warnDeprecated ".lib.lib" diskoLib;
_cliDestroy = 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;
_cliDestroy =
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;
_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;
_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;
_cliUnmountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).unmountNoDeps;
_cliUnmount =
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;
_cliFormatMountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatMountNoDeps;
_cliFormatMount =
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;
_cliDestroyFormatMountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).destroyFormatMountNoDeps;
_cliDestroyFormatMount =
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
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;
createScriptNoDeps = cfg: pkgs: warnDeprecated "createScriptNoDeps" ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatScriptNoDeps;
createScript =
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;
formatScript = 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;
formatScript =
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;
mountScript = 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;
mountScript =
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;
diskoScript = 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;
diskoScript =
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
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;
packages = cfg: (eval cfg).config.disko.devices._packages;

14
doc.nix
View File

@@ -1,4 +1,10 @@
{ lib, nixosOptionsDoc, runCommand, fetchurl, pandoc }:
{
lib,
nixosOptionsDoc,
runCommand,
fetchurl,
pandoc,
}:
let
diskoLib = import ./lib {
@@ -21,13 +27,15 @@ let
options = nixosOptionsDoc {
options = eval.options;
};
md = (runCommand "disko-options.md" { } ''
md =
(runCommand "disko-options.md" { } ''
cat >$out <<EOF
# Disko options
EOF
cat ${options.optionsCommonMark} >>$out
'').overrideAttrs (_o: {
'').overrideAttrs
(_o: {
# Work around https://github.com/hercules-ci/hercules-ci-agent/issues/168
allowSubstitutes = true;
});

View File

@@ -26,7 +26,10 @@
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
mountOptions = [
"compress=zstd"
"noatime"
];
};
};
};
@@ -35,4 +38,3 @@
};
};
}

View File

@@ -41,7 +41,10 @@
"/home/user" = { };
# Parent is not mounted so the mountpoint must be set
"/nix" = {
mountOptions = [ "compress=zstd" "noatime" ];
mountOptions = [
"compress=zstd"
"noatime"
];
mountpoint = "/nix";
};
# This subvolume will be created but not mounted
@@ -74,4 +77,3 @@
};
};
}

View File

@@ -38,4 +38,3 @@
};
};
}

View File

@@ -35,15 +35,24 @@
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
mountOptions = [
"compress=zstd"
"noatime"
];
};
"/home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" "noatime" ];
mountOptions = [
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
mountOptions = [
"compress=zstd"
"noatime"
];
};
"/swap" = {
mountpoint = "/.swapvol";

View File

@@ -56,4 +56,3 @@
};
};
}

View File

@@ -1,6 +1,7 @@
{ pkgs
, lib
, ...
{
pkgs,
lib,
...
}:
let
# We just import from the repository for testing here:

View File

@@ -1,5 +1,10 @@
# Example to create a bios compatible gpt partition
{ disks ? [ "/dev/vdb" ], lib, ... }: {
{
disks ? [ "/dev/vdb" ],
lib,
...
}:
{
disko.devices = {
disk = lib.genAttrs disks (device: {
name = lib.replaceStrings [ "/" ] [ "_" ] device;

View File

@@ -23,7 +23,10 @@
type = "filesystem";
format = "xfs";
mountpoint = "/";
mountOptions = [ "defaults" "pquota" ];
mountOptions = [
"defaults"
"pquota"
];
};
};
};

View File

@@ -251,14 +251,20 @@
}
{
mode = "mirror";
members = [ "data2" "data3" ];
members = [
"data2"
"data3"
];
}
];
spare = [ "spare" ];
log = [
{
mode = "mirror";
members = [ "log1" "log2" ];
members = [
"log1"
"log2"
];
}
{
members = [ "log3" ];
@@ -267,7 +273,10 @@
dedup = [
{
mode = "mirror";
members = [ "dedup1" "dedup2" ];
members = [
"dedup1"
"dedup2"
];
}
{
members = [ "dedup3" ];
@@ -276,7 +285,10 @@
special = [
{
mode = "mirror";
members = [ "special1" "special2" ];
members = [
"special1"
"special2"
];
}
{
members = [ "special3" ];

View File

@@ -6,7 +6,8 @@
#inputs.nixpkgs.url = "nixpkgs";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
outputs = { self, nixpkgs, ... }:
outputs =
{ self, nixpkgs, ... }:
let
lib = nixpkgs.lib;
supportedSystems = [
@@ -28,7 +29,8 @@
nixosModules.default = self.nixosModules.disko; # convention
nixosModules.disko = ./module.nix;
lib = diskoLib;
packages = forAllSystems (system:
packages = forAllSystems (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
@@ -41,27 +43,35 @@
default = self.packages.${system}.disko;
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 { };
});
}
);
# TODO: disable bios-related tests on aarch64...
# Run checks: nix flake check -L
checks = forAllSystems (system:
checks = forAllSystems (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
# 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 (
import ./tests {
inherit pkgs;
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 {
inherit self;
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" { } ''
${self.formatter.${system}}/bin/treefmt --ci --working-dir ${self}
@@ -69,11 +79,14 @@
'';
in
# FIXME: aarch64-linux seems to hang on boot
lib.optionalAttrs pkgs.stdenv.hostPlatform.isx86_64 (nixosTests // { inherit disko-install; }) //
pkgs.lib.optionalAttrs (!pkgs.stdenv.buildPlatform.isRiscV64 && !pkgs.stdenv.hostPlatform.isx86_32) {
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;
inherit (self.packages.${system}) disko-doc;
});
}
);
nixosConfigurations.testmachine = lib.nixosSystem {
system = "x86_64-linux";
@@ -83,7 +96,8 @@
./module.nix
];
};
formatter = forAllSystems (system:
formatter = forAllSystems (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in

View File

@@ -1,10 +1,10 @@
{ flake
, flakeAttr
, diskMappings
, extraSystemConfig ? "{}"
, writeEfiBootEntries ? false
, rootMountPoint ? "/mnt"
,
{
flake,
flakeAttr,
diskMappings,
extraSystemConfig ? "{}",
writeEfiBootEntries ? false,
rootMountPoint ? "/mnt",
}:
let
originalSystem = (builtins.getFlake "${flake}").nixosConfigurations."${flakeAttr}";
@@ -17,8 +17,7 @@ let
else
throw "No device passed for disk '${name}'. Pass `--disk ${name} /dev/name` via commandline";
modifiedDisks = builtins.mapAttrs
(
modifiedDisks = builtins.mapAttrs (
name: value:
let
dev = deviceName name;
@@ -30,8 +29,7 @@ let
device = dev;
};
}
)
originalSystem.config.disko.devices.disk;
) originalSystem.config.disko.devices.disk;
# filter all nixos module internal attributes
cleanedDisks = lib.filterAttrsRecursive (n: _: !lib.hasPrefix "_" n) modifiedDisks;

View File

@@ -1,25 +1,33 @@
{ lib, diskoLib, pkgs, imagePkgs, ... }:
{
lib,
diskoLib,
pkgs,
imagePkgs,
...
}:
let
# from https://github.com/NixOS/nixpkgs/blob/851f7fc119e9597c26cc43e10938ce7272d0af9d/nixos/modules/system/boot/binfmt.nix
makeBinfmtLine =
{ name
, recognitionType
, offset
, magicOrExtension
, mask
, preserveArgvZero
, openBinary
, matchCredentials
, fixBinary
, interpreter
, ...
{
name,
recognitionType,
offset,
magicOrExtension,
mask,
preserveArgvZero,
openBinary,
matchCredentials,
fixBinary,
interpreter,
...
}:
let
type = if recognitionType == "magic" then "M" else "E";
offset' = toString offset;
mask' = toString mask;
flags = with lib;
flags =
with lib;
if !(matchCredentials -> openBinary) then
throw "boot.binfmt.registrations.${name}: you can't specify openBinary = false when matchCredentials = true."
else
@@ -153,7 +161,8 @@ in
inherit (elaborated) qemuArch;
isQemu = "qemu-${qemuArch}" == baseNameOf interpreter;
in makeBinfmtLine (
in
makeBinfmtLine (
{
name = system;
inherit interpreter;

View File

@@ -1,7 +1,8 @@
{ lib ? import <nixpkgs/lib>
, rootMountPoint ? "/mnt"
, makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>
, eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>
{
lib ? import <nixpkgs/lib>,
rootMountPoint ? "/mnt",
makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>,
eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>,
}:
let
outputs = import ../default.nix { inherit lib diskoLib; };
@@ -9,42 +10,89 @@ let
testLib = import ./tests.nix { inherit lib makeTest eval-config; };
# like lib.types.oneOf but instead of a list takes an attrset
# uses the field "type" to find the correct type in the attrset
subType = { types, extraArgs ? { parent = { type = "rootNode"; name = "root"; }; } }: lib.mkOptionType {
subType =
{
types,
extraArgs ? {
parent = {
type = "rootNode";
name = "root";
};
},
}:
lib.mkOptionType {
name = "subType";
description = "one of ${lib.concatStringsSep "," (lib.attrNames types)}";
check = x: if x ? type then types.${x.type}.check x else throw "No type option set in:\n${lib.generators.toPretty {} x}";
merge = loc: lib.foldl'
(_res: def: types.${def.value.type}.merge loc [
check =
x:
if x ? type then
types.${x.type}.check x
else
throw "No type option set in:\n${lib.generators.toPretty { } x}";
merge =
loc:
lib.foldl' (
_res: def:
types.${def.value.type}.merge loc [
# we add a dummy root parent node to render documentation
(lib.recursiveUpdate { value._module.args = extraArgs; } def)
])
{ };
]
) { };
nestedTypes = types;
};
# option for valid contents of partitions (basically like devices, but without tables)
_partitionTypes = { inherit (diskoLib.types) btrfs filesystem zfs mdraid luks lvm_pv swap; };
partitionType = extraArgs: lib.mkOption {
type = lib.types.nullOr (diskoLib.subType {
_partitionTypes = {
inherit (diskoLib.types)
btrfs
filesystem
zfs
mdraid
luks
lvm_pv
swap
;
};
partitionType =
extraArgs:
lib.mkOption {
type = lib.types.nullOr (
diskoLib.subType {
types = diskoLib._partitionTypes;
inherit extraArgs;
});
}
);
default = null;
description = "The type of partition";
};
# option for valid contents of devices
_deviceTypes = { inherit (diskoLib.types) table gpt btrfs filesystem zfs mdraid luks lvm_pv swap; };
deviceType = extraArgs: lib.mkOption {
type = lib.types.nullOr (diskoLib.subType {
_deviceTypes = {
inherit (diskoLib.types)
table
gpt
btrfs
filesystem
zfs
mdraid
luks
lvm_pv
swap
;
};
deviceType =
extraArgs:
lib.mkOption {
type = lib.types.nullOr (
diskoLib.subType {
types = diskoLib._deviceTypes;
inherit extraArgs;
});
}
);
default = null;
description = "The type of device";
};
/**
like lib.recursiveUpdate but supports merging of lists
@@ -75,25 +123,35 @@ let
boot.loader.grub.devices = [ "/dev/hda" "/dev/hdb" ];
}
```
**/
recursiveUpdate = left: right:
*
*/
recursiveUpdate =
left: right:
let
inherit (lib) zipAttrsWith length elemAt head isAttrs isList concatLists all reverseList;
inherit (lib)
zipAttrsWith
length
elemAt
head
isAttrs
isList
concatLists
all
reverseList
;
recursiveMergeUntil =
pred:
lhs:
rhs:
pred: lhs: rhs:
let
f = attrPath:
zipAttrsWith (n: values:
let here = attrPath ++ [ n ]; in
if length values == 1
|| pred here (elemAt values 1) (head values) then
(
if all isList values then concatLists (reverseList values)
else head values
)
f =
attrPath:
zipAttrsWith (
n: values:
let
here = attrPath ++ [ n ];
in
if length values == 1 || pred here (elemAt values 1) (head values) then
(if all isList values then concatLists (reverseList values) else head values)
else
f here values
);
@@ -101,19 +159,17 @@ let
f [ ] [ rhs lhs ];
recursiveMerge =
lhs:
rhs:
recursiveMergeUntil
(_path: lhs: rhs:
!(isAttrs lhs && isAttrs rhs))
lhs
rhs;
lhs: rhs:
recursiveMergeUntil (
_path: lhs: rhs:
!(isAttrs lhs && isAttrs rhs)
) lhs rhs;
in
recursiveMerge left right;
/* deepMergeMap takes a function and a list of attrsets and deep merges them
/*
deepMergeMap takes a function and a list of attrsets and deep merges them
deepMergeMap :: (AttrSet -> AttrSet ) -> [ AttrSet ] -> Attrset
@@ -123,7 +179,8 @@ let
*/
deepMergeMap = f: lib.foldr (attr: acc: (diskoLib.recursiveUpdate acc (f attr))) { };
/* get a device and an index to get the matching device name
/*
get a device and an index to get the matching device name
deviceNumbering :: str -> int -> str
@@ -134,8 +191,11 @@ let
deviceNumbering "/dev/disk/by-id/xxx" 2
=> "/dev/disk/by-id/xxx-part2"
*/
deviceNumbering = dev: index:
let inherit (lib) match; in
deviceNumbering =
dev: index:
let
inherit (lib) match;
in
if match "/dev/([vs]|(xv)d).+" dev != null then
dev + toString index # /dev/{s,v,xv}da style
else if match "/dev/(disk|zvol)/.+" dev != null then
@@ -146,14 +206,15 @@ let
"${dev}${toString index}" # /dev/md/raid1 style
else if match "/dev/mapper/.+" dev != null then
"${dev}${toString index}" # /dev/mapper/vg-lv1 style
else if match "/dev/loop[[:digit:]]+" dev != null
then "${dev}p${toString index}" # /dev/mapper/vg-lv1 style
else if match "/dev/loop[[:digit:]]+" dev != null then
"${dev}p${toString index}" # /dev/mapper/vg-lv1 style
else
abort ''
${dev} seems not to be a supported disk format. Please add this to disko in https://github.com/nix-community/disko/blob/master/lib/default.nix
'';
/* Escape a string as required to be used in udev symlinks
/*
Escape a string as required to be used in udev symlinks
The allowed characters are "0-9A-Za-z#+-.:=@_/", valid UTF-8 character sequences, and "\x00" hex encoding.
Everything else is escaped as "\xXX" where XX is the hex value of the character.
@@ -181,10 +242,12 @@ let
allowedChars = "[0-9A-Za-z#+-.:=@_/]";
charToHex = c: lib.toHexString (lib.strings.charToInt c);
in
lib.stringAsChars
(c: if lib.match allowedChars c != null || c == "" then c else "\\x" + charToHex c);
lib.stringAsChars (
c: if lib.match allowedChars c != null || c == "" then c else "\\x" + charToHex c
);
/* get the index an item in a list
/*
get the index an item in a list
indexOf :: (a -> bool) -> [a] -> int -> int
@@ -195,9 +258,11 @@ let
indexOf (x: x == "x") [ 1 2 3 ] 0
=> 0
*/
indexOf = f: list: fallback:
indexOf =
f: list: fallback:
let
iter = index: list:
iter =
index: list:
if list == [ ] then
fallback
else if f (lib.head list) then
@@ -207,8 +272,8 @@ let
in
iter 1 list;
/* indent takes a multiline string and indents it by 2 spaces starting on the second line
/*
indent takes a multiline string and indents it by 2 spaces starting on the second line
indent :: str -> str
@@ -218,11 +283,12 @@ let
*/
indent = lib.replaceStrings [ "\n" ] [ "\n " ];
/* A nix option type representing a json datastructure, vendored from nixpkgs to avoid dependency on pkgs */
# A nix option type representing a json datastructure, vendored from nixpkgs to avoid dependency on pkgs
jsonType =
let
valueType = lib.types.nullOr
(lib.types.oneOf [
valueType =
lib.types.nullOr (
lib.types.oneOf [
lib.types.bool
lib.types.int
lib.types.float
@@ -230,21 +296,24 @@ let
lib.types.path
(lib.types.attrsOf valueType)
(lib.types.listOf valueType)
]) // {
]
)
// {
description = "JSON value";
};
in
valueType;
/* Given a attrset of deviceDependencies and a devices attrset
/*
Given a attrset of deviceDependencies and a devices attrset
returns a sorted list by deviceDependencies. aborts if a loop is found
sortDevicesByDependencies :: AttrSet -> AttrSet -> [ [ str str ] ]
*/
sortDevicesByDependencies = deviceDependencies: devices:
sortDevicesByDependencies =
deviceDependencies: devices:
let
dependsOn = a: b:
lib.elem a (lib.attrByPath b [ ] deviceDependencies);
dependsOn = a: b: lib.elem a (lib.attrByPath b [ ] deviceDependencies);
maybeSortedDevices = lib.toposort dependsOn (diskoLib.deviceList devices);
in
if (lib.hasAttr "cycle" maybeSortedDevices) then
@@ -252,7 +321,8 @@ let
else
maybeSortedDevices.result;
/* Takes a devices attrSet and returns it as a list
/*
Takes a devices attrSet and returns it as a list
deviceList :: AttrSet -> [ [ str str ] ]
@@ -260,10 +330,20 @@ let
deviceList { zfs.pool1 = {}; zfs.pool2 = {}; mdadm.raid1 = {}; }
=> [ [ "zfs" "pool1" ] [ "zfs" "pool2" ] [ "mdadm" "raid1" ] ]
*/
deviceList = devices:
lib.concatLists (lib.mapAttrsToList (n: v: (map (x: [ n x ]) (lib.attrNames v))) devices);
deviceList =
devices:
lib.concatLists (
lib.mapAttrsToList (
n: v:
(map (x: [
n
x
]) (lib.attrNames v))
) devices
);
/* Takes either a string or null and returns the string or an empty string
/*
Takes either a string or null and returns the string or an empty string
maybeStr :: Either (str null) -> str
@@ -275,34 +355,46 @@ let
*/
maybeStr = x: lib.optionalString (x != null) x;
/* Takes a Submodules config and options argument and returns a serializable
/*
Takes a Submodules config and options argument and returns a serializable
subset of config variables as a shell script snippet.
*/
defineHookVariables = { options }:
defineHookVariables =
{ options }:
let
sanitizeName = lib.replaceStrings [ "-" ] [ "_" ];
isAttrsOfSubmodule = o: o.type.name == "attrsOf" && o.type.nestedTypes.elemType.name == "submodule";
isSerializable = n: o: !(
isSerializable =
n: o:
!(
lib.hasPrefix "_" n
|| lib.hasSuffix "Hook" n
|| isAttrsOfSubmodule o
# TODO don't hardcode diskoLib.subType options.
|| n == "content" || n == "partitions" || n == "datasets" || n == "swap"
|| n == "content"
|| n == "partitions"
|| n == "datasets"
|| n == "swap"
|| n == "mode"
);
in
lib.toShellVars
(lib.mapAttrs'
(n: o: lib.nameValuePair (sanitizeName n) o.value)
(lib.filterAttrs isSerializable options));
lib.toShellVars (
lib.mapAttrs' (n: o: lib.nameValuePair (sanitizeName n) o.value) (
lib.filterAttrs isSerializable options
)
);
mkHook = description: lib.mkOption {
mkHook =
description:
lib.mkOption {
inherit description;
type = lib.types.lines;
default = "";
};
mkSubType = module: lib.types.submodule [
mkSubType =
module:
lib.types.submodule [
module
{
@@ -320,13 +412,25 @@ let
}
];
mkCreateOption = { config, options, default }@attrs:
mkCreateOption =
{
config,
options,
default,
}@attrs:
lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.str;
default = ''
( # ${config.type} ${lib.concatMapStringsSep " " (n: toString (config.${n} or "")) ["name" "device" "format" "mountpoint"]} #
( # ${config.type} ${
lib.concatMapStringsSep " " (n: toString (config.${n} or "")) [
"name"
"device"
"format"
"mountpoint"
]
} #
${diskoLib.indent (diskoLib.defineHookVariables { inherit options; })}
${diskoLib.indent config.preCreateHook}
${diskoLib.indent attrs.default}
@@ -336,98 +440,131 @@ let
description = "Creation script";
};
mkMountOption = { config, options, default }@attrs:
mkMountOption =
{
config,
options,
default,
}@attrs:
lib.mkOption {
internal = true;
readOnly = true;
type = diskoLib.jsonType;
default = lib.mapAttrsRecursive
(_name: value:
if builtins.isString value then ''
default = lib.mapAttrsRecursive (
_name: value:
if builtins.isString value then
''
(
${diskoLib.indent (diskoLib.defineHookVariables { inherit options; })}
${diskoLib.indent config.preMountHook}
${diskoLib.indent value}
${diskoLib.indent config.postMountHook}
)
'' else value)
attrs.default;
''
else
value
) attrs.default;
description = "Mount script";
};
mkUnmountOption = { config, options, default }@attrs:
mkUnmountOption =
{
config,
options,
default,
}@attrs:
lib.mkOption {
internal = true;
readOnly = true;
type = diskoLib.jsonType;
default = lib.mapAttrsRecursive
(_name: value:
if builtins.isString value then ''
default = lib.mapAttrsRecursive (
_name: value:
if builtins.isString value then
''
(
${diskoLib.indent (diskoLib.defineHookVariables { inherit options; })}
${diskoLib.indent config.preUnmountHook}
${diskoLib.indent value}
${diskoLib.indent config.postUnmountHook}
)
'' else value)
attrs.default;
''
else
value
) attrs.default;
description = "Unmount script";
};
/* Writer for optionally checking bash scripts before writing them to the store
/*
Writer for optionally checking bash scripts before writing them to the store
writeCheckedBash :: AttrSet -> str -> str -> derivation
*/
writeCheckedBash = { pkgs, checked ? false, noDeps ? false }: pkgs.writers.makeScriptWriter {
writeCheckedBash =
{
pkgs,
checked ? false,
noDeps ? false,
}:
pkgs.writers.makeScriptWriter {
interpreter = if noDeps then "/usr/bin/env bash" else "${pkgs.bash}/bin/bash";
check = lib.optionalString (checked && !pkgs.stdenv.hostPlatform.isRiscV64 && !pkgs.stdenv.hostPlatform.isx86_32) (pkgs.writeScript "check" ''
check =
lib.optionalString
(checked && !pkgs.stdenv.hostPlatform.isRiscV64 && !pkgs.stdenv.hostPlatform.isx86_32)
(
pkgs.writeScript "check" ''
set -efu
# SC2054: our toShellVars function doesn't quote list elements with commas
# SC2034: We don't use all variables exported by hooks.
${pkgs.shellcheck}/bin/shellcheck -e SC2034,SC2054 "$1"
'');
''
);
};
/* Takes a disko device specification, returns an attrset with metadata
/*
Takes a disko device specification, returns an attrset with metadata
meta :: lib.types.devices -> AttrSet
*/
meta = toplevel: toplevel._meta;
/* Takes a disko device specification and returns a string which formats the disks
/*
Takes a disko device specification and returns a string which formats the disks
create :: lib.types.devices -> str
*/
create = toplevel: toplevel._create;
/* Takes a disko device specification and returns a string which mounts the disks
/*
Takes a disko device specification and returns a string which mounts the disks
mount :: lib.types.devices -> str
*/
mount = toplevel: toplevel._mount;
/* takes a disko device specification and returns a string which unmounts, destroys all disks and then runs create and mount
/*
takes a disko device specification and returns a string which unmounts, destroys all disks and then runs create and mount
zapCreateMount :: lib.types.devices -> str
*/
zapCreateMount = toplevel:
''
zapCreateMount = toplevel: ''
set -efux
${toplevel._disko}
'';
/* Takes a disko device specification and returns a nixos configuration
/*
Takes a disko device specification and returns a nixos configuration
config :: lib.types.devices -> nixosConfig
*/
config = toplevel: toplevel._config;
/* Takes a disko device specification and returns a function to get the needed packages to format/mount the disks
/*
Takes a disko device specification and returns a function to get the needed packages to format/mount the disks
packages :: lib.types.devices -> pkgs -> [ derivation ]
*/
packages = toplevel: toplevel._packages;
/* Checks whether nixpkgs is recent enough for vmTools to support the customQemu argument.
/*
Checks whether nixpkgs is recent enough for vmTools to support the customQemu argument.
Returns false, which is technically incorrect, for a few commits on 2024-07-08, but we can't be more accurate.
Make sure to pass lib, not pkgs.lib! See https://github.com/nix-community/disko/issues/904
@@ -453,8 +590,10 @@ let
pathname = lib.mkOptionType {
name = "pathname";
check = x:
with lib; let
check =
x:
with lib;
let
# The filter is used to normalize paths, i.e. to remove duplicated and
# trailing slashes. It also removes leading slashes, thus we have to
# check for "/" explicitly below.
@@ -466,11 +605,19 @@ let
};
};
/* topLevel type of the disko config, takes attrsets of disks, mdadms, zpools, nodevs, and lvm vgs.
*/
toplevel = lib.types.submodule (cfg:
# topLevel type of the disko config, takes attrsets of disks, mdadms, zpools, nodevs, and lvm vgs.
toplevel = lib.types.submodule (
cfg:
let
devices = { inherit (cfg.config) disk mdadm zpool lvm_vg nodev; };
devices = {
inherit (cfg.config)
disk
mdadm
zpool
lvm_vg
nodev
;
};
in
{
options = {
@@ -505,7 +652,9 @@ let
meta informationen generated by disko
currently used for building a dependency list so we know in which order to create the devices
'';
default = diskoLib.deepMergeMap (dev: dev._meta) (lib.flatten (map lib.attrValues (lib.attrValues devices)));
default = diskoLib.deepMergeMap (dev: dev._meta) (
lib.flatten (map lib.attrValues (lib.attrValues devices))
);
};
_packages = lib.mkOption {
internal = true;
@@ -513,16 +662,31 @@ let
packages required by the disko configuration
coreutils is always included
'';
default = pkgs: with lib; unique ((flatten (map (dev: dev._pkgs pkgs) (flatten (map attrValues (attrValues devices))))) ++ [ pkgs.coreutils-full ]);
default =
pkgs:
with lib;
unique (
(flatten (map (dev: dev._pkgs pkgs) (flatten (map attrValues (attrValues devices)))))
++ [ pkgs.coreutils-full ]
);
};
_scripts = lib.mkOption {
internal = true;
description = ''
The scripts generated by disko
'';
default = { pkgs, checked ? false }:
default =
{
pkgs,
checked ? false,
}:
let
throwIfNoDisksDetected = _: v: if devices.disk == { } then throw "No disks defined, did you forget to import your disko config?" else v;
throwIfNoDisksDetected =
_: v:
if devices.disk == { } then
throw "No disks defined, did you forget to import your disko config?"
else
v;
destroyDependencies = with pkgs; [
util-linux
e2fsprogs
@@ -557,32 +721,71 @@ let
export PATH=${lib.makeBinPath ((cfg.config._packages pkgs) ++ [ pkgs.bash ])}:$PATH
${cfg.config._formatMount}
'';
destroyFormatMount = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "/bin/disko-destroy-format-mount" ''
export PATH=${lib.makeBinPath ((cfg.config._packages pkgs) ++ [ pkgs.bash ] ++ destroyDependencies)}:$PATH
destroyFormatMount =
(diskoLib.writeCheckedBash { inherit pkgs checked; }) "/bin/disko-destroy-format-mount"
''
export PATH=${
lib.makeBinPath ((cfg.config._packages pkgs) ++ [ pkgs.bash ] ++ destroyDependencies)
}:$PATH
${cfg.config._destroyFormatMount}
'';
# These are useful to skip copying executables uploading a script to an in-memory installer
destroyNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-destroy" ''
destroyNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"/bin/disko-destroy"
''
${cfg.config._destroy}
'';
formatNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-format" ''
formatNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"/bin/disko-format"
''
${cfg.config._create}
'';
mountNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-mount" ''
mountNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"/bin/disko-mount"
''
${cfg.config._mount}
'';
unmountNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-unmount" ''
unmountNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"/bin/disko-unmount"
''
${cfg.config._unmount}
'';
formatMountNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-format-mount" ''
formatMountNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"/bin/disko-format-mount"
''
${cfg.config._formatMount}
'';
destroyFormatMountNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-destroy-format-mount" ''
destroyFormatMountNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"/bin/disko-destroy-format-mount"
''
${cfg.config._destroyFormatMount}
'';
# Legacy scripts, to be removed in version 2.0.0
# They are generally less useful, because the scripts are directly written to their $out path instead of
# into the $out/bin directory, which makes them incompatible with `nix run`
@@ -604,24 +807,50 @@ let
'';
diskoScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko" ''
export PATH=${lib.makeBinPath ((cfg.config._packages pkgs) ++ [ pkgs.bash ] ++ destroyDependencies)}:$PATH
export PATH=${
lib.makeBinPath ((cfg.config._packages pkgs) ++ [ pkgs.bash ] ++ destroyDependencies)
}:$PATH
${cfg.config._disko}
'';
# These are useful to skip copying executables uploading a script to an in-memory installer
destroyScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-destroy" ''
destroyScriptNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"disko-destroy"
''
${cfg.config._legacyDestroy}
'';
formatScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-format" ''
formatScriptNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"disko-format"
''
${cfg.config._create}
'';
mountScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-mount" ''
mountScriptNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"disko-mount"
''
${cfg.config._mount}
'';
diskoScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko" ''
diskoScriptNoDeps =
(diskoLib.writeCheckedBash {
inherit pkgs checked;
noDeps = true;
})
"disko"
''
${cfg.config._disko}
'';
};
@@ -687,8 +916,10 @@ let
The script to create all devices defined by disko.devices
'';
default =
with lib; let
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }) devices;
with lib;
let
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }
) devices;
in
''
set -efux
@@ -707,9 +938,13 @@ let
The script to mount all devices defined by disko.devices
'';
default =
with lib; let
fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or { }) (flatten (map attrValues (attrValues devices)));
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }) devices;
with lib;
let
fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or { }) (
flatten (map attrValues (attrValues devices))
);
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }
) devices;
in
''
set -efux
@@ -727,9 +962,13 @@ let
The script to unmount all devices defined by disko.devices
'';
default =
with lib; let
fsMounts = diskoLib.deepMergeMap (dev: dev._unmount.fs or { }) (flatten (map attrValues (attrValues devices)));
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }) devices;
with lib;
let
fsMounts = diskoLib.deepMergeMap (dev: dev._unmount.fs or { }) (
flatten (map attrValues (attrValues devices))
);
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }
) devices;
in
''
set -efux
@@ -737,7 +976,9 @@ let
${concatStrings (lib.reverseList (attrValues fsMounts))}
# Than close the devices
${concatMapStrings (dev: (attrByPath (dev ++ [ "_unmount" ]) {} devices).dev or "") (lib.reverseList sortedDeviceList)}
${concatMapStrings (dev: (attrByPath (dev ++ [ "_unmount" ]) { } devices).dev or "") (
lib.reverseList sortedDeviceList
)}
'';
};
_disko = lib.mkOption {
@@ -782,39 +1023,33 @@ let
The NixOS config generated by disko
'';
default =
with lib; let
configKeys = flatten (map attrNames (flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices))))));
with lib;
let
configKeys = flatten (
map attrNames (flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices)))))
);
collectedConfigs = flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices))));
in
genAttrs configKeys (key: mkMerge (catAttrs key collectedConfigs));
};
};
});
}
);
# import all the types from the types directory
types = lib.listToAttrs (
map
(file: lib.nameValuePair
(lib.removeSuffix ".nix" file)
(diskoLib.mkSubType (./types + "/${file}"))
)
(lib.attrNames (builtins.readDir ./types))
map (
file: lib.nameValuePair (lib.removeSuffix ".nix" file) (diskoLib.mkSubType (./types + "/${file}"))
) (lib.attrNames (builtins.readDir ./types))
);
# render types into an json serializable format
serializeType = type:
serializeType =
type:
let
options = lib.filter (x: !lib.hasPrefix "_" x) (lib.attrNames type.options);
in
lib.listToAttrs (
map
(option: lib.nameValuePair
option
type.options.${option}
)
options
);
lib.listToAttrs (map (option: lib.nameValuePair option type.options.${option}) options);
typesSerializerLib = {
rootMountPoint = "";
@@ -855,7 +1090,10 @@ let
};
either = t1: t2: {
type = "oneOf";
types = [ t1 t2 ];
types = [
t1
t2
];
};
enum = choices: {
type = "enum";
@@ -867,7 +1105,9 @@ let
str = "str";
bool = "bool";
int = "int";
submodule = x: x {
submodule =
x:
x {
inherit (diskoLib.typesSerializerLib) lib config options;
name = "<self.name>";
};
@@ -878,7 +1118,9 @@ let
# Spoof these types to avoid infinite recursion
deviceType = _: "<deviceType>";
partitionType = _: "<partitionType>";
subType = { types, ... }: {
subType =
{ types, ... }:
{
type = "oneOf";
types = lib.attrNames types;
};
@@ -886,15 +1128,16 @@ let
};
};
jsonTypes = lib.listToAttrs
(
map
(file: lib.nameValuePair
(lib.removeSuffix ".nix" file)
(diskoLib.serializeType (import (./types + "/${file}") diskoLib.typesSerializerLib))
jsonTypes =
lib.listToAttrs (
map (
file:
lib.nameValuePair (lib.removeSuffix ".nix" file) (
diskoLib.serializeType (import (./types + "/${file}") diskoLib.typesSerializerLib)
)
(lib.filter (name: lib.hasSuffix ".nix" name) (lib.attrNames (builtins.readDir ./types)))
) // {
) (lib.filter (name: lib.hasSuffix ".nix" name) (lib.attrNames (builtins.readDir ./types)))
)
// {
partitionType = {
type = "oneOf";
types = lib.attrNames diskoLib._partitionTypes;

View File

@@ -1,8 +1,16 @@
{ diskoLib, modulesPath, config, pkgs, lib, ... }:
{
diskoLib,
modulesPath,
config,
pkgs,
lib,
...
}:
let
vm_disko = (diskoLib.testLib.prepareDiskoConfig config diskoLib.testLib.devices).disko;
cfg_ = (lib.evalModules {
cfg_ =
(lib.evalModules {
modules = lib.singleton {
# _file = toString input;
imports = lib.singleton { disko.devices = vm_disko.devices; };
@@ -26,13 +34,11 @@ let
deviceExtraOpts.bootindex = "1";
deviceExtraOpts.serial = "root";
};
otherDisks = map
(disk: {
otherDisks = map (disk: {
name = disk.name;
file = ''"$tmp"/${lib.escapeShellArg disk.name}.qcow2'';
driveExtraOpts.werror = "report";
})
(builtins.tail disks);
}) (builtins.tail disks);
diskoBasedConfiguration = {
# generated from disko config

View File

@@ -1,10 +1,11 @@
{ config
, diskoLib
, lib
, extendModules
, options
, imagePkgs
, ...
{
config,
diskoLib,
lib,
extendModules,
options,
imagePkgs,
...
}:
let
diskoCfg = config.disko;
@@ -13,16 +14,25 @@ let
checked = diskoCfg.checkScripts;
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) ''
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
${pkgs.systemdMinimal}/lib/systemd/systemd-binfmt <(echo ${lib.strings.escapeShellArg binfmt.binfmtRegistration})
'';
vmTools = pkgs.vmTools.override
({
rootModules = [
"9p" "9pnet_virtio" # we can drop those in future if we stop supporting 24.11
vmTools = pkgs.vmTools.override (
{
rootModules =
[
"9p"
"9pnet_virtio" # we can drop those in future if we stop supporting 24.11
"virtiofs"
"virtio_pci"
@@ -32,14 +42,17 @@ let
]
++ (lib.optional configSupportsZfs "zfs")
++ cfg.extraRootModules;
kernel = pkgs.aggregateModules
([ cfg.kernelPackages.kernel ]
++ lib.optional (lib.elem "zfs" cfg.extraRootModules || configSupportsZfs) cfg.kernelPackages.${config.boot.zfs.package.kernelModuleAttribute});
kernel = pkgs.aggregateModules (
[ cfg.kernelPackages.kernel ]
++ 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;
});
}
);
cleanedConfig = diskoLib.testLib.prepareDiskoConfig config diskoLib.testLib.devices;
systemToInstall = extendModules {
modules = [
@@ -51,7 +64,9 @@ let
}
];
};
systemToInstallNative = if binfmt.systemsAreDifferent then extendModules {
systemToInstallNative =
if binfmt.systemsAreDifferent then
extendModules {
modules = [
cfg.extraConfig
{
@@ -62,8 +77,11 @@ let
}
];
}
else systemToInstall;
dependencies = with pkgs; [
else
systemToInstall;
dependencies =
with pkgs;
[
bash
coreutils
gnused
@@ -73,11 +91,13 @@ let
util-linux
findutils
kmod
] ++ cfg.extraDependencies;
]
++ cfg.extraDependencies;
preVM = ''
# shellcheck disable=SC2154
mkdir -p "$out"
${lib.concatMapStringsSep "\n" (disk:
${lib.concatMapStringsSep "\n" (
disk:
# shellcheck disable=SC2154
"${pkgs.qemu}/bin/qemu-img create -f ${imageFormat} \"$out/${disk.imageName}.${imageFormat}\" ${disk.imageSize}"
) (lib.attrValues diskoCfg.devices.disk)}
@@ -127,24 +147,26 @@ let
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"
] ++ builtins.map
(disk:
]
++ builtins.map (
disk:
"-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
{
system.build.diskoImages = vmTools.runInLinuxVM (pkgs.runCommand cfg.name
{
system.build.diskoImages = vmTools.runInLinuxVM (
pkgs.runCommand cfg.name {
buildInputs = dependencies;
inherit preVM QEMU_OPTS;
postVM = cfg.extraPostVM;
inherit (diskoCfg) memSize;
}
(binfmtSetup + partitioner + installer));
} (binfmtSetup + partitioner + installer)
);
system.build.diskoImagesScript = diskoLib.writeCheckedBash { inherit checked pkgs; } cfg.name ''
set -efu
@@ -209,7 +231,8 @@ in
shift
done
export preVM=${diskoLib.writeCheckedBash { inherit pkgs checked; } "preVM.sh" ''
export preVM=${
diskoLib.writeCheckedBash { inherit pkgs checked; } "preVM.sh" ''
set -efu
mv copy_before_disko copy_after_disko xchg/
origBuilder=${pkgs.writeScript "disko-builder" ''
@@ -234,7 +257,8 @@ in
''}
echo "export origBuilder=$origBuilder" >> xchg/saved-env
${preVM}
''}
''
}
export postVM=${diskoLib.writeCheckedBash { inherit pkgs checked; } "postVM.sh" cfg.extraPostVM}
build_memory=''${build_memory:-${builtins.toString diskoCfg.memSize}}

View File

@@ -1,25 +1,34 @@
{ lib
, makeTest
, eval-config
, ...
{
lib,
makeTest,
eval-config,
...
}:
let
testLib = {
# 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.
prepareDiskoConfig = cfg: devices:
prepareDiskoConfig =
cfg: devices:
let
cleanedTopLevel = lib.filterAttrsRecursive (n: _: !lib.hasPrefix "_" n) cfg;
preparedDisks = lib.foldlAttrs
preparedDisks =
lib.foldlAttrs
(acc: n: v: {
devices = lib.tail acc.devices;
grub-devices = acc.grub-devices ++ (lib.optional (lib.any (part: (part.type or "") == "EF02") (lib.attrValues (v.content.partitions or { }))) (lib.head acc.devices));
grub-devices =
acc.grub-devices
++ (lib.optional (lib.any (part: (part.type or "") == "EF02") (
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; };
content = v.content // {
device = lib.head acc.devices;
};
};
};
})
@@ -30,8 +39,10 @@ let
}
cleanedTopLevel.disko.devices.disk;
in
cleanedTopLevel // {
boot.loader.grub.devices = if (preparedDisks.grub-devices != [ ]) then preparedDisks.grub-devices else [ "nodev" ];
cleanedTopLevel
// {
boot.loader.grub.devices =
if (preparedDisks.grub-devices != [ ]) then preparedDisks.grub-devices else [ "nodev" ];
disko.devices = cleanedTopLevel.disko.devices // {
disk = preparedDisks.disks;
};
@@ -58,33 +69,31 @@ let
# This is the test generator for a disko test
makeDiskoTest =
{ name
, disko-config
, extendModules ? null
, pkgs ? import <nixpkgs> { }
, extraTestScript ? ""
, bootCommands ? ""
, extraInstallerConfig ? { }
, extraSystemConfig ? { }
, efi ? !pkgs.stdenv.hostPlatform.isRiscV64
, postDisko ? ""
, testMode ? "module" # can be one of direct module cli
, testBoot ? true # if we actually want to test booting or just create/mount
, enableOCR ? false
{
name,
disko-config,
extendModules ? null,
pkgs ? import <nixpkgs> { },
extraTestScript ? "",
bootCommands ? "",
extraInstallerConfig ? { },
extraSystemConfig ? { },
efi ? !pkgs.stdenv.hostPlatform.isRiscV64,
postDisko ? "",
testMode ? "module", # can be one of direct module cli
testBoot ? true, # if we actually want to test booting or just create/mount
enableOCR ? false,
}:
let
makeTest' = args:
makeTest' =
args:
makeTest args {
inherit pkgs;
inherit (pkgs) system;
};
# for installation we skip /dev/vda because it is the test runner disk
importedDiskoConfig =
if builtins.isPath disko-config then
import disko-config
else
disko-config;
importedDiskoConfig = if builtins.isPath disko-config then import disko-config else disko-config;
diskoConfigWithArgs =
if builtins.isFunction importedDiskoConfig then
@@ -104,7 +113,9 @@ let
tsp-config = tsp-generator.config testConfigBooted;
num-disks = builtins.length (lib.attrNames testConfigBooted.disko.devices.disk);
installed-system = { config, ... }: {
installed-system =
{ config, ... }:
{
imports = [
(lib.optionalAttrs (testMode == "direct") tsp-config)
(lib.optionalAttrs (testMode == "module") {
@@ -132,18 +143,24 @@ let
inherit (pkgs) system;
};
installedTopLevel = ((if extendModules != null then extendModules else installed-system-eval.extendModules) {
installedTopLevel =
((if extendModules != null then extendModules else installed-system-eval.extendModules) {
modules = [
({ config, ... }: {
(
{ config, ... }:
{
imports = [
extraSystemConfig
({ modulesPath, ... }: {
(
{ 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
@@ -156,7 +173,11 @@ let
device = "nix-store";
fsType = "9p";
neededForBoot = true;
options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
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
@@ -166,7 +187,8 @@ let
assertions = [
{
assertion = builtins.length config.boot.loader.grub.mirroredBoots > 1 -> config.boot.loader.grub.devices == [ ];
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 [];`.
@@ -174,7 +196,8 @@ let
'';
}
];
})
}
)
];
}).config.system.build.toplevel;
@@ -184,7 +207,9 @@ let
meta.timeout = 600; # 10 minutes
inherit enableOCR;
nodes.machine = { pkgs, ... }: {
nodes.machine =
{ pkgs, ... }:
{
imports = [
(lib.optionalAttrs (testMode == "module") {
imports = [
@@ -199,17 +224,37 @@ let
extraInstallerConfig
# from base.nix
({ config, ... }: {
(
{ config, ... }:
{
boot.supportedFilesystems =
[ "btrfs" "cifs" "f2fs" "jfs" "ntfs" "reiserfs" "vfat" "xfs" ] ++
lib.optional (config.networking.hostId != null && lib.meta.availableOn pkgs.stdenv.hostPlatform config.boot.zfs.package) "zfs";
})
[
"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 {
(
if lib.versionAtLeast (lib.versions.majorMinor lib.version) "23.11" then
{
boot.swraid.enable = true;
} else {
}
else
{
boot.initrd.services.swraid.enable = true;
})
}
)
];
systemd.services.mdmonitor.enable = false; # silence some weird warnings
@@ -227,11 +272,9 @@ let
connect-timeout = 1;
};
networking.hostId = lib.mkIf
(
networking.hostId = lib.mkIf (
(testConfigInstall ? networking.hostId) && (testConfigInstall.networking.hostId != null)
)
testConfigInstall.networking.hostId;
) testConfigInstall.networking.hostId;
virtualisation.emptyDiskImages = builtins.genList (_: 4096) num-disks;
@@ -239,7 +282,9 @@ let
system.build.systemToInstall = installed-system-eval;
};
testScript = { nodes, ... }: ''
testScript =
{ nodes, ... }:
''
def disks(oldmachine, num_disks):
disk_flags = []
for i in range(num_disks):
@@ -311,7 +356,9 @@ let
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")
machine.succeed("nix-store --load-db < ${
pkgs.closureInfo { rootPaths = [ installedTopLevel ]; }
}/registration")
# fix "this is not a NixOS installation"
machine.succeed("mkdir -p /mnt/etc")

View File

@@ -1,7 +1,19 @@
{ config, options, diskoLib, lib, rootMountPoint, parent, device, ... }:
{
config,
options,
diskoLib,
lib,
rootMountPoint,
parent,
device,
...
}:
let
swapType = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
size = lib.mkOption {
type = lib.types.strMatching "^([0-9]+[KMGTP])?$";
@@ -31,30 +43,29 @@ let
description = "Options used to mount the swap.";
};
};
}));
}
)
);
default = { };
description = "Swap files";
};
swapConfig = { mountpoint, swap }:
swapConfig =
{ mountpoint, swap }:
{
swapDevices = builtins.map
(file: {
swapDevices = builtins.map (file: {
device = "${mountpoint}/${file.path}";
inherit (file) priority options;
})
(lib.attrValues swap);
}) (lib.attrValues swap);
};
swapCreate = mountpoint: swap:
lib.concatMapStringsSep
"\n"
(file: ''
swapCreate =
mountpoint: swap:
lib.concatMapStringsSep "\n" (file: ''
if ! test -e "${mountpoint}/${file.path}"; then
btrfs filesystem mkswapfile --size ${file.size} "${mountpoint}/${file.path}"
fi
'')
(lib.attrValues swap);
'') (lib.attrValues swap);
in
{
@@ -80,7 +91,10 @@ in
description = "A list of options to pass to mount.";
};
subvolumes = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ config, ... }: {
type = lib.types.attrsOf (
lib.types.submodule (
{ config, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
@@ -110,7 +124,9 @@ in
};
swap = swapType;
};
}));
}
)
);
default = { };
description = "Subvolumes to define for BTRFS.";
};
@@ -169,9 +185,13 @@ in
inherit config options;
default =
let
subvolMounts = lib.concatMapAttrs
(_: subvol:
lib.warnIf (subvol.mountOptions != (options.subvolumes.type.getSubOptions [ ]).mountOptions.default && subvol.mountpoint == null)
subvolMounts = lib.concatMapAttrs (
_: subvol:
lib.warnIf
(
subvol.mountOptions != (options.subvolumes.type.getSubOptions [ ]).mountOptions.default
&& subvol.mountpoint == null
)
"Subvolume ${subvol.name} has mountOptions but no mountpoint. See upgrade guide (2023-07-09 121df48)."
lib.optionalAttrs
(subvol.mountpoint != null)
@@ -179,16 +199,19 @@ in
${subvol.mountpoint} = ''
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}" ])} \
${
lib.concatMapStringsSep " " (opt: "-o ${opt}") (subvol.mountOptions ++ [ "subvol=${subvol.name}" ])
} \
-o X-mount.mkdir
fi
'';
}
)
config.subvolumes;
) config.subvolumes;
in
{
fs = subvolMounts // lib.optionalAttrs (config.mountpoint != null) {
fs =
subvolMounts
// lib.optionalAttrs (config.mountpoint != null) {
${config.mountpoint} = ''
if ! findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
mount "${config.device}" "${rootMountPoint}${config.mountpoint}" \
@@ -203,22 +226,21 @@ in
inherit config options;
default =
let
subvolMounts = lib.concatMapAttrs
(_: subvol:
lib.optionalAttrs
(subvol.mountpoint != null)
{
subvolMounts = lib.concatMapAttrs (
_: subvol:
lib.optionalAttrs (subvol.mountpoint != null) {
${subvol.mountpoint} = ''
if findmnt "${config.device}" "${rootMountPoint}${subvol.mountpoint}" > /dev/null 2>&1; then
umount "${rootMountPoint}${subvol.mountpoint}"
fi
'';
}
)
config.subvolumes;
) config.subvolumes;
in
{
fs = subvolMounts // lib.optionalAttrs (config.mountpoint != null) {
fs =
subvolMounts
// lib.optionalAttrs (config.mountpoint != null) {
${config.mountpoint} = ''
if findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
umount "${rootMountPoint}${config.mountpoint}"
@@ -231,8 +253,8 @@ in
internal = true;
readOnly = true;
default = [
(map
(subvol:
(map (
subvol:
lib.optional (subvol.mountpoint != null) {
fileSystems.${subvol.mountpoint} = {
device = config.device;
@@ -240,8 +262,7 @@ in
options = subvol.mountOptions ++ [ "subvol=${subvol.name}" ];
};
}
)
(lib.attrValues config.subvolumes))
) (lib.attrValues config.subvolumes))
(lib.optional (config.mountpoint != null) {
fileSystems.${config.mountpoint} = {
device = config.device;
@@ -249,11 +270,12 @@ in
options = config.mountOptions;
};
})
(map
(subvol: swapConfig {
(map (
subvol:
swapConfig {
inherit (subvol) mountpoint swap;
})
(lib.attrValues config.subvolumes))
}
) (lib.attrValues config.subvolumes))
(swapConfig {
inherit (config) mountpoint swap;
})
@@ -264,8 +286,10 @@ in
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs:
[ pkgs.btrfs-progs pkgs.gnugrep ];
default = pkgs: [
pkgs.btrfs-progs
pkgs.gnugrep
];
description = "Packages";
};
};

View File

@@ -1,4 +1,10 @@
{ config, options, lib, diskoLib, ... }:
{
config,
options,
lib,
diskoLib,
...
}:
{
options = {
name = lib.mkOption {
@@ -32,13 +38,20 @@
'';
default = "2G";
};
content = diskoLib.deviceType { parent = config; device = config.device; };
content = diskoLib.deviceType {
parent = config;
device = config.device;
};
_meta = lib.mkOption {
internal = true;
readOnly = true;
type = diskoLib.jsonType;
default =
lib.optionalAttrs (config.content != null) (config.content._meta [ "disk" config.device ]);
default = lib.optionalAttrs (config.content != null) (
config.content._meta [
"disk"
config.device
]
);
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
@@ -56,8 +69,7 @@
_config = lib.mkOption {
internal = true;
readOnly = true;
default =
lib.optional (config.content != null) config.content._config;
default = lib.optional (config.content != null) config.content._config;
description = "NixOS configuration";
};
_pkgs = lib.mkOption {

View File

@@ -1,4 +1,13 @@
{ config, options, lib, diskoLib, rootMountPoint, parent, device, ... }:
{
config,
options,
lib,
diskoLib,
rootMountPoint,
parent,
device,
...
}:
{
options = {
type = lib.mkOption {
@@ -90,18 +99,32 @@
internal = true;
readOnly = true;
# type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs:
[ pkgs.util-linux pkgs.gnugrep ] ++ (
default =
pkgs:
[
pkgs.util-linux
pkgs.gnugrep
]
++ (
# TODO add many more
if (config.format == "xfs") then [ pkgs.xfsprogs ]
else if (config.format == "btrfs") then [ pkgs.btrfs-progs ]
else if (config.format == "vfat") then [ pkgs.dosfstools ]
else if (config.format == "ext2") then [ pkgs.e2fsprogs ]
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 [ ]
if (config.format == "xfs") then
[ pkgs.xfsprogs ]
else if (config.format == "btrfs") then
[ pkgs.btrfs-progs ]
else if (config.format == "vfat") then
[ pkgs.dosfstools ]
else if (config.format == "ext2") then
[ pkgs.e2fsprogs ]
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";
};

View File

@@ -1,4 +1,12 @@
{ config, options, lib, diskoLib, parent, device, ... }:
{
config,
options,
lib,
diskoLib,
parent,
device,
...
}:
let
sortedPartitions = lib.sort (x: y: x.priority < y.priority) (lib.attrValues config.partitions);
sortedHybridPartitions = lib.filter (p: p.hybrid != null) sortedPartitions;
@@ -16,17 +24,32 @@ in
description = "Device to use for the partition table";
};
partitions = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@partition: {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }@partition:
{
options = {
type = lib.mkOption {
type =
let
hexPattern = len: "[A-Fa-f0-9]{${toString len}}";
in
lib.types.either
(lib.types.strMatching (hexPattern 4))
(lib.types.strMatching (lib.concatMapStringsSep "-" hexPattern [ 8 4 4 4 12 ]));
default = if partition.config.content != null && partition.config.content.type == "swap" then "8200" else "8300";
lib.types.either (lib.types.strMatching (hexPattern 4)) (
lib.types.strMatching (
lib.concatMapStringsSep "-" hexPattern [
8
4
4
4
12
]
)
);
default =
if partition.config.content != null && partition.config.content.type == "swap" then
"8200"
else
"8300";
defaultText = ''8300 (Linux filesystem) normally, 8200 (Linux swap) if content.type is "swap"'';
description = ''
Filesystem type to use.
@@ -80,7 +103,9 @@ in
default = name;
};
uuid = lib.mkOption {
type = lib.types.nullOr (lib.types.strMatching "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}");
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";
@@ -120,7 +145,19 @@ in
};
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;
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";
};
@@ -141,9 +178,15 @@ in
or - for relative sizes from the disks end
'';
};
content = diskoLib.partitionType { parent = config; device = partition.config.device; };
content = diskoLib.partitionType {
parent = config;
device = partition.config.device;
};
hybrid = lib.mkOption {
type = lib.types.nullOr (lib.types.submodule ({ ... } @ hp: {
type = lib.types.nullOr (
lib.types.submodule (
{ ... }@hp:
{
options = {
mbrPartitionType = lib.mkOption {
type = lib.types.nullOr lib.types.str;
@@ -169,7 +212,9 @@ in
'';
};
};
}));
}
)
);
default = null;
description = "Entry to add to the Hybrid MBR table";
};
@@ -180,7 +225,9 @@ in
defaultText = null;
};
};
}));
}
)
);
default = { };
description = "Attrs of partitions to add to the partition table";
};
@@ -197,12 +244,13 @@ in
internal = true;
readOnly = true;
type = lib.types.functionTo diskoLib.jsonType;
default = dev:
lib.foldr lib.recursiveUpdate { } (map
(partition:
lib.optionalAttrs (partition.content != null) (partition.content._meta dev)
default =
dev:
lib.foldr lib.recursiveUpdate { } (
map (partition: lib.optionalAttrs (partition.content != null) (partition.content._meta dev)) (
lib.attrValues config.partitions
)
(lib.attrValues config.partitions));
);
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
@@ -211,16 +259,23 @@ in
if ! blkid "${config.device}" >&2; then
sgdisk --clear "${config.device}"
fi
${lib.concatMapStrings (partition:
${lib.concatMapStrings (
partition:
let
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}" \
--typecode=${toString partition._index}:${partition.type} \
"${config.device}" \
'';
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} \
'';
in
@@ -237,35 +292,30 @@ in
''
) sortedPartitions}
${
lib.optionalString (sortedHybridPartitions != [])
("sgdisk -h "
${lib.optionalString (sortedHybridPartitions != [ ]) (
"sgdisk -h "
+ (lib.concatStringsSep ":" (map (p: (toString p._index)) sortedHybridPartitions))
+ (
lib.optionalString (!config.efiGptPartitionFirst) ":EE "
)
+ ''"${parent.device}"'')
}
${lib.concatMapStrings (p:
p.hybrid._create
)
sortedHybridPartitions
}
+ (lib.optionalString (!config.efiGptPartitionFirst) ":EE ")
+ ''"${parent.device}"''
)}
${lib.concatMapStrings (p: p.hybrid._create) sortedHybridPartitions}
${lib.concatStrings (map (partition: ''
${lib.concatStrings (
map (partition: ''
${lib.optionalString (partition.content != null) partition.content._create}
'') sortedPartitions)}
'') sortedPartitions
)}
'';
};
_mount = diskoLib.mkMountOption {
inherit config options;
default =
let
partMounts = lib.foldr lib.recursiveUpdate { } (map
(partition:
lib.optionalAttrs (partition.content != null) partition.content._mount
partMounts = lib.foldr lib.recursiveUpdate { } (
map (partition: lib.optionalAttrs (partition.content != null) partition.content._mount) (
lib.attrValues config.partitions
)
(lib.attrValues config.partitions));
);
in
{
dev = partMounts.dev or "";
@@ -276,11 +326,11 @@ in
inherit config options;
default =
let
partMounts = lib.foldr lib.recursiveUpdate { } (map
(partition:
lib.optionalAttrs (partition.content != null) partition.content._unmount
partMounts = lib.foldr lib.recursiveUpdate { } (
map (partition: lib.optionalAttrs (partition.content != null) partition.content._unmount) (
lib.attrValues config.partitions
)
(lib.attrValues config.partitions));
);
in
{
dev = partMounts.dev or "";
@@ -290,11 +340,10 @@ in
_config = lib.mkOption {
internal = true;
readOnly = true;
default = (map
(partition:
lib.optional (partition.content != null) partition.content._config
)
(lib.attrValues config.partitions))
default =
(map (partition: lib.optional (partition.content != null) partition.content._config) (
lib.attrValues config.partitions
))
++ (lib.optional (lib.any (part: part.type == "EF02") (lib.attrValues config.partitions)) {
boot.loader.grub.devices = [ config.device ];
});
@@ -304,16 +353,18 @@ in
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs:
default =
pkgs:
[
pkgs.gptfdisk
pkgs.systemdMinimal
pkgs.parted # for partprobe
] ++ lib.flatten (map
(partition:
lib.optional (partition.content != null) (partition.content._pkgs pkgs)
]
++ lib.flatten (
map (partition: lib.optional (partition.content != null) (partition.content._pkgs pkgs)) (
lib.attrValues config.partitions
)
(lib.attrValues config.partitions));
);
description = "Packages";
};
};

View File

@@ -1,20 +1,30 @@
{ config, options, lib, diskoLib, parent, device, ... }:
{
config,
options,
lib,
diskoLib,
parent,
device,
...
}:
let
keyFile =
if config.settings ? "keyFile"
then config.settings.keyFile
else if config.askPassword
then ''<(set +x; echo -n "$password"; set -x)''
else if config.passwordFile != null
if config.settings ? "keyFile" then
config.settings.keyFile
else if config.askPassword then
''<(set +x; echo -n "$password"; set -x)''
else if
config.passwordFile != null
# do not print the password to the console
then ''<(set +x; echo -n "$(cat ${config.passwordFile})"; set -x)''
else if config.keyFile != null
then
lib.warn
("The option `keyFile` is deprecated."
+ "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;
''<(set +x; echo -n "$(cat ${config.passwordFile})"; set -x)''
else if config.keyFile != null then
lib.warn (
"The option `keyFile` is deprecated."
+ "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 = ''
${lib.optionalString (keyFile != null) "--key-file ${keyFile}"} \
${lib.optionalString (lib.hasAttr "keyFileSize" config.settings) "--keyfile-size ${builtins.toString config.settings.keyFileSize}"} \
@@ -23,7 +33,10 @@ let
cryptsetupOpen = ''
cryptsetup open "${config.device}" "${config.name}" \
${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} \
${keyFileArgs} \
'';
@@ -66,7 +79,8 @@ in
type = lib.types.attrsOf lib.types.anything;
default = { };
description = "LUKS settings (as defined in configuration.nix in boot.initrd.luks.devices.<name>)";
example = ''{
example = ''
{
keyFile = "/tmp/disk.key";
keyFileSize = 2048;
keyFileOffset = 1024;
@@ -98,7 +112,10 @@ in
description = "Extra arguments to pass to `cryptsetup luksOpen` when opening";
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 {
internal = true;
default = parent;
@@ -107,8 +124,7 @@ in
internal = true;
readOnly = true;
type = lib.types.functionTo diskoLib.jsonType;
default = dev:
lib.optionalAttrs (config.content != null) (config.content._meta dev);
default = dev: lib.optionalAttrs (config.content != null) (config.content._meta dev);
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
@@ -136,9 +152,11 @@ in
''}
cryptsetup -q luksFormat "${config.device}" ${toString config.extraFormatArgs} ${keyFileArgs}
${cryptsetupOpen} --persistent
${toString (lib.forEach config.additionalKeyFiles (keyFile: ''
${toString (
lib.forEach config.additionalKeyFiles (keyFile: ''
cryptsetup luksAddKey "${config.device}" ${keyFile} ${keyFileArgs}
''))}
'')
)}
fi
${lib.optionalString (config.content != null) config.content._create}
'';
@@ -188,7 +206,8 @@ in
_config = lib.mkOption {
internal = true;
readOnly = true;
default = [ ]
default =
[ ]
# If initrdUnlock is true, then add a device entry to the initrd.luks.devices config.
++ (lib.optional config.initrdUnlock [
{
@@ -196,14 +215,21 @@ in
inherit (config) device;
} // config.settings;
}
]) ++ (lib.optional (config.content != null) config.content._config);
])
++ (lib.optional (config.content != null) config.content._config);
description = "NixOS configuration";
};
_pkgs = lib.mkOption {
internal = true;
readOnly = true;
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";
};
};

View File

@@ -1,4 +1,12 @@
{ config, options, lib, diskoLib, parent, device, ... }:
{
config,
options,
lib,
diskoLib,
parent,
device,
...
}:
{
options = {
type = lib.mkOption {
@@ -55,7 +63,10 @@
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs: [ pkgs.gnugrep pkgs.lvm2 ];
default = pkgs: [
pkgs.gnugrep
pkgs.lvm2
];
description = "Packages";
};
};

View File

@@ -1,14 +1,22 @@
{ config, options, lib, diskoLib, ... }:
{
config,
options,
lib,
diskoLib,
...
}:
let
# Load kernel modules to ensure device mapper types are available
kernelModules =
[
# Prevent unbootable systems if LVM snapshots are present at boot time.
"dm-snapshot"
] ++
lib.filter (x: x != "") (map
(lv: lib.optionalString (lv.lvm_type != null && lv.lvm_type != "thinlv") "dm-${lv.lvm_type}")
(lib.attrValues config.lvs));
]
++ lib.filter (x: x != "") (
map (lv: lib.optionalString (lv.lvm_type != null && lv.lvm_type != "thinlv") "dm-${lv.lvm_type}") (
lib.attrValues config.lvs
)
);
in
{
options = {
@@ -23,7 +31,10 @@ in
description = "Type";
};
lvs = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@lv: {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }@lv:
{
options = {
name = lib.mkOption {
type = lib.types.str;
@@ -32,7 +43,9 @@ in
};
priority = lib.mkOption {
type = lib.types.int;
default = (if lv.config.lvm_type == "thin-pool" then 501 else 1000) + (if lib.hasInfix "100%" lv.config.size then 251 else 0);
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 ''
if (lib.hasInfix "100%" lv.config.size) then 9001 else 1000
'';
@@ -44,7 +57,18 @@ in
};
lvm_type = lib.mkOption {
# TODO: add raid10
type = lib.types.nullOr (lib.types.enum [ "mirror" "raid0" "raid1" "raid4" "raid5" "raid6" "thin-pool" "thinlv" ]); # TODO add all lib.types
type = lib.types.nullOr (
lib.types.enum [
"mirror"
"raid0"
"raid1"
"raid4"
"raid5"
"raid6"
"thin-pool"
"thinlv"
]
); # TODO add all lib.types
default = null; # maybe there is always a default type?
description = "LVM type";
};
@@ -58,9 +82,14 @@ in
default = null;
description = "Name of pool LV that this LV belongs to";
};
content = diskoLib.partitionType { parent = config; device = "/dev/${config.name}/${lv.config.name}"; };
content = diskoLib.partitionType {
parent = config;
device = "/dev/${config.name}/${lv.config.name}";
};
}));
};
}
)
);
default = { };
description = "LVS for the volume group";
};
@@ -68,12 +97,15 @@ in
internal = true;
readOnly = true;
type = diskoLib.jsonType;
default =
diskoLib.deepMergeMap
(lv:
lib.optionalAttrs (lv.content != null) (lv.content._meta [ "lvm_vg" config.name ])
default = diskoLib.deepMergeMap (
lv:
lib.optionalAttrs (lv.content != null) (
lv.content._meta [
"lvm_vg"
config.name
]
)
(lib.attrValues config.lvs);
) (lib.attrValues config.lvs);
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
@@ -93,8 +125,14 @@ in
if ! lvdisplay "${config.name}/${lv.name}"; then
lvcreate \
--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} \
-n "${lv.name}" \
${lib.optionalString (lv.lvm_type == "thinlv") "--thinpool=${lv.pool}"} \
@@ -113,11 +151,9 @@ in
inherit config options;
default =
let
lvMounts = diskoLib.deepMergeMap
(lv:
lib.optionalAttrs (lv.content != null) lv.content._mount
)
(lib.attrValues config.lvs);
lvMounts = diskoLib.deepMergeMap (lv: lib.optionalAttrs (lv.content != null) lv.content._mount) (
lib.attrValues config.lvs
);
in
{
dev = ''
@@ -131,12 +167,11 @@ in
inherit config options;
default =
let
lvMounts = diskoLib.deepMergeMap
(lv:
lib.optionalAttrs (lv.content != null) lv.content._unmount
)
(lib.attrValues config.lvs);
in {
lvMounts = diskoLib.deepMergeMap (lv: lib.optionalAttrs (lv.content != null) lv.content._unmount) (
lib.attrValues config.lvs
);
in
{
dev = ''
${lib.concatMapStrings (x: x.dev or "") (lib.attrValues lvMounts)}
vgchange -a n
@@ -147,36 +182,35 @@ in
_config = lib.mkOption {
internal = true;
readOnly = true;
default = [{ boot.initrd.kernelModules = kernelModules; }] ++
map
(lv: [
default =
[ { boot.initrd.kernelModules = kernelModules; } ]
++ map (lv: [
(lib.optional (lv.content != null) lv.content._config)
(lib.optional (lv.lvm_type != null) {
boot.initrd.kernelModules = [
boot.initrd.kernelModules =
[
(if lv.lvm_type == "mirror" then "dm-mirror" else "dm-raid")
]
++ lib.optional (lv.lvm_type == "raid0") "raid0"
++ lib.optional (lv.lvm_type == "raid1") "raid1"
# ++ lib.optional (lv.lvm_type == "raid10") "raid10"
++ lib.optional
(lv.lvm_type == "raid4" ||
lv.lvm_type == "raid5" ||
lv.lvm_type == "raid6") "raid456";
++ lib.optional (
lv.lvm_type == "raid4" || lv.lvm_type == "raid5" || lv.lvm_type == "raid6"
) "raid456";
})
])
(lib.attrValues config.lvs);
]) (lib.attrValues config.lvs);
description = "NixOS configuration";
};
_pkgs = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs: lib.flatten (map
(lv:
lib.optional (lv.content != null) (lv.content._pkgs pkgs)
)
(lib.attrValues config.lvs));
default =
pkgs:
lib.flatten (
map (lv: lib.optional (lv.content != null) (lv.content._pkgs pkgs)) (lib.attrValues config.lvs)
);
description = "Packages";
};
};

View File

@@ -1,4 +1,10 @@
{ config, options, lib, diskoLib, ... }:
{
config,
options,
lib,
diskoLib,
...
}:
{
options = {
name = lib.mkOption {
@@ -18,17 +24,32 @@
description = "mdadm level";
};
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";
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 {
internal = true;
readOnly = true;
type = diskoLib.jsonType;
default =
lib.optionalAttrs (config.content != null) (config.content._meta [ "mdadm" config.name ]);
default = lib.optionalAttrs (config.content != null) (
config.content._meta [
"mdadm"
config.name
]
);
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
@@ -54,15 +75,16 @@
};
_mount = diskoLib.mkMountOption {
inherit config options;
default =
lib.optionalAttrs (config.content != null) config.content._mount;
default = lib.optionalAttrs (config.content != null) config.content._mount;
# TODO we probably need to assemble the mdadm somehow
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = let
default =
let
content = lib.optionalAttrs (config.content != null) config.content._unmount;
in {
in
{
fs = content.fs;
dev = ''
${content.dev or ""}
@@ -75,24 +97,30 @@
_config = lib.mkOption {
internal = true;
readOnly = true;
default =
[
(if lib.versionAtLeast (lib.versions.majorMinor lib.version) "23.11" then {
default = [
(
if lib.versionAtLeast (lib.versions.majorMinor lib.version) "23.11" then
{
boot.swraid.enable = true;
} else {
}
else
{
boot.initrd.services.swraid.enable = true;
})
] ++
lib.optional (config.content != null) config.content._config;
}
)
] ++ lib.optional (config.content != null) config.content._config;
description = "NixOS configuration";
};
_pkgs = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs: [
default =
pkgs:
[
pkgs.parted # for partprobe
] ++ (lib.optionals (config.content != null) (config.content._pkgs pkgs));
]
++ (lib.optionals (config.content != null) (config.content._pkgs pkgs));
description = "Packages";
};
};

View File

@@ -1,4 +1,12 @@
{ config, options, lib, diskoLib, parent, device, ... }:
{
config,
options,
lib,
diskoLib,
parent,
device,
...
}:
{
options = {
type = lib.mkOption {

View File

@@ -1,4 +1,11 @@
{ lib, config, options, diskoLib, rootMountPoint, ... }:
{
lib,
config,
options,
diskoLib,
rootMountPoint,
...
}:
{
options = {
type = lib.mkOption {

View File

@@ -1,4 +1,12 @@
{ diskoLib, config, options, lib, parent, device, ... }:
{
diskoLib,
config,
options,
lib,
parent,
device,
...
}:
{
options = {
type = lib.mkOption {
@@ -14,7 +22,13 @@
discardPolicy = lib.mkOption {
default = null;
example = "once";
type = lib.types.nullOr (lib.types.enum [ "once" "pages" "both" ]);
type = lib.types.nullOr (
lib.types.enum [
"once"
"pages"
"both"
]
);
description = ''
Specify the discard policy for the swap device. If "once", then the
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
swapon ${
lib.optionalString (config.discardPolicy != null)
"--discard${lib.optionalString (config.discardPolicy != "both")
"=${config.discardPolicy}"
}"} ${
lib.optionalString (config.priority != null)
"--priority=${toString config.priority}"
} \
"--discard${lib.optionalString (config.discardPolicy != "both") "=${config.discardPolicy}"}"
} ${lib.optionalString (config.priority != null) "--priority=${toString config.priority}"} \
--options=${lib.concatStringsSep "," config.mountOptions} \
"${config.device}"
fi
@@ -108,8 +118,10 @@
_config = lib.mkOption {
internal = true;
readOnly = true;
default = [{
swapDevices = [{
default = [
{
swapDevices = [
{
device = config.device;
inherit (config) discardPolicy priority;
randomEncryption = {
@@ -118,16 +130,21 @@
allowDiscards = config.discardPolicy != null;
};
options = config.mountOptions;
}];
}
];
boot.resumeDevice = lib.mkIf config.resumeDevice config.device;
}];
}
];
description = "NixOS configuration";
};
_pkgs = lib.mkOption {
internal = true;
readOnly = true;
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";
};
};

View File

@@ -1,6 +1,16 @@
{ config, options, lib, diskoLib, parent, device, ... }:
{
options = lib.warn ''
config,
options,
lib,
diskoLib,
parent,
device,
...
}:
{
options =
lib.warn
''
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.
If you encounter errors similar to:
@@ -20,20 +30,46 @@
description = "Device to partition";
};
format = lib.mkOption {
type = lib.types.enum [ "gpt" "msdos" ];
type = lib.types.enum [
"gpt"
"msdos"
];
default = "gpt";
description = "The kind of partition table";
};
partitions = lib.mkOption {
type = lib.types.listOf (lib.types.submodule ({ name, ... }@partition: {
type = lib.types.listOf (
lib.types.submodule (
{ name, ... }@partition:
{
options = {
part-type = lib.mkOption {
type = lib.types.enum [ "primary" "logical" "extended" ];
type = lib.types.enum [
"primary"
"logical"
"extended"
];
default = "primary";
description = "Partition type";
};
fs-type = lib.mkOption {
type = lib.types.nullOr (lib.types.enum [ "btrfs" "ext2" "ext3" "ext4" "fat16" "fat32" "hfs" "hfs+" "linux-swap" "ntfs" "reiserfs" "udf" "xfs" ]);
type = lib.types.nullOr (
lib.types.enum [
"btrfs"
"ext2"
"ext3"
"ext4"
"fat16"
"fat32"
"hfs"
"hfs+"
"linux-swap"
"ntfs"
"reiserfs"
"udf"
"xfs"
]
);
default = null;
description = "Filesystem type to use";
};
@@ -61,7 +97,10 @@
default = false;
description = "Whether to make the partition bootable";
};
content = diskoLib.partitionType { parent = config; device = diskoLib.deviceNumbering config.device partition.config._index; };
content = diskoLib.partitionType {
parent = config;
device = diskoLib.deviceNumbering config.device partition.config._index;
};
_index = lib.mkOption {
type = lib.types.int;
internal = true;
@@ -69,7 +108,9 @@
defaultText = null;
};
};
}));
}
)
);
default = [ ];
description = "List of partitions to add to the partition table";
};
@@ -81,12 +122,13 @@
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);
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 {
@@ -94,7 +136,8 @@
default = ''
if ! blkid "${config.device}" >/dev/null; then
parted -s "${config.device}" -- mklabel ${config.format}
${lib.concatStrings (map (partition: ''
${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}
''}
@@ -115,22 +158,25 @@
partprobe "${config.device}"
udevadm trigger --subsystem-match=block
udevadm settle
'') config.partitions)}
'') config.partitions
)}
fi
${lib.concatStrings (map (partition: ''
${lib.concatStrings (
map (partition: ''
${lib.optionalString (partition.content != null) partition.content._create}
'') config.partitions)}
'') 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);
partMounts = lib.foldr lib.recursiveUpdate { } (
map (
partition: lib.optionalAttrs (partition.content != null) partition.content._mount
) config.partitions
);
in
{
dev = partMounts.dev or "";
@@ -141,11 +187,11 @@
inherit config options;
default =
let
partMounts = lib.foldr lib.recursiveUpdate { } (map
(partition:
lib.optionalAttrs (partition.content != null) partition.content._unmount
)
config.partitions);
partMounts = lib.foldr lib.recursiveUpdate { } (
map (
partition: lib.optionalAttrs (partition.content != null) partition.content._unmount
) config.partitions
);
in
{
dev = partMounts.dev or "";
@@ -155,24 +201,26 @@
_config = lib.mkOption {
internal = true;
readOnly = true;
default =
map
(partition:
lib.optional (partition.content != null) partition.content._config
)
config.partitions;
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);
default =
pkgs:
[
pkgs.parted
pkgs.systemdMinimal
]
++ lib.flatten (
map (
partition: lib.optional (partition.content != null) (partition.content._pkgs pkgs)
) config.partitions
);
description = "Packages";
};
};

View File

@@ -1,4 +1,12 @@
{ config, options, lib, diskoLib, parent, device, ... }:
{
config,
options,
lib,
diskoLib,
parent,
device,
...
}:
{
options = {
type = lib.mkOption {

View File

@@ -1,4 +1,12 @@
{ config, options, lib, diskoLib, rootMountPoint, parent, ... }:
{
config,
options,
lib,
diskoLib,
rootMountPoint,
parent,
...
}:
{
options = {
name = lib.mkOption {
@@ -58,8 +66,7 @@
default = true;
};
_create = diskoLib.mkCreateOption
{
_create = diskoLib.mkCreateOption {
inherit config options;
# -u prevents mounting newly created datasets, which is
# important to prevent accidental shadowing of mount points
@@ -67,7 +74,9 @@
# -p creates parents automatically
default =
let
createOptions = (lib.optionalAttrs (config.mountpoint != null) { mountpoint = config.mountpoint; }) // config.options;
createOptions =
(lib.optionalAttrs (config.mountpoint != null) { mountpoint = config.mountpoint; })
// config.options;
# All options defined as PROP_ONETIME or PROP_ONETIME_DEFAULT in https://github.com/openzfs/zfs/blob/master/module/zcommon/zfs_prop.c
onetimeProperties = [
"encryption"
@@ -83,16 +92,23 @@
in
''
if ! zfs get type ${config._name} >/dev/null 2>&1; then
${if config._createFilesystem then ''
${
if config._createFilesystem then
''
zfs create -up ${config._name} \
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") (createOptions))}
'' else ''
''
else
''
# don't create anything for root dataset of zpools
true
''}
''
}
${lib.optionalString (updateOptions != { }) ''
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)
} ${config._name}
''}
fi
'';
@@ -107,7 +123,10 @@
zfs load-key ${config._name}
fi
'';
}) // lib.optionalAttrs (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") {
})
// lib.optionalAttrs
(config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off")
{
fs.${config.mountpoint} = ''
if ! findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
mount ${config._name} "${rootMountPoint}${config.mountpoint}" \
@@ -125,7 +144,10 @@
default =
(lib.optionalAttrs (config.options.keylocation or "none" != "none") {
dev = "zfs unload-key ${config.name}";
}) // lib.optionalAttrs (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") {
})
// lib.optionalAttrs
(config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off")
{
fs.${config.mountpoint} = ''
if findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
umount "${rootMountPoint}${config.mountpoint}"
@@ -138,11 +160,14 @@
internal = true;
readOnly = true;
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}";
fsType = "zfs";
options = config.mountOptions ++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil";
options =
config.mountOptions
++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil";
};
};
description = "NixOS configuration";
@@ -157,4 +182,3 @@
};
};
}

View File

@@ -1,4 +1,11 @@
{ config, options, lib, diskoLib, parent, ... }:
{
config,
options,
lib,
diskoLib,
parent,
...
}:
{
options = {
name = lib.mkOption {
@@ -35,7 +42,10 @@
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 {
internal = true;
@@ -45,8 +55,7 @@
internal = true;
readOnly = true;
type = lib.types.functionTo diskoLib.jsonType;
default = dev:
lib.optionalAttrs (config.content != null) (config.content._meta dev);
default = dev: lib.optionalAttrs (config.content != null) (config.content._meta dev);
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
@@ -83,7 +92,9 @@
inherit config options;
default = {
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 ""}
'';
@@ -94,20 +105,21 @@
_config = lib.mkOption {
internal = true;
readOnly = true;
default =
lib.optional (config.content != null) config.content._config;
default = lib.optional (config.content != null) config.content._config;
description = "NixOS configuration";
};
_pkgs = lib.mkOption {
internal = true;
readOnly = true;
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = pkgs: [
default =
pkgs:
[
pkgs.util-linux
pkgs.parted # for partprobe
] ++ lib.optionals (config.content != null) (config.content._pkgs pkgs);
]
++ lib.optionals (config.content != null) (config.content._pkgs pkgs);
description = "Packages";
};
};
}

View File

@@ -1,4 +1,11 @@
{ config, options, lib, diskoLib, rootMountPoint, ... }:
{
config,
options,
lib,
diskoLib,
rootMountPoint,
...
}:
let
# TODO: Consider expanding to handle `file` and `draid` mode options.
modeOptions = [
@@ -63,13 +70,17 @@ in
};
};
};
type = (lib.types.oneOf [
type = (
lib.types.oneOf [
(lib.types.enum modeOptions)
(lib.types.attrsOf (diskoLib.subType {
(lib.types.attrsOf (
diskoLib.subType {
types = {
topology =
let
vdev = lib.types.submodule ({ ... }: {
vdev = lib.types.submodule (
{ ... }:
{
options = {
mode = lib.mkOption {
type = lib.types.enum modeOptions;
@@ -81,10 +92,12 @@ in
description = "Members of the vdev";
};
};
});
}
);
in
lib.types.submodule
({ ... }: {
lib.types.submodule (
{ ... }:
{
options = {
type = lib.mkOption {
type = lib.types.enum [ "topology" ];
@@ -104,7 +117,10 @@ in
example = [
{
mode = "mirror";
members = [ "x" "y" ];
members = [
"x"
"y"
];
}
{
members = [ "z" ];
@@ -119,7 +135,10 @@ in
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Hot_Spares
for details.
'';
example = [ "x" "y" ];
example = [
"x"
"y"
];
};
log = lib.mkOption {
type = lib.types.listOf vdev;
@@ -132,7 +151,10 @@ in
example = [
{
mode = "mirror";
members = [ "x" "y" ];
members = [
"x"
"y"
];
}
{
members = [ "z" ];
@@ -150,7 +172,10 @@ in
example = [
{
mode = "mirror";
members = [ "x" "y" ];
members = [
"x"
"y"
];
}
{
members = [ "z" ];
@@ -168,7 +193,10 @@ in
example = [
{
mode = "mirror";
members = [ "x" "y" ];
members = [
"x"
"y"
];
}
{
members = [ "z" ];
@@ -183,14 +211,20 @@ in
https://openzfs.github.io/openzfs-docs/man/master/7/zpoolconcepts.7.html#Cache_Devices
for details.
'';
example = [ "x" "y" ];
example = [
"x"
"y"
];
};
};
});
}
);
};
extraArgs.parent = config;
}))
]);
}
))
]
);
description = "Mode of the ZFS pool";
};
options = lib.mkOption {
@@ -214,18 +248,25 @@ in
description = "Options to pass to mount";
};
datasets = lib.mkOption {
type = lib.types.attrsOf (diskoLib.subType {
type = lib.types.attrsOf (
diskoLib.subType {
types = { inherit (diskoLib.types) zfs_fs zfs_volume; };
extraArgs.parent = config;
});
}
);
description = "List of datasets to define";
};
_meta = lib.mkOption {
internal = true;
readOnly = true;
type = diskoLib.jsonType;
default =
diskoLib.deepMergeMap (dataset: dataset._meta [ "zpool" config.name ]) (lib.attrValues config.datasets);
default = diskoLib.deepMergeMap (
dataset:
dataset._meta [
"zpool"
config.name
]
) (lib.attrValues config.datasets);
description = "Metadata";
};
_create = diskoLib.mkCreateOption {
@@ -234,14 +275,14 @@ in
let
formatOutput = type: mode: members: ''
entries+=("${type} ${mode}=${
lib.concatMapStringsSep " "
(d: if lib.strings.hasPrefix "/" d then d else "/dev/disk/by-partlabel/disk-${d}-zfs") members
lib.concatMapStringsSep " " (
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;
formatVdevList = type: vdevs: lib.concatMapStrings
(formatVdev type)
(builtins.sort (a: _: a.mode == "") vdevs);
formatVdevList =
type: vdevs: lib.concatMapStrings (formatVdev type) (builtins.sort (a: _: a.mode == "") vdevs);
hasTopology = !(builtins.isString config.mode);
mode = if hasTopology then "prescribed" else config.mode;
topology = lib.optionalAttrs hasTopology config.mode.topology;
@@ -281,18 +322,20 @@ in
topology="${mode} ''${zfs_devices[*]}"
else
entries=()
${lib.optionalString (hasTopology && topology.vdev != null)
(formatVdevList "" topology.vdev)}
${lib.optionalString (hasTopology && topology.spare != [])
(formatOutput "spare" "" topology.spare)}
${lib.optionalString (hasTopology && topology.log != [])
(formatVdevList "log" topology.log)}
${lib.optionalString (hasTopology && topology.dedup != [])
(formatVdevList "dedup" topology.dedup)}
${lib.optionalString (hasTopology && topology.special != null && topology.special != [])
(formatVdevList "special" (lib.lists.toList topology.special))}
${lib.optionalString (hasTopology && topology.cache != [])
(formatOutput "cache" "" topology.cache)}
${lib.optionalString (hasTopology && topology.vdev != null) (formatVdevList "" topology.vdev)}
${lib.optionalString (hasTopology && topology.spare != [ ]) (
formatOutput "spare" "" topology.spare
)}
${lib.optionalString (hasTopology && topology.log != [ ]) (formatVdevList "log" topology.log)}
${lib.optionalString (hasTopology && topology.dedup != [ ]) (
formatVdevList "dedup" topology.dedup
)}
${lib.optionalString (hasTopology && topology.special != null && topology.special != [ ]) (
formatVdevList "special" (lib.lists.toList topology.special)
)}
${lib.optionalString (hasTopology && topology.cache != [ ]) (
formatOutput "cache" "" topology.cache
)}
all_devices=()
last_type=
for line in "''${entries[@]}"; do
@@ -337,7 +380,9 @@ in
inherit config options;
default =
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
{
dev = ''
@@ -372,7 +417,13 @@ in
internal = true;
readOnly = true;
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";
};
};

View File

@@ -1,4 +1,11 @@
{ config, lib, pkgs, extendModules, diskoLib, ... }:
{
config,
lib,
pkgs,
extendModules,
diskoLib,
...
}:
let
cfg = config.disko;
@@ -107,7 +114,10 @@ in
};
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";
default = "raw";
};
@@ -239,14 +249,28 @@ in
eval-config = import (pkgs.path + "/nixos/lib/eval-config.nix");
};
system.build = (cfg.devices._scripts { inherit pkgs; checked = cfg.checkScripts; }) // (
system.build =
(cfg.devices._scripts {
inherit pkgs;
checked = cfg.checkScripts;
})
// (
let
throwIfNoDisksDetected = _: v: if cfg.devices.disk == { } then throw "No disks defined, did you forget to import your disko config?" else v;
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;
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 {
inherit extendModules pkgs;
@@ -266,11 +290,8 @@ in
# 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
fileSystems = lib.mkIf
cfg.enableConfig cfg.devices._config.fileSystems or { };
boot = lib.mkIf
cfg.enableConfig cfg.devices._config.boot or { };
swapDevices = lib.mkIf
cfg.enableConfig cfg.devices._config.swapDevices or [ ];
fileSystems = lib.mkIf cfg.enableConfig cfg.devices._config.fileSystems or { };
boot = lib.mkIf cfg.enableConfig cfg.devices._config.boot or { };
swapDevices = lib.mkIf cfg.enableConfig cfg.devices._config.swapDevices or [ ];
};
}

View File

@@ -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
self = stdenvNoCC.mkDerivation (finalAttrs: {
@@ -16,7 +26,13 @@ let
chmod 755 "$out/bin/$i"
wrapProgram "$out/bin/$i" \
--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}"
done
'';

View File

@@ -1,3 +1,5 @@
#! /usr/bin/env bash
# Don't run directly! Instead, use
# nix run .#create-release

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;
@@ -17,4 +18,3 @@ diskoLib.testLib.makeDiskoTest {
machine.succeed("test -e /partition-root/swapfile1");
'';
}

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;
@@ -26,7 +27,10 @@ diskoLib.testLib.makeDiskoTest {
];
};
extraInstallerConfig = {
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
boot.kernelModules = [
"dm-raid"
"dm-mirror"
];
imports = [
../module.nix
];

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;
@@ -24,6 +25,9 @@ diskoLib.testLib.makeDiskoTest {
machine.succeed("test -e /ext4_on_lvm/file-from-postMountHook");
'';
extraInstallerConfig = {
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
boot.kernelModules = [
"dm-raid"
"dm-mirror"
];
};
}

View File

@@ -1,20 +1,28 @@
{ makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>
, eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>
, pkgs ? import <nixpkgs> { }
{
makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>,
eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>,
pkgs ? import <nixpkgs> { },
}:
let
lib = pkgs.lib;
diskoLib = import ../lib { inherit lib makeTest eval-config; };
allTestFilenames =
builtins.map (lib.removeSuffix ".nix") (
builtins.filter
(x: lib.hasSuffix ".nix" x && x != "default.nix")
(lib.attrNames (builtins.readDir ./.))
allTestFilenames = builtins.map (lib.removeSuffix ".nix") (
builtins.filter (x: lib.hasSuffix ".nix" x && x != "default.nix") (
lib.attrNames (builtins.readDir ./.)
)
);
incompatibleTests = lib.optionals pkgs.stdenv.buildPlatform.isRiscV64 [ "zfs" "zfs-over-legacy" "cli" "module" "complex" ];
incompatibleTests = lib.optionals pkgs.stdenv.buildPlatform.isRiscV64 [
"zfs"
"zfs-over-legacy"
"cli"
"module"
"complex"
];
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
allTests

View File

@@ -1,4 +1,10 @@
{ lib, pkgs, modulesPath, ... }: {
{
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/testing/test-instrumentation.nix")
(modulesPath + "/profiles/qemu-guest.nix")
@@ -13,11 +19,15 @@
hashed-mirrors = null;
connect-timeout = 3;
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
experimental-features = [ "nix-command" "flakes" ];
experimental-features = [
"nix-command"
"flakes"
];
};
services.openssh.enable = true;
boot.kernelParams = [ "console=tty0" ] ++
(lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200") ++
(lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200") ++
[ "console=ttyS0,115200" ];
boot.kernelParams =
[ "console=tty0" ]
++ (lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200")
++ (lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200")
++ [ "console=ttyS0,115200" ];
}

View File

@@ -1,4 +1,8 @@
{ pkgs ? import <nixpkgs> { }, self, diskoVersion }:
{
pkgs ? import <nixpkgs> { },
self,
diskoVersion,
}:
let
disko = pkgs.callPackage ../../package.nix { inherit diskoVersion; };

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;
@@ -9,7 +10,11 @@ diskoLib.testLib.makeDiskoTest {
machine.succeed("mountpoint /home");
'';
extraInstallerConfig = {
boot.kernelModules = [ "dm-raid" "raid0" "dm-mirror" ];
boot.kernelModules = [
"dm-raid"
"raid0"
"dm-mirror"
];
};
extraSystemConfig = {
# sadly systemd-boot fails to install to a raid /boot device

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,13 +1,17 @@
{ pkgs ? import <nixpkgs> { }
, ...
{
pkgs ? import <nixpkgs> { },
...
}:
(pkgs.nixos [
../module.nix
../example/simple-efi.nix
({ config, ... }: {
(
{ config, ... }:
{
documentation.enable = false;
system.stateVersion = config.system.nixos.version;
disko.checkScripts = true;
})
}
)
]).config.system.build.diskoImagesScript

View File

@@ -1,14 +1,18 @@
{ pkgs ? import <nixpkgs> { }
, ...
{
pkgs ? import <nixpkgs> { },
...
}:
(pkgs.nixos [
../module.nix
../example/simple-efi.nix
({ config, ... }: {
(
{ config, ... }:
{
documentation.enable = false;
system.stateVersion = config.system.nixos.version;
disko.memSize = 2048;
disko.checkScripts = true;
})
}
)
]).config.system.build.diskoImages

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;
@@ -21,6 +22,9 @@ diskoLib.testLib.makeDiskoTest {
machine.succeed("mountpoint /ext4_on_lvm");
'';
extraInstallerConfig = {
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
boot.kernelModules = [
"dm-raid"
"dm-mirror"
];
};
}

View File

@@ -1,6 +1,7 @@
# 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 {
inherit pkgs;

View File

@@ -1,6 +1,7 @@
# 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 {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,4 +1,7 @@
{ pkgs ? import <nixpkgs> { }, ... }:
{
pkgs ? import <nixpkgs> { },
...
}:
(pkgs.nixos [
../example/stand-alone/configuration.nix
{ documentation.enable = false; }

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,13 +1,13 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;
name = "zfs-encrypted-root";
extraInstallerConfig.networking.hostId = "8425e349";
extraSystemConfig.networking.hostId = "8425e349";
disko-config =
pkgs.lib.recursiveUpdate (import ../example/zfs-encrypted-root.nix) {
disko-config = pkgs.lib.recursiveUpdate (import ../example/zfs-encrypted-root.nix) {
disko.devices.zpool.zroot.datasets.root.options.keylocation = "file:///tmp/secret.key";
};
extraTestScript = ''
@@ -15,4 +15,3 @@ diskoLib.testLib.makeDiskoTest {
machine.succeed("mountpoint /nix");
'';
}

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;
@@ -12,4 +13,3 @@ diskoLib.testLib.makeDiskoTest {
machine.succeed("mountpoint /zfs_fs");
'';
}

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1,5 +1,6 @@
{ pkgs ? import <nixpkgs> { }
, diskoLib ? pkgs.callPackage ../lib { }
{
pkgs ? import <nixpkgs> { },
diskoLib ? pkgs.callPackage ../lib { },
}:
diskoLib.testLib.makeDiskoTest {
inherit pkgs;

View File

@@ -1 +1,4 @@
{ version = "1.10.0"; released = false; }
{
version = "1.10.0";
released = false;
}