Merge pull request #186314 from ck3d/unit-add-map-control

nixos: Add option to influence override strategies in systemd units

+24 -11
nixos/lib/systemd-lib.nix
···
done
done
-
# Symlink all units defined by systemd.units. If these are also
-
# provided by systemd or systemd.packages, then add them as
+
# Symlink units defined by systemd.units where override strategy
+
# shall be automatically detected. If these are also provided by
+
# systemd or systemd.packages, then add them as
# <unit-name>.d/overrides.conf, which makes them extend the
# upstream unit.
-
for i in ${toString (mapAttrsToList (n: v: v.unit) units)}; do
+
for i in ${toString (mapAttrsToList
+
(n: v: v.unit)
+
(lib.filterAttrs (n: v: (attrByPath [ "overrideStrategy" ] "asDropinIfExists" v) == "asDropinIfExists") units))}; do
fn=$(basename $i/*)
if [ -e $out/$fn ]; then
if [ "$(readlink -f $i/$fn)" = /dev/null ]; then
···
else
ln -fs $i/$fn $out/
fi
+
done
+
+
# Symlink units defined by systemd.units which shall be
+
# treated as drop-in file.
+
for i in ${toString (mapAttrsToList
+
(n: v: v.unit)
+
(lib.filterAttrs (n: v: v ? overrideStrategy && v.overrideStrategy == "asDropin") units))}; do
+
fn=$(basename $i/*)
+
mkdir -p $out/$fn.d
+
ln -s $i/$fn $out/$fn.d/overrides.conf
done
# Create service aliases from aliases option.
···
'';
targetToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text =
''
[Unit]
···
};
serviceToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text = commonUnitText def +
''
[Service]
···
};
socketToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text = commonUnitText def +
''
[Socket]
···
};
timerToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text = commonUnitText def +
''
[Timer]
···
};
pathToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text = commonUnitText def +
''
[Path]
···
};
mountToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text = commonUnitText def +
''
[Mount]
···
};
automountToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text = commonUnitText def +
''
[Automount]
···
};
sliceToUnit = name: def:
-
{ inherit (def) aliases wantedBy requiredBy enable;
+
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
text = commonUnitText def +
''
[Slice]
+16
nixos/lib/systemd-unit-options.nix
···
'';
};
+
overrideStrategy = mkOption {
+
default = "asDropinIfExists";
+
type = types.enum [ "asDropinIfExists" "asDropin" ];
+
description = lib.mdDoc ''
+
Defines how unit configuration is provided for systemd:
+
+
`asDropinIfExists` creates a unit file when no unit file is provided by the package
+
otherwise a drop-in file name `overrides.conf`.
+
+
`asDropin` creates a drop-in file named `overrides.conf`.
+
Mainly needed to define instances for systemd template units (e.g. `systemd-nspawn@mycontainer.service`).
+
+
See also systemd.unit(1).
+
'';
+
};
+
requiredBy = mkOption {
default = [];
type = types.listOf unitNameType;
+11
nixos/tests/systemd-machinectl.nix
···
# not needed, but we want to test the nspawn file generation
systemd.nspawn.${containerName} = { };
+
+
systemd.services."systemd-nspawn@${containerName}" = {
+
serviceConfig.Environment = [
+
# Disable tmpfs for /tmp
+
"SYSTEMD_NSPAWN_TMPFS_TMP=0"
+
];
+
overrideStrategy = "asDropin";
+
};
};
testScript = ''
···
# Test machinectl stop
machine.succeed("machinectl stop ${containerName}");
machine.wait_until_succeeds("test $(systemctl is-active systemd-nspawn@${containerName}) = inactive");
+
+
# Test tmpfs for /tmp
+
machine.fail("mountpoint /tmp");
# Show to to delete the container
machine.succeed("chattr -i ${containerRoot}/var/empty");