Commit | Line | Data |
---|---|---|
d3e439e3 MC |
1 | ;;; GNU Guix --- Functional package management for GNU |
2 | ;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com> | |
044d1478 | 3 | ;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re> |
587e0d91 | 4 | ;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il> |
fe7529d7 | 5 | ;;; Copyright © 2021 raid5atemyhomework <raid5atemyhomework@protonmail.com> |
2c93df3d | 6 | ;;; Copyright © 2021 B. Wilson <elaexuotee@wilsonb.com> |
a99015c8 | 7 | ;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz> |
d3e439e3 MC |
8 | ;;; |
9 | ;;; This file is part of GNU Guix. | |
10 | ;;; | |
11 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | |
12 | ;;; under the terms of the GNU General Public License as published by | |
13 | ;;; the Free Software Foundation; either version 3 of the License, or (at | |
14 | ;;; your option) any later version. | |
15 | ;;; | |
16 | ;;; GNU Guix is distributed in the hope that it will be useful, but | |
17 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;;; GNU General Public License for more details. | |
20 | ;;; | |
21 | ;;; You should have received a copy of the GNU General Public License | |
22 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | |
23 | ||
24 | (define-module (gnu services linux) | |
a99015c8 | 25 | #:use-module (guix diagnostics) |
d3e439e3 MC |
26 | #:use-module (guix gexp) |
27 | #:use-module (guix records) | |
28 | #:use-module (guix modules) | |
a99015c8 JP |
29 | #:use-module (guix i18n) |
30 | #:use-module (guix ui) | |
d3e439e3 | 31 | #:use-module (gnu services) |
587e0d91 | 32 | #:use-module (gnu services base) |
d3e439e3 MC |
33 | #:use-module (gnu services shepherd) |
34 | #:use-module (gnu packages linux) | |
35 | #:use-module (srfi srfi-1) | |
36 | #:use-module (srfi srfi-26) | |
044d1478 BW |
37 | #:use-module (srfi srfi-34) |
38 | #:use-module (srfi srfi-35) | |
d3e439e3 MC |
39 | #:use-module (ice-9 match) |
40 | #:export (earlyoom-configuration | |
41 | earlyoom-configuration? | |
42 | earlyoom-configuration-earlyoom | |
43 | earlyoom-configuration-minimum-available-memory | |
44 | earlyoom-configuration-minimum-free-swap | |
45 | earlyoom-configuration-prefer-regexp | |
46 | earlyoom-configuration-avoid-regexp | |
47 | earlyoom-configuration-memory-report-interval | |
48 | earlyoom-configuration-ignore-positive-oom-score-adj? | |
49 | earlyoom-configuration-show-debug-messages? | |
50 | earlyoom-configuration-send-notification-command | |
044d1478 BW |
51 | earlyoom-service-type |
52 | ||
587e0d91 EF |
53 | kernel-module-loader-service-type |
54 | ||
2c93df3d W |
55 | rasdaemon-configuration |
56 | rasdaemon-configuration? | |
57 | rasdaemon-configuration-record? | |
58 | rasdaemon-service-type | |
59 | ||
587e0d91 EF |
60 | zram-device-configuration |
61 | zram-device-configuration? | |
62 | zram-device-configuration-size | |
63 | zram-device-configuration-compression-algorithm | |
64 | zram-device-configuration-memory-limit | |
65 | zram-device-configuration-priority | |
66 | zram-device-service-type)) | |
d3e439e3 MC |
67 | |
68 | \f | |
69 | ;;; | |
70 | ;;; Early OOM daemon. | |
71 | ;;; | |
72 | ||
73 | (define-record-type* <earlyoom-configuration> | |
74 | earlyoom-configuration make-earlyoom-configuration | |
75 | earlyoom-configuration? | |
76 | (earlyoom earlyoom-configuration-earlyoom | |
77 | (default earlyoom)) | |
78 | (minimum-available-memory earlyoom-configuration-minimum-available-memory | |
79 | (default 10)) ; in percent | |
80 | (minimum-free-swap earlyoom-configuration-minimum-free-swap | |
81 | (default 10)) ; in percent | |
82 | (prefer-regexp earlyoom-configuration-prefer-regexp ; <string> | |
83 | (default #f)) | |
84 | (avoid-regexp earlyoom-configuration-avoid-regexp ; <string> | |
85 | (default #f)) | |
86 | (memory-report-interval earlyoom-configuration-memory-report-interval | |
87 | (default 0)) ; in seconds; 0 means disabled | |
88 | (ignore-positive-oom-score-adj? | |
89 | earlyoom-configuration-ignore-positive-oom-score-adj? (default #f)) | |
90 | (run-with-higher-priority? earlyoom-configuration-run-with-higher-priority? | |
91 | (default #f)) | |
92 | (show-debug-messages? earlyoom-configuration-show-debug-messages? | |
93 | (default #f)) | |
94 | (send-notification-command | |
95 | earlyoom-configuration-send-notification-command ; <string> | |
96 | (default #f))) | |
97 | ||
98 | (define (earlyoom-configuration->command-line-args config) | |
99 | "Translate a <earlyoom-configuration> object to its command line arguments | |
100 | representation." | |
101 | (match config | |
102 | (($ <earlyoom-configuration> earlyoom minimum-available-memory | |
103 | minimum-free-swap prefer-regexp avoid-regexp | |
104 | memory-report-interval | |
105 | ignore-positive-oom-score-adj? | |
106 | run-with-higher-priority? show-debug-messages? | |
107 | send-notification-command) | |
108 | `(,(file-append earlyoom "/bin/earlyoom") | |
109 | ,@(if minimum-available-memory | |
110 | (list "-m" (format #f "~s" minimum-available-memory)) | |
111 | '()) | |
112 | ,@(if minimum-free-swap | |
113 | (list "-s" (format #f "~s" minimum-free-swap)) | |
114 | '()) | |
115 | ,@(if prefer-regexp | |
116 | (list "--prefer" prefer-regexp) | |
117 | '()) | |
118 | ,@(if avoid-regexp | |
119 | (list "--avoid" avoid-regexp) | |
120 | '()) | |
121 | "-r" ,(format #f "~s" memory-report-interval) | |
122 | ,@(if ignore-positive-oom-score-adj? | |
123 | (list "-i") | |
124 | '()) | |
125 | ,@(if run-with-higher-priority? | |
126 | (list "-p") | |
127 | '()) | |
128 | ,@(if show-debug-messages? | |
129 | (list "-d") | |
130 | '()) | |
131 | ,@(if send-notification-command | |
132 | (list "-N" send-notification-command) | |
133 | '()))))) | |
134 | ||
135 | (define (earlyoom-shepherd-service config) | |
136 | (shepherd-service | |
137 | (documentation "Run the Early OOM daemon.") | |
138 | (provision '(earlyoom)) | |
139 | (start #~(make-forkexec-constructor | |
140 | '#$(earlyoom-configuration->command-line-args config) | |
141 | #:log-file "/var/log/earlyoom.log")) | |
142 | (stop #~(make-kill-destructor)))) | |
143 | ||
144 | (define earlyoom-service-type | |
145 | (service-type | |
146 | (name 'earlyoom) | |
147 | (default-value (earlyoom-configuration)) | |
148 | (extensions | |
149 | (list (service-extension shepherd-root-service-type | |
150 | (compose list earlyoom-shepherd-service)))) | |
151 | (description "Run @command{earlyoom}, the Early OOM daemon."))) | |
044d1478 BW |
152 | |
153 | \f | |
154 | ;;; | |
155 | ;;; Kernel module loader. | |
156 | ;;; | |
157 | ||
158 | (define kernel-module-loader-shepherd-service | |
159 | (match-lambda | |
160 | ((and (? list? kernel-modules) ((? string?) ...)) | |
3d3185b5 BW |
161 | (shepherd-service |
162 | (documentation "Load kernel modules.") | |
163 | (provision '(kernel-module-loader)) | |
fe7529d7 | 164 | (requirement '()) |
3d3185b5 BW |
165 | (one-shot? #t) |
166 | (modules `((srfi srfi-1) | |
167 | (srfi srfi-34) | |
168 | (srfi srfi-35) | |
169 | (rnrs io ports) | |
170 | ,@%default-modules)) | |
171 | (start | |
172 | #~(lambda _ | |
173 | (cond | |
174 | ((null? '#$kernel-modules) #t) | |
175 | ((file-exists? "/proc/sys/kernel/modprobe") | |
176 | (let ((modprobe (call-with-input-file | |
177 | "/proc/sys/kernel/modprobe" get-line))) | |
178 | (guard (c ((message-condition? c) | |
179 | (format (current-error-port) "~a~%" | |
180 | (condition-message c)) | |
181 | #f)) | |
182 | (every (lambda (module) | |
183 | (invoke/quiet modprobe "--" module)) | |
184 | '#$kernel-modules)))) | |
185 | (else | |
186 | (format (current-error-port) "error: ~a~%" | |
187 | "Kernel is missing loadable module support.") | |
188 | #f)))))))) | |
044d1478 BW |
189 | |
190 | (define kernel-module-loader-service-type | |
191 | (service-type | |
192 | (name 'kernel-module-loader) | |
193 | (description "Load kernel modules.") | |
194 | (extensions | |
195 | (list (service-extension shepherd-root-service-type | |
3d3185b5 | 196 | (compose list kernel-module-loader-shepherd-service)))) |
044d1478 BW |
197 | (compose concatenate) |
198 | (extend append) | |
199 | (default-value '()))) | |
587e0d91 EF |
200 | |
201 | \f | |
2c93df3d W |
202 | ;;; |
203 | ;;; Reliability, Availability, and Serviceability (RAS) daemon | |
204 | ;;; | |
205 | ||
206 | (define-record-type* <rasdaemon-configuration> | |
207 | rasdaemon-configuration make-rasdaemon-configuration | |
208 | rasdaemon-configuration? | |
209 | (record? rasdaemon-configuration-record? (default #f))) | |
210 | ||
211 | (define (rasdaemon-configuration->command-line-args config) | |
212 | "Translate <rasdaemon-configuration> to its command line arguments | |
213 | representation" | |
214 | (let ((record? (rasdaemon-configuration-record? config))) | |
215 | `(,(file-append rasdaemon "/sbin/rasdaemon") | |
216 | "--foreground" ,@(if record? '("--record") '())))) | |
217 | ||
218 | (define (rasdaemon-activation config) | |
219 | (let ((record? (rasdaemon-configuration-record? config)) | |
220 | (rasdaemon-dir "/var/lib/rasdaemon")) | |
221 | (with-imported-modules '((guix build utils)) | |
222 | #~(if #$record? (mkdir-p #$rasdaemon-dir))))) | |
223 | ||
224 | (define (rasdaemon-shepherd-service config) | |
225 | (shepherd-service | |
226 | (documentation "Run rasdaemon") | |
227 | (provision '(rasdaemon)) | |
228 | (requirement '(syslogd)) | |
229 | (start #~(make-forkexec-constructor | |
230 | '#$(rasdaemon-configuration->command-line-args config))) | |
231 | (stop #~(make-kill-destructor)))) | |
232 | ||
233 | (define rasdaemon-service-type | |
234 | (service-type | |
235 | (name 'rasdaemon) | |
236 | (default-value (rasdaemon-configuration)) | |
237 | (extensions | |
238 | (list (service-extension shepherd-root-service-type | |
239 | (compose list rasdaemon-shepherd-service)) | |
240 | (service-extension activation-service-type rasdaemon-activation))) | |
241 | (compose concatenate) | |
242 | (description "Run @command{rasdaemon}, the RAS monitor"))) | |
243 | ||
244 | \f | |
587e0d91 EF |
245 | ;;; |
246 | ;;; Kernel module loader. | |
247 | ;;; | |
248 | ||
249 | (define-record-type* <zram-device-configuration> | |
250 | zram-device-configuration make-zram-device-configuration | |
251 | zram-device-configuration? | |
71992a53 | 252 | (size zram-device-configuration-size |
587e0d91 EF |
253 | (default "1G")) ; string or integer |
254 | (compression-algorithm zram-device-configuration-compression-algorithm | |
255 | (default 'lzo)) ; symbol | |
256 | (memory-limit zram-device-configuration-memory-limit | |
257 | (default 0)) ; string or integer | |
258 | (priority zram-device-configuration-priority | |
a99015c8 JP |
259 | (default #f) ; integer | #f |
260 | (delayed) ; to avoid printing the deprecation | |
261 | ; warning multiple times | |
262 | (sanitize warn-zram-priority-change))) | |
263 | ||
264 | (define-with-syntax-properties | |
265 | (warn-zram-priority-change (priority properties)) | |
266 | (if (eqv? priority -1) | |
267 | (begin | |
268 | (warning (source-properties->location properties) | |
269 | (G_ "using -1 for zram priority is deprecated~%")) | |
270 | (display-hint (G_ "Use #f or leave as default instead (@pxref{Linux \ | |
271 | Services}).")) | |
272 | #f) | |
273 | priority)) | |
587e0d91 EF |
274 | |
275 | (define (zram-device-configuration->udev-string config) | |
276 | "Translate a <zram-device-configuration> into a string which can be | |
277 | placed in a udev rules file." | |
278 | (match config | |
279 | (($ <zram-device-configuration> size compression-algorithm memory-limit priority) | |
280 | (string-append | |
281 | "KERNEL==\"zram0\", " | |
282 | "ATTR{comp_algorithm}=\"" (symbol->string compression-algorithm) "\" " | |
283 | (if (not (or (equal? "0" size) | |
284 | (equal? 0 size))) | |
285 | (string-append "ATTR{disksize}=\"" (if (number? size) | |
286 | (number->string size) | |
287 | size) | |
288 | "\" ") | |
289 | "") | |
290 | (if (not (or (equal? "0" memory-limit) | |
291 | (equal? 0 memory-limit))) | |
292 | (string-append "ATTR{mem_limit}=\"" (if (number? memory-limit) | |
293 | (number->string memory-limit) | |
294 | memory-limit) | |
295 | "\" ") | |
296 | "") | |
297 | "RUN+=\"/run/current-system/profile/sbin/mkswap /dev/zram0\" " | |
298 | "RUN+=\"/run/current-system/profile/sbin/swapon " | |
a99015c8 JP |
299 | ;; TODO: Revert to simply use 'priority' after removing the deprecation |
300 | ;; warning and the delayed property of the field. | |
301 | (let ((priority* (force priority))) | |
302 | (if priority* | |
303 | (format #f "--priority ~a " priority*) | |
304 | "")) | |
587e0d91 EF |
305 | "/dev/zram0\"\n")))) |
306 | ||
307 | (define %zram-device-config | |
308 | `("modprobe.d/zram.conf" | |
309 | ,(plain-file "zram.conf" | |
310 | "options zram num_devices=1"))) | |
311 | ||
312 | (define (zram-device-udev-rule config) | |
313 | (file->udev-rule "99-zram.rules" | |
314 | (plain-file "99-zram.rules" | |
315 | (zram-device-configuration->udev-string config)))) | |
316 | ||
317 | (define zram-device-service-type | |
318 | (service-type | |
319 | (name 'zram) | |
320 | (default-value (zram-device-configuration)) | |
321 | (extensions | |
322 | (list (service-extension kernel-module-loader-service-type | |
323 | (const (list "zram"))) | |
324 | (service-extension etc-service-type | |
325 | (const (list %zram-device-config))) | |
326 | (service-extension udev-service-type | |
327 | (compose list zram-device-udev-rule)))) | |
328 | (description "Creates a zram swap device."))) |