nixos/repart-image: refactor to use mkDerivation
As a follow-up to https://github.com/NixOS/nixpkgs/pull/294096 this should further improve the flexibility around building OS images with systemd-repart: * Previously the attribute set `compression` needed to be fully populated, including `algorithm` and `level` because `compression.enable` was evaluated by bash, after being interpolated as strings into the `buildCommand`. Now it's sufficient to pass `compression.enable = false` to the builder, e.g. in `overrideAttrs`, to disable the compression. * Using mkDerivation allows for much more customization than the previously used `runCommand`, making use of phases and pre/post hooks. This is especially helpful for building multiple images from the same system configuration, e.g. to build an image `Y` based on a partially built raw image `X`, by injecting a UKI that depends on `X` into a defered ESP. * Before this change it was non-trivial to conduct further manipulations on the amended repart definitions. Now, the definitions that systemd-repart uses to build the image can be easily manipulated in `postPatch` or `preBuild`. Aside from this, the build is now executed in the build directory, rather than `$out`. This allows references to relative paths in the build environment to be used, especially for `--definitions`, which previously required an absolute path.
This commit is contained in:
parent
1357b820aa
commit
d7ef2defda
|
@ -2,8 +2,8 @@
|
||||||
# NixOS module that can be imported.
|
# NixOS module that can be imported.
|
||||||
|
|
||||||
{ lib
|
{ lib
|
||||||
|
, stdenvNoCC
|
||||||
, runCommand
|
, runCommand
|
||||||
, runCommandLocal
|
|
||||||
, python3
|
, python3
|
||||||
, black
|
, black
|
||||||
, ruff
|
, ruff
|
||||||
|
@ -26,15 +26,18 @@
|
||||||
, xz
|
, xz
|
||||||
|
|
||||||
# arguments
|
# arguments
|
||||||
|
, name
|
||||||
|
, version
|
||||||
, imageFileBasename
|
, imageFileBasename
|
||||||
, compression
|
, compression
|
||||||
, fileSystems
|
, fileSystems
|
||||||
, partitions
|
, partitionsJSON
|
||||||
, split
|
, split
|
||||||
, seed
|
, seed
|
||||||
, definitionsDirectory
|
, definitionsDirectory
|
||||||
, sectorSize
|
, sectorSize
|
||||||
, mkfsEnv ? {}
|
, mkfsEnv ? {}
|
||||||
|
, createEmpty ? true
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
@ -52,11 +55,6 @@ let
|
||||||
mypy --strict $out
|
mypy --strict $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
amendedRepartDefinitions = runCommandLocal "amended-repart.d" {} ''
|
|
||||||
definitions=$(${amendRepartDefinitions} ${partitions} ${definitionsDirectory})
|
|
||||||
cp -r $definitions $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
fileSystemToolMapping = {
|
fileSystemToolMapping = {
|
||||||
"vfat" = [ dosfstools mtools ];
|
"vfat" = [ dosfstools mtools ];
|
||||||
"ext4" = [ e2fsprogs.bin ];
|
"ext4" = [ e2fsprogs.bin ];
|
||||||
|
@ -78,53 +76,88 @@ let
|
||||||
"xz" = "xz --keep --verbose --threads=0 -${toString compression.level}";
|
"xz" = "xz --keep --verbose --threads=0 -${toString compression.level}";
|
||||||
}."${compression.algorithm}";
|
}."${compression.algorithm}";
|
||||||
in
|
in
|
||||||
|
stdenvNoCC.mkDerivation (finalAttrs:
|
||||||
runCommand imageFileBasename
|
(if (version != null)
|
||||||
{
|
then { pname = name; inherit version; }
|
||||||
|
else { inherit name; }
|
||||||
|
) // {
|
||||||
__structuredAttrs = true;
|
__structuredAttrs = true;
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
systemd
|
systemd
|
||||||
fakeroot
|
fakeroot
|
||||||
util-linux
|
util-linux
|
||||||
|
] ++ lib.optionals (compression.enable) [
|
||||||
compressionPkg
|
compressionPkg
|
||||||
] ++ fileSystemTools;
|
] ++ fileSystemTools;
|
||||||
|
|
||||||
env = mkfsEnv;
|
env = mkfsEnv;
|
||||||
|
|
||||||
|
inherit partitionsJSON definitionsDirectory;
|
||||||
|
|
||||||
|
# relative path to the repart definitions that are read by systemd-repart
|
||||||
|
finalRepartDefinitions = "repart.d";
|
||||||
|
|
||||||
systemdRepartFlags = [
|
systemdRepartFlags = [
|
||||||
"--dry-run=no"
|
"--dry-run=no"
|
||||||
"--empty=create"
|
|
||||||
"--size=auto"
|
"--size=auto"
|
||||||
"--seed=${seed}"
|
"--seed=${seed}"
|
||||||
"--definitions=${amendedRepartDefinitions}"
|
"--definitions=${finalAttrs.finalRepartDefinitions}"
|
||||||
"--split=${lib.boolToString split}"
|
"--split=${lib.boolToString split}"
|
||||||
"--json=pretty"
|
"--json=pretty"
|
||||||
|
] ++ lib.optionals createEmpty [
|
||||||
|
"--empty=create"
|
||||||
] ++ lib.optionals (sectorSize != null) [
|
] ++ lib.optionals (sectorSize != null) [
|
||||||
"--sector-size=${toString sectorSize}"
|
"--sector-size=${toString sectorSize}"
|
||||||
];
|
];
|
||||||
|
|
||||||
passthru = {
|
dontUnpack = true;
|
||||||
inherit amendRepartDefinitions amendedRepartDefinitions;
|
dontConfigure = true;
|
||||||
};
|
doCheck = false;
|
||||||
} ''
|
|
||||||
mkdir -p $out
|
|
||||||
cd $out
|
|
||||||
|
|
||||||
echo "Building image with systemd-repart..."
|
patchPhase = ''
|
||||||
unshare --map-root-user fakeroot systemd-repart \
|
runHook prePatch
|
||||||
''${systemdRepartFlags[@]} \
|
|
||||||
${imageFileBasename}.raw \
|
|
||||||
| tee repart-output.json
|
|
||||||
|
|
||||||
|
amendedRepartDefinitionsDir=$(${amendRepartDefinitions} $partitionsJSON $definitionsDirectory)
|
||||||
|
ln -vs $amendedRepartDefinitionsDir $finalRepartDefinitions
|
||||||
|
|
||||||
|
runHook postPatch
|
||||||
|
'';
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
echo "Building image with systemd-repart..."
|
||||||
|
unshare --map-root-user fakeroot systemd-repart \
|
||||||
|
''${systemdRepartFlags[@]} \
|
||||||
|
${imageFileBasename}.raw \
|
||||||
|
| tee repart-output.json
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p $out
|
||||||
|
''
|
||||||
# Compression is implemented in the same derivation as opposed to in a
|
# Compression is implemented in the same derivation as opposed to in a
|
||||||
# separate derivation to allow users to save disk space. Disk images are
|
# separate derivation to allow users to save disk space. Disk images are
|
||||||
# already very space intensive so we want to allow users to mitigate this.
|
# already very space intensive so we want to allow users to mitigate this.
|
||||||
if ${lib.boolToString compression.enable}; then
|
+ lib.optionalString compression.enable
|
||||||
|
''
|
||||||
for f in ${imageFileBasename}*; do
|
for f in ${imageFileBasename}*; do
|
||||||
echo "Compressing $f with ${compression.algorithm}..."
|
echo "Compressing $f with ${compression.algorithm}..."
|
||||||
# Keep the original file when compressing and only delete it afterwards
|
# Keep the original file when compressing and only delete it afterwards
|
||||||
${compressionCommand} $f && rm $f
|
${compressionCommand} $f && rm $f
|
||||||
done
|
done
|
||||||
fi
|
'' + ''
|
||||||
''
|
mv -v repart-output.json ${imageFileBasename}* $out
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit amendRepartDefinitions;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
|
@ -266,14 +266,14 @@ in
|
||||||
format
|
format
|
||||||
(lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) finalPartitions);
|
(lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) finalPartitions);
|
||||||
|
|
||||||
partitions = pkgs.writeText "partitions.json" (builtins.toJSON finalPartitions);
|
partitionsJSON = pkgs.writeText "partitions.json" (builtins.toJSON finalPartitions);
|
||||||
|
|
||||||
mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions;
|
mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions;
|
||||||
in
|
in
|
||||||
pkgs.callPackage ./repart-image.nix {
|
pkgs.callPackage ./repart-image.nix {
|
||||||
systemd = cfg.package;
|
systemd = cfg.package;
|
||||||
inherit (cfg) imageFileBasename compression split seed sectorSize;
|
inherit (cfg) name version imageFileBasename compression split seed sectorSize;
|
||||||
inherit fileSystems definitionsDirectory partitions mkfsEnv;
|
inherit fileSystems definitionsDirectory partitionsJSON mkfsEnv;
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = with lib.maintainers; [ nikstur ];
|
meta.maintainers = with lib.maintainers; [ nikstur ];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user