diff options
Diffstat (limited to 'modules/networkd/systemd-lib.nix')
-rw-r--r-- | modules/networkd/systemd-lib.nix | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/modules/networkd/systemd-lib.nix b/modules/networkd/systemd-lib.nix deleted file mode 100644 index c5b5b7cb..00000000 --- a/modules/networkd/systemd-lib.nix +++ /dev/null | |||
@@ -1,241 +0,0 @@ | |||
1 | { config, lib, pkgs }: | ||
2 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
6 | cfg = config.systemd; | ||
7 | lndir = "${pkgs.xorg.lndir}/bin/lndir"; | ||
8 | in rec { | ||
9 | |||
10 | shellEscape = s: (replaceChars [ "\\" ] [ "\\\\" ] s); | ||
11 | |||
12 | mkPathSafeName = lib.replaceChars ["@" ":" "\\" "[" "]"] ["-" "-" "-" "" ""]; | ||
13 | |||
14 | makeUnit = name: unit: | ||
15 | if unit.enable then | ||
16 | pkgs.runCommand "unit-${mkPathSafeName name}" | ||
17 | { preferLocalBuild = true; | ||
18 | allowSubstitutes = false; | ||
19 | inherit (unit) text; | ||
20 | } | ||
21 | '' | ||
22 | mkdir -p $out | ||
23 | echo -n "$text" > $out/${shellEscape name} | ||
24 | '' | ||
25 | else | ||
26 | pkgs.runCommand "unit-${mkPathSafeName name}-disabled" | ||
27 | { preferLocalBuild = true; | ||
28 | allowSubstitutes = false; | ||
29 | } | ||
30 | '' | ||
31 | mkdir -p $out | ||
32 | ln -s /dev/null $out/${shellEscape name} | ||
33 | ''; | ||
34 | |||
35 | boolValues = [true false "yes" "no"]; | ||
36 | |||
37 | digits = map toString (range 0 9); | ||
38 | |||
39 | isByteFormat = s: | ||
40 | let | ||
41 | l = reverseList (stringToCharacters s); | ||
42 | suffix = head l; | ||
43 | nums = tail l; | ||
44 | in elem suffix (["K" "M" "G" "T"] ++ digits) | ||
45 | && all (num: elem num digits) nums; | ||
46 | |||
47 | assertByteFormat = name: group: attr: | ||
48 | optional (attr ? ${name} && ! isByteFormat attr.${name}) | ||
49 | "Systemd ${group} field `${name}' must be in byte format [0-9]+[KMGT]."; | ||
50 | |||
51 | hexChars = stringToCharacters "0123456789abcdefABCDEF"; | ||
52 | |||
53 | isMacAddress = s: stringLength s == 17 | ||
54 | && flip all (splitString ":" s) (bytes: | ||
55 | all (byte: elem byte hexChars) (stringToCharacters bytes) | ||
56 | ); | ||
57 | |||
58 | assertMacAddress = name: group: attr: | ||
59 | optional (attr ? ${name} && ! isMacAddress attr.${name}) | ||
60 | "Systemd ${group} field `${name}' must be a valid mac address."; | ||
61 | |||
62 | isPort = i: i >= 0 && i <= 65535; | ||
63 | |||
64 | assertPort = name: group: attr: | ||
65 | optional (attr ? ${name} && ! isPort attr.${name}) | ||
66 | "Error on the systemd ${group} field `${name}': ${attr.name} is not a valid port number."; | ||
67 | |||
68 | assertValueOneOf = name: values: group: attr: | ||
69 | optional (attr ? ${name} && !elem attr.${name} values) | ||
70 | "Systemd ${group} field `${name}' cannot have value `${toString attr.${name}}'."; | ||
71 | |||
72 | assertHasField = name: group: attr: | ||
73 | optional (!(attr ? ${name})) | ||
74 | "Systemd ${group} field `${name}' must exist."; | ||
75 | |||
76 | assertRange = name: min: max: group: attr: | ||
77 | optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name})) | ||
78 | "Systemd ${group} field `${name}' is outside the range [${toString min},${toString max}]"; | ||
79 | |||
80 | assertMinimum = name: min: group: attr: | ||
81 | optional (attr ? ${name} && attr.${name} < min) | ||
82 | "Systemd ${group} field `${name}' must be greater than or equal to ${toString min}"; | ||
83 | |||
84 | assertOnlyFields = fields: group: attr: | ||
85 | let badFields = filter (name: ! elem name fields) (attrNames attr); in | ||
86 | optional (badFields != [ ]) | ||
87 | "Systemd ${group} has extra fields [${concatStringsSep " " badFields}]."; | ||
88 | |||
89 | assertInt = name: group: attr: | ||
90 | optional (attr ? ${name} && !isInt attr.${name}) | ||
91 | "Systemd ${group} field `${name}' is not an integer"; | ||
92 | |||
93 | assertMaxLength = name: max: group: attr: | ||
94 | optional (attr ? ${name} && stringLength attr.${name} > max) | ||
95 | "Systemd ${group} field `${name}' is too long (max of ${max})"; | ||
96 | |||
97 | checkUnitConfig = group: checks: attrs: let | ||
98 | # We're applied at the top-level type (attrsOf unitOption), so the actual | ||
99 | # unit options might contain attributes from mkOverride and mkIf that we need to | ||
100 | # convert into single values before checking them. | ||
101 | defs = mapAttrs (const (v: | ||
102 | if v._type or "" == "override" then v.content | ||
103 | else if v._type or "" == "if" then v.content | ||
104 | else v | ||
105 | )) attrs; | ||
106 | errors = concatMap (c: c group defs) checks; | ||
107 | in if errors == [] then true | ||
108 | else builtins.trace (concatStringsSep "\n" errors) false; | ||
109 | |||
110 | toOption = x: | ||
111 | if x == true then "true" | ||
112 | else if x == false then "false" | ||
113 | else toString x; | ||
114 | |||
115 | attrsToSection = as: | ||
116 | concatStrings (concatLists (mapAttrsToList (name: value: | ||
117 | map (x: '' | ||
118 | ${name}=${toOption x} | ||
119 | '') | ||
120 | (if isList value then value else [value])) | ||
121 | as)); | ||
122 | |||
123 | generateUnits = generateUnits' true; | ||
124 | |||
125 | generateUnits' = allowCollisions: type: units: upstreamUnits: upstreamWants: | ||
126 | pkgs.runCommand "${type}-units" | ||
127 | { preferLocalBuild = true; | ||
128 | allowSubstitutes = false; | ||
129 | } '' | ||
130 | mkdir -p $out | ||
131 | |||
132 | # Copy the upstream systemd units we're interested in. | ||
133 | for i in ${toString upstreamUnits}; do | ||
134 | fn=${cfg.package}/example/systemd/${type}/$i | ||
135 | if ! [ -e $fn ]; then echo "missing $fn"; false; fi | ||
136 | if [ -L $fn ]; then | ||
137 | target="$(readlink "$fn")" | ||
138 | if [ ''${target:0:3} = ../ ]; then | ||
139 | ln -s "$(readlink -f "$fn")" $out/ | ||
140 | else | ||
141 | cp -pd $fn $out/ | ||
142 | fi | ||
143 | else | ||
144 | ln -s $fn $out/ | ||
145 | fi | ||
146 | done | ||
147 | |||
148 | # Copy .wants links, but only those that point to units that | ||
149 | # we're interested in. | ||
150 | for i in ${toString upstreamWants}; do | ||
151 | fn=${cfg.package}/example/systemd/${type}/$i | ||
152 | if ! [ -e $fn ]; then echo "missing $fn"; false; fi | ||
153 | x=$out/$(basename $fn) | ||
154 | mkdir $x | ||
155 | for i in $fn/*; do | ||
156 | y=$x/$(basename $i) | ||
157 | cp -pd $i $y | ||
158 | if ! [ -e $y ]; then rm $y; fi | ||
159 | done | ||
160 | done | ||
161 | |||
162 | # Symlink all units provided listed in systemd.packages. | ||
163 | packages="${toString cfg.packages}" | ||
164 | |||
165 | # Filter duplicate directories | ||
166 | declare -A unique_packages | ||
167 | for k in $packages ; do unique_packages[$k]=1 ; done | ||
168 | |||
169 | for i in ''${!unique_packages[@]}; do | ||
170 | for fn in $i/etc/systemd/${type}/* $i/lib/systemd/${type}/*; do | ||
171 | if ! [[ "$fn" =~ .wants$ ]]; then | ||
172 | if [[ -d "$fn" ]]; then | ||
173 | targetDir="$out/$(basename "$fn")" | ||
174 | mkdir -p "$targetDir" | ||
175 | ${lndir} "$fn" "$targetDir" | ||
176 | else | ||
177 | ln -s $fn $out/ | ||
178 | fi | ||
179 | fi | ||
180 | done | ||
181 | done | ||
182 | |||
183 | # Symlink all units defined by systemd.units. If these are also | ||
184 | # provided by systemd or systemd.packages, then add them as | ||
185 | # <unit-name>.d/overrides.conf, which makes them extend the | ||
186 | # upstream unit. | ||
187 | for i in ${toString (mapAttrsToList (n: v: v.unit) units)}; do | ||
188 | fn=$(basename $i/*) | ||
189 | if [ -e $out/$fn ]; then | ||
190 | if [ "$(readlink -f $i/$fn)" = /dev/null ]; then | ||
191 | ln -sfn /dev/null $out/$fn | ||
192 | else | ||
193 | ${if allowCollisions then '' | ||
194 | mkdir -p $out/$fn.d | ||
195 | ln -s $i/$fn $out/$fn.d/overrides.conf | ||
196 | '' else '' | ||
197 | echo "Found multiple derivations configuring $fn!" | ||
198 | exit 1 | ||
199 | ''} | ||
200 | fi | ||
201 | else | ||
202 | ln -fs $i/$fn $out/ | ||
203 | fi | ||
204 | done | ||
205 | |||
206 | # Create service aliases from aliases option. | ||
207 | ${concatStrings (mapAttrsToList (name: unit: | ||
208 | concatMapStrings (name2: '' | ||
209 | ln -sfn '${name}' $out/'${name2}' | ||
210 | '') unit.aliases) units)} | ||
211 | |||
212 | # Create .wants and .requires symlinks from the wantedBy and | ||
213 | # requiredBy options. | ||
214 | ${concatStrings (mapAttrsToList (name: unit: | ||
215 | concatMapStrings (name2: '' | ||
216 | mkdir -p $out/'${name2}.wants' | ||
217 | ln -sfn '../${name}' $out/'${name2}.wants'/ | ||
218 | '') unit.wantedBy) units)} | ||
219 | |||
220 | ${concatStrings (mapAttrsToList (name: unit: | ||
221 | concatMapStrings (name2: '' | ||
222 | mkdir -p $out/'${name2}.requires' | ||
223 | ln -sfn '../${name}' $out/'${name2}.requires'/ | ||
224 | '') unit.requiredBy) units)} | ||
225 | |||
226 | ${optionalString (type == "system") '' | ||
227 | # Stupid misc. symlinks. | ||
228 | ln -s ${cfg.defaultUnit} $out/default.target | ||
229 | ln -s ${cfg.ctrlAltDelUnit} $out/ctrl-alt-del.target | ||
230 | ln -s rescue.target $out/kbrequest.target | ||
231 | |||
232 | mkdir -p $out/getty.target.wants/ | ||
233 | ln -s ../autovt@tty1.service $out/getty.target.wants/ | ||
234 | |||
235 | ln -s ../local-fs.target ../remote-fs.target \ | ||
236 | ../nss-lookup.target ../nss-user-lookup.target ../swap.target \ | ||
237 | $out/multi-user.target.wants/ | ||
238 | ''} | ||
239 | ''; # */ | ||
240 | |||
241 | } | ||