diff --git a/pkgs/build-support/setup-systemd-units.nix b/pkgs/build-support/setup-systemd-units.nix new file mode 100644 index 00000000000..4fa2f42c39d --- /dev/null +++ b/pkgs/build-support/setup-systemd-units.nix @@ -0,0 +1,83 @@ +# | Build a script to install and start a set of systemd units on any +# systemd-based system. +# +# Creates a symlink at /etc/systemd-static/${namespace} for slightly +# improved atomicity. +{ writeScriptBin +, bash +, coreutils +, systemd +, runCommand +, lib +}: + { units # : AttrSet String (Either Path { path : Path, wanted-by : [ String ] }) + # ^ A set whose names are unit names and values are + # either paths to the corresponding unit files or a set + # containing the path and the list of units this unit + # should be wanted-by (none by default). + # + # The names should include the unit suffix + # (e.g. ".service") + , namespace # : String + # The namespace for the unit files, to allow for + # multiple independent unit sets managed by + # `setupSystemdUnits`. + }: + let static = runCommand "systemd-static" {} + '' + mkdir -p $out + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (nm: file: + "ln -sv ${file.path or file} $out/${nm}" + ) units)} + ''; + add-unit-snippet = name: file: + '' + oldUnit=$(readlink -f "$unitDir/${name}" || echo "$unitDir/${name}") + if [ -f "$oldUnit" -a "$oldUnit" != "${file.path or file}" ]; then + unitsToStop+=("${name}") + fi + ln -sf "/etc/systemd-static/${namespace}/${name}" \ + "$unitDir/.${name}.tmp" + mv -T "$unitDir/.${name}.tmp" "$unitDir/${name}" + ${lib.concatStringsSep "\n" (map (unit: + '' + mkdir -p "$unitDir/${unit}.wants" + ln -sf "../${name}" \ + "$unitDir/${unit}.wants/.${name}.tmp" + mv -T "$unitDir/${unit}.wants/.${name}.tmp" \ + "$unitDir/${unit}.wants/${name}" + '' + ) file.wanted-by or [])} + unitsToStart+=("${name}") + ''; + in + writeScriptBin "setup-systemd-units" + '' + #!${bash}/bin/bash -e + export PATH=${coreutils}/bin:${systemd}/bin + + unitDir=/etc/systemd/system + if [ ! -w "$unitDir" ]; then + unitDir=/etc/systemd-mutable/system + mkdir -p "$unitDir" + fi + declare -a unitsToStop unitsToStart + + oldStatic=$(readlink -f /etc/systemd-static/${namespace} || true) + if [ "$oldStatic" != "${static}" ]; then + ${lib.concatStringsSep "\n" + (lib.mapAttrsToList add-unit-snippet units)} + if [ ''${#unitsToStop[@]} -ne 0 ]; then + echo "Stopping unit(s) ''${unitsToStop[@]}" >&2 + systemctl stop "''${unitsToStop[@]}" + fi + mkdir -p /etc/systemd-static + ln -sfT ${static} /etc/systemd-static/.${namespace}.tmp + mv -T /etc/systemd-static/.${namespace}.tmp /etc/systemd-static/${namespace} + systemctl daemon-reload + echo "Starting unit(s) ''${unitsToStart[@]}" >&2 + systemctl start "''${unitsToStart[@]}" + else + echo "Units unchanged, doing nothing" >&2 + fi + '' diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 923676aa154..552f9d4158e 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -281,6 +281,8 @@ with pkgs; pathsFromGraph = ../build-support/kernel/paths-from-graph.pl; + setupSystemdUnits = callPackage ../build-support/setup-systemd-units.nix { }; + singularity-tools = callPackage ../build-support/singularity-tools { }; srcOnly = args: callPackage ../build-support/src-only args;