| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 |
|
| 29 | (define-module (gnu services linux)
|
| 30 | #:use-module (guix diagnostics)
|
| 31 | #:use-module (guix gexp)
|
| 32 | #:use-module (guix records)
|
| 33 | #:use-module (guix modules)
|
| 34 | #:use-module (guix i18n)
|
| 35 | #:use-module (guix packages)
|
| 36 | #:use-module (guix ui)
|
| 37 | #:use-module (gnu services)
|
| 38 | #:use-module (gnu services admin)
|
| 39 | #:use-module (gnu services base)
|
| 40 | #:use-module (gnu services configuration)
|
| 41 | #:use-module (gnu services dbus)
|
| 42 | #:use-module (gnu services shepherd)
|
| 43 | #:use-module (gnu system file-systems)
|
| 44 | #:use-module (gnu packages base)
|
| 45 | #:use-module (gnu packages linux)
|
| 46 | #:use-module (gnu packages power)
|
| 47 | #:use-module (gnu packages file-systems)
|
| 48 | #:use-module (srfi srfi-1)
|
| 49 | #:use-module (srfi srfi-26)
|
| 50 | #:use-module (srfi srfi-34)
|
| 51 | #:use-module (srfi srfi-35)
|
| 52 | #:use-module (srfi srfi-171)
|
| 53 | #:use-module (ice-9 format)
|
| 54 | #:use-module (ice-9 match)
|
| 55 | #:use-module (ice-9 string-fun)
|
| 56 | #:export (btrfs-scrub-configuration
|
| 57 | btrfs-scrub-service-type
|
| 58 |
|
| 59 | earlyoom-configuration
|
| 60 | earlyoom-configuration?
|
| 61 | earlyoom-configuration-earlyoom
|
| 62 | earlyoom-configuration-minimum-available-memory
|
| 63 | earlyoom-configuration-minimum-free-swap
|
| 64 | earlyoom-configuration-prefer-regexp
|
| 65 | earlyoom-configuration-avoid-regexp
|
| 66 | earlyoom-configuration-memory-report-interval
|
| 67 | earlyoom-configuration-ignore-positive-oom-score-adj?
|
| 68 | earlyoom-configuration-show-debug-messages?
|
| 69 | earlyoom-configuration-send-notification-command
|
| 70 | earlyoom-service-type
|
| 71 |
|
| 72 | fstrim-configuration
|
| 73 | fstrim-configuration?
|
| 74 | fstrim-configuration-package
|
| 75 | fstrim-configuration-schedule
|
| 76 | fstrim-configuration-listed-in
|
| 77 | fstrim-configuration-verbose?
|
| 78 | fstrim-configuration-quiet-unsupported?
|
| 79 | fstrim-configuration-extra-arguments
|
| 80 | fstrim-service-type
|
| 81 |
|
| 82 | kernel-module-loader-service-type
|
| 83 |
|
| 84 | cachefilesd-configuration
|
| 85 | cachefilesd-configuration?
|
| 86 | cachefilesd-configuration-cachefilesd
|
| 87 | cachefilesd-configuration-debug-output?
|
| 88 | cachefilesd-configuration-use-syslog?
|
| 89 | cachefilesd-configuration-scan?
|
| 90 | cachefilesd-configuration-cache-directory
|
| 91 | cachefilesd-configuration-cache-name
|
| 92 | cachefilesd-configuration-security-context
|
| 93 | cachefilesd-configuration-pause-culling-for-block-percentage
|
| 94 | cachefilesd-configuration-pause-culling-for-file-percentage
|
| 95 | cachefilesd-configuration-resume-culling-for-block-percentage
|
| 96 | cachefilesd-configuration-resume-culling-for-file-percentage
|
| 97 | cachefilesd-configuration-pause-caching-for-block-percentage
|
| 98 | cachefilesd-configuration-pause-caching-for-file-percentage
|
| 99 | cachefilesd-configuration-log2-table-size
|
| 100 | cachefilesd-configuration-cull?
|
| 101 | cachefilesd-configuration-trace-function-entry-in-kernel-module
|
| 102 | cachefilesd-configuration-trace-function-exit-in-kernel-module
|
| 103 | cachefilesd-configuration-trace-internal-checkpoints-in-kernel-module
|
| 104 | cachefilesd-service-type
|
| 105 |
|
| 106 | rasdaemon-configuration
|
| 107 | rasdaemon-configuration?
|
| 108 | rasdaemon-configuration-record?
|
| 109 | rasdaemon-service-type
|
| 110 |
|
| 111 | %default-tuned-configuration-recommend.conf
|
| 112 | %default-tuned-ppd-settings-battery
|
| 113 | %default-tuned-ppd-settings-profiles
|
| 114 |
|
| 115 | tuned-configuration
|
| 116 | tuned-configuration?
|
| 117 | tuned-configuration-fields
|
| 118 | tuned-configuration-tuned
|
| 119 | tuned-configuration-auto-start?
|
| 120 | tuned-configuration-power-profiles-daemon-support?
|
| 121 | tuned-configuration-profiles
|
| 122 | tuned-configuration-settings
|
| 123 | tuned-configuration-ppd-settings
|
| 124 | tuned-configuration-recommend.conf
|
| 125 |
|
| 126 | tuned-settings
|
| 127 | tuned-settings?
|
| 128 | tuned-settings-fields
|
| 129 | tuned-settings-daemon?
|
| 130 | tuned-settings-dynamic-tuning?
|
| 131 | tuned-settings-default-instance-priority
|
| 132 | tuned-settings-recommend-command?
|
| 133 | tuned-settings-sleep-interval
|
| 134 | tuned-settings-update-interval
|
| 135 | tuned-settings-profile-dirs
|
| 136 | tuned-settings-extra-content
|
| 137 |
|
| 138 | tuned-ppd-settings
|
| 139 | tuned-ppd-settings?
|
| 140 | tuned-ppd-settings-fields
|
| 141 | tuned-ppd-settings-default
|
| 142 | tuned-ppd-settings-battery-detection?
|
| 143 | tuned-ppd-settings-sysfs-acpi-monitor?
|
| 144 | tuned-ppd-settings-profiles
|
| 145 | tuned-ppd-settings-battery
|
| 146 | tuned-ppd-settings-extra-content
|
| 147 |
|
| 148 | tuned-file-systems
|
| 149 | tuned-activation
|
| 150 | tuned-shepherd-services
|
| 151 |
|
| 152 | tuned-service-type
|
| 153 |
|
| 154 | zram-device-configuration
|
| 155 | zram-device-configuration?
|
| 156 | zram-device-configuration-size
|
| 157 | zram-device-configuration-compression-algorithm
|
| 158 | zram-device-configuration-memory-limit
|
| 159 | zram-device-configuration-priority
|
| 160 | zram-device-service-type
|
| 161 |
|
| 162 | vfs-mapping-service-type
|
| 163 | vfs-mapping-configuration
|
| 164 | vfs-mapping))
|
| 165 |
|
| 166 |
|
| 167 | |
| 168 | |
| 169 | |
| 170 |
|
| 171 | (define (btrfs-scrub-shepherd-calendar-event? x)
|
| 172 | (or (string? x) (gexp? x)))
|
| 173 |
|
| 174 | (define-maybe string (prefix btrfs-scrub-))
|
| 175 |
|
| 176 | (define-maybe list-of-strings (prefix btrfs-scrub-))
|
| 177 |
|
| 178 | (define (btrfs-scrub-serialize-string field-name value)
|
| 179 | (if (maybe-value-set? value)
|
| 180 | (list value) '()))
|
| 181 |
|
| 182 | (define (btrfs-scrub-serialize-list-of-strings field-name value)
|
| 183 | (if (maybe-value-set? value)
|
| 184 | value '()))
|
| 185 |
|
| 186 | (define-configuration btrfs-scrub-configuration
|
| 187 | (package
|
| 188 | (file-like btrfs-progs)
|
| 189 | "The package providing the @command{btrfs} command." empty-serializer)
|
| 190 | (schedule (btrfs-scrub-shepherd-calendar-event "0 0 1-7 * 0")
|
| 191 | "Schedule for launching @command{btrfs-scrub}, expressed as a string in
|
| 192 | traditional cron syntax or as a gexp evaluating to a Shepherd calendar
|
| 193 | event (@pxref{Timers,,, shepherd, The GNU Shepherd Manual}). By default this
|
| 194 | is set to run the 1st Sunday of the month, at 00:00."
|
| 195 | empty-serializer)
|
| 196 | |
| 197 | (to-scrub (maybe-string "/")
|
| 198 | "Device to scrub. It will scrub the root (\"/\") if not given.")
|
| 199 | (extra-arguments maybe-list-of-strings
|
| 200 | "Extra options to append to @command{btrfs scrub start}
|
| 201 | (run @samp{man btrfs-scrub} for more information). Keep in mind that,
|
| 202 | by default, this service uses the @option{-B} flag (do not background and
|
| 203 | print scrub statistics when finished).")
|
| 204 | (prefix btrfs-scrub-))
|
| 205 |
|
| 206 | (define (serialize-btrfs-scrub-configuration config)
|
| 207 | (list-transduce (compose (base-transducer config) tconcatenate)
|
| 208 | rcons
|
| 209 | btrfs-scrub-configuration-fields))
|
| 210 |
|
| 211 |
|
| 212 | (define (btrfs-scrub-template-action-procedure btrfs-bin cmd-args to-scrub)
|
| 213 | "Template procedure to call the btrfs command, print it's outputs and return
|
| 214 | it's exit code. Taken from
|
| 215 | https://www.gnu.org/software/guile/manual/html_node/Processes.html#index-spawn"
|
| 216 | #~(lambda (_ . args)
|
| 217 | (let* ((stdout-in-out (pipe)) (stderr-in-out (pipe))
|
| 218 | (argv (append (list #$btrfs-bin) '#$cmd-args '(#$to-scrub)))
|
| 219 | (pid (spawn #$btrfs-bin argv
|
| 220 | #:output (cdr stdout-in-out)
|
| 221 | #:error (cdr stderr-in-out))))
|
| 222 | (close-port (cdr stdout-in-out))
|
| 223 | (close-port (cdr stderr-in-out))
|
| 224 | (display (get-string-all (car stdout-in-out)))
|
| 225 | |
| 226 | (display (get-string-all (car stderr-in-out)))
|
| 227 | (close-port (car stdout-in-out))
|
| 228 | (close-port (car stderr-in-out))
|
| 229 | (let* ((status (waitpid pid)) (exit-val (status:exit-val (cdr status))))
|
| 230 | (= EXIT_SUCCESS exit-val)))))
|
| 231 |
|
| 232 |
|
| 233 | (define (btrfs-scrub-status-action-procedure btrfs-bin to-scrub)
|
| 234 | "Return a procedure to check the status of the current BTRFS scrub."
|
| 235 | (btrfs-scrub-template-action-procedure btrfs-bin '("scrub" "status") to-scrub))
|
| 236 |
|
| 237 | (define (btrfs-scrub-cancel-action-procedure btrfs-bin to-scrub)
|
| 238 | "Return a procedure to always cancel the current BTRFS scrub."
|
| 239 | (btrfs-scrub-template-action-procedure btrfs-bin '("scrub" "cancel") to-scrub))
|
| 240 |
|
| 241 | (define (btrfs-scrub-extra-actions btrfs-bin to-scrub)
|
| 242 | (list shepherd-trigger-action
|
| 243 | (shepherd-action (name 'scrub-status)
|
| 244 | (documentation
|
| 245 | "Print the status of the scrubing process.")
|
| 246 | (procedure (btrfs-scrub-status-action-procedure
|
| 247 | btrfs-bin
|
| 248 | to-scrub)))
|
| 249 | (shepherd-action (name 'cancel)
|
| 250 | (documentation
|
| 251 | "Cancel the current scrub (it's an alias for stop).")
|
| 252 | (procedure (btrfs-scrub-cancel-action-procedure
|
| 253 | btrfs-bin
|
| 254 | to-scrub)))))
|
| 255 |
|
| 256 |
|
| 257 | (define (btrfs-scrub-shepherd-services config)
|
| 258 | (match-record config <btrfs-scrub-configuration>
|
| 259 | (package schedule to-scrub)
|
| 260 | (let ((btrfs-bin (file-append package "/bin/btrfs")))
|
| 261 | (list (shepherd-service
|
| 262 | (provision (list (string->symbol (string-append "btrfs-scrub-" to-scrub))))
|
| 263 | (requirement '(user-processes))
|
| 264 | (modules '((shepherd service timer)
|
| 265 | (ice-9 popen)
|
| 266 | (ice-9 textual-ports)))
|
| 267 | (start #~(make-timer-constructor
|
| 268 | #$(if (string? schedule)
|
| 269 | #~(cron-string->calendar-event #$schedule)
|
| 270 | schedule)
|
| 271 | (command (list #$btrfs-bin
|
| 272 | "scrub"
|
| 273 | "start"
|
| 274 | "-B"
|
| 275 | #$@(serialize-btrfs-scrub-configuration config)))
|
| 276 | #:wait-for-termination? #t))
|
| 277 | (stop (btrfs-scrub-cancel-action-procedure btrfs-bin to-scrub))
|
| 278 | (documentation "Periodically run the 'btrfs-scrub' command.")
|
| 279 | (actions (btrfs-scrub-extra-actions btrfs-bin to-scrub)))))))
|
| 280 |
|
| 281 |
|
| 282 | (define btrfs-scrub-service-type
|
| 283 | (service-type (name 'btrfs-scrub)
|
| 284 | (extensions (list (service-extension
|
| 285 | shepherd-root-service-type
|
| 286 | btrfs-scrub-shepherd-services)))
|
| 287 | (description
|
| 288 | "Verify the block checksums of a BTRFS filesystem.")
|
| 289 | (default-value (btrfs-scrub-configuration))))
|
| 290 |
|
| 291 |
|
| 292 | |
| 293 | |
| 294 | |
| 295 |
|
| 296 | (define-record-type* <earlyoom-configuration>
|
| 297 | earlyoom-configuration make-earlyoom-configuration
|
| 298 | earlyoom-configuration?
|
| 299 | (earlyoom earlyoom-configuration-earlyoom
|
| 300 | (default earlyoom))
|
| 301 | (minimum-available-memory earlyoom-configuration-minimum-available-memory
|
| 302 | (default 10)) |
| 303 | (minimum-free-swap earlyoom-configuration-minimum-free-swap
|
| 304 | (default 10)) |
| 305 | (prefer-regexp earlyoom-configuration-prefer-regexp |
| 306 | (default #f))
|
| 307 | (avoid-regexp earlyoom-configuration-avoid-regexp |
| 308 | (default #f))
|
| 309 | (memory-report-interval earlyoom-configuration-memory-report-interval
|
| 310 | (default 0)) |
| 311 | (ignore-positive-oom-score-adj?
|
| 312 | earlyoom-configuration-ignore-positive-oom-score-adj? (default #f))
|
| 313 | (run-with-higher-priority? earlyoom-configuration-run-with-higher-priority?
|
| 314 | (default #f))
|
| 315 | (show-debug-messages? earlyoom-configuration-show-debug-messages?
|
| 316 | (default #f))
|
| 317 | (send-notification-command
|
| 318 | earlyoom-configuration-send-notification-command |
| 319 | (default #f)))
|
| 320 |
|
| 321 | (define (earlyoom-configuration->command-line-args config)
|
| 322 | "Translate a <earlyoom-configuration> object to its command line arguments
|
| 323 | representation."
|
| 324 | (match config
|
| 325 | (($ <earlyoom-configuration> earlyoom minimum-available-memory
|
| 326 | minimum-free-swap prefer-regexp avoid-regexp
|
| 327 | memory-report-interval
|
| 328 | ignore-positive-oom-score-adj?
|
| 329 | run-with-higher-priority? show-debug-messages?
|
| 330 | send-notification-command)
|
| 331 | `(,(file-append earlyoom "/bin/earlyoom")
|
| 332 | ,@(if minimum-available-memory
|
| 333 | (list "-m" (format #f "~s" minimum-available-memory))
|
| 334 | '())
|
| 335 | ,@(if minimum-free-swap
|
| 336 | (list "-s" (format #f "~s" minimum-free-swap))
|
| 337 | '())
|
| 338 | ,@(if prefer-regexp
|
| 339 | (list "--prefer" prefer-regexp)
|
| 340 | '())
|
| 341 | ,@(if avoid-regexp
|
| 342 | (list "--avoid" avoid-regexp)
|
| 343 | '())
|
| 344 | "-r" ,(format #f "~s" memory-report-interval)
|
| 345 | ,@(if ignore-positive-oom-score-adj?
|
| 346 | (list "-i")
|
| 347 | '())
|
| 348 | ,@(if run-with-higher-priority?
|
| 349 | (list "-p")
|
| 350 | '())
|
| 351 | ,@(if show-debug-messages?
|
| 352 | (list "-d")
|
| 353 | '())
|
| 354 | ,@(if send-notification-command
|
| 355 | (list "-N" send-notification-command)
|
| 356 | '())))))
|
| 357 |
|
| 358 | (define (earlyoom-shepherd-service config)
|
| 359 | (shepherd-service
|
| 360 | (documentation "Run the Early OOM daemon.")
|
| 361 | (provision '(earlyoom))
|
| 362 | (requirement '(user-processes))
|
| 363 | (start #~(make-forkexec-constructor
|
| 364 | '#$(earlyoom-configuration->command-line-args config)
|
| 365 | #:log-file "/var/log/earlyoom.log"))
|
| 366 | (stop #~(make-kill-destructor))))
|
| 367 |
|
| 368 | (define earlyoom-service-type
|
| 369 | (service-type
|
| 370 | (name 'earlyoom)
|
| 371 | (default-value (earlyoom-configuration))
|
| 372 | (extensions
|
| 373 | (list (service-extension shepherd-root-service-type
|
| 374 | (compose list earlyoom-shepherd-service))))
|
| 375 | (description "Run @command{earlyoom}, a daemon that quickly responds to
|
| 376 | @acronym{OOM, out-of-memory} conditions by terminating relevant processes.")))
|
| 377 |
|
| 378 |
|
| 379 | |
| 380 | |
| 381 | |
| 382 |
|
| 383 | (define (fstrim-shepherd-calendar-event? x)
|
| 384 | (or (string? x) (gexp? x)))
|
| 385 |
|
| 386 | (define-maybe list-of-strings (prefix fstrim-))
|
| 387 |
|
| 388 | (define (fstrim-serialize-boolean field-name value)
|
| 389 | (list (format #f "~:[~;--~a~]" value
|
| 390 | |
| 391 | (string-drop-right (symbol->string field-name) 1))))
|
| 392 |
|
| 393 | (define (fstrim-serialize-list-of-strings field-name value)
|
| 394 | (list (string-append "--" (symbol->string field-name))
|
| 395 | #~(string-join '#$value ":")))
|
| 396 |
|
| 397 | (define-configuration fstrim-configuration
|
| 398 | (package
|
| 399 | (file-like util-linux)
|
| 400 | "The package providing the @command{fstrim} command."
|
| 401 | empty-serializer)
|
| 402 | (schedule
|
| 403 | (fstrim-shepherd-calendar-event "0 0 * * 0")
|
| 404 | "Schedule for launching @command{fstrim}, expressed as a string in
|
| 405 | traditional cron syntax or as a gexp evaluating to a Shepherd calendar
|
| 406 | event (@pxref{Timers,,, shepherd, The GNU Shepherd Manual}). By default this
|
| 407 | is set to run weekly on Sunday at 00:00."
|
| 408 | empty-serializer)
|
| 409 | |
| 410 | (listed-in
|
| 411 | (maybe-list-of-strings '("/etc/fstab" "/proc/self/mountinfo"))
|
| 412 | |
| 413 | "List of files in fstab or kernel mountinfo format. All missing or
|
| 414 | empty files are silently ignored. The evaluation of the list @emph{stops}
|
| 415 | after the first non-empty file. File systems with @code{X-fstrim.notrim} mount
|
| 416 | option in fstab are skipped.")
|
| 417 | (verbose?
|
| 418 | (boolean #t)
|
| 419 | "Verbose execution.")
|
| 420 | (quiet-unsupported?
|
| 421 | (boolean #t)
|
| 422 | "Suppress error messages if trim operation (ioctl) is unsupported.")
|
| 423 | (extra-arguments
|
| 424 | maybe-list-of-strings
|
| 425 | "Extra options to append to @command{fstrim} (run @samp{man fstrim} for
|
| 426 | more information)."
|
| 427 | (serializer
|
| 428 | (lambda (_ value)
|
| 429 | (if (maybe-value-set? value)
|
| 430 | value '()))))
|
| 431 | (prefix fstrim-))
|
| 432 |
|
| 433 | (define (serialize-fstrim-configuration config)
|
| 434 | (list-transduce (compose (base-transducer config) tconcatenate)
|
| 435 | rcons
|
| 436 | fstrim-configuration-fields))
|
| 437 |
|
| 438 | (define (fstrim-shepherd-services config)
|
| 439 | (match-record config <fstrim-configuration>
|
| 440 | (package schedule)
|
| 441 | (list (shepherd-service
|
| 442 | (provision '(fstrim))
|
| 443 | (requirement '(user-processes))
|
| 444 | (modules '((shepherd service timer)))
|
| 445 | (start #~(make-timer-constructor
|
| 446 | #$(if (string? schedule)
|
| 447 | #~(cron-string->calendar-event #$schedule)
|
| 448 | schedule)
|
| 449 | (command
|
| 450 | (list #$(file-append package "/sbin/fstrim")
|
| 451 | #$@(serialize-fstrim-configuration config)))
|
| 452 | #:wait-for-termination? #t))
|
| 453 | (stop #~(make-timer-destructor))
|
| 454 | (documentation "Periodically run the 'fstrim' command.")
|
| 455 | (actions (list shepherd-trigger-action))))))
|
| 456 |
|
| 457 | (define fstrim-service-type
|
| 458 | (service-type
|
| 459 | (name 'fstrim)
|
| 460 | (extensions
|
| 461 | (list (service-extension shepherd-root-service-type
|
| 462 | fstrim-shepherd-services)))
|
| 463 | (description "Discard unused blocks from file systems.")
|
| 464 | (default-value (fstrim-configuration))))
|
| 465 |
|
| 466 |
|
| 467 | |
| 468 | |
| 469 | |
| 470 |
|
| 471 | (define kernel-module-loader-shepherd-service
|
| 472 | (match-lambda
|
| 473 | ((and (? list? kernel-modules) ((? string?) ...))
|
| 474 | (shepherd-service
|
| 475 | (documentation "Load kernel modules.")
|
| 476 | (provision '(kernel-module-loader))
|
| 477 | (requirement '(udev))
|
| 478 | (one-shot? #t)
|
| 479 | (modules `((srfi srfi-1)
|
| 480 | (srfi srfi-34)
|
| 481 | (srfi srfi-35)
|
| 482 | (rnrs io ports)
|
| 483 | ,@%default-modules))
|
| 484 | (start
|
| 485 | #~(lambda _
|
| 486 | (cond
|
| 487 | ((null? '#$kernel-modules) #t)
|
| 488 | ((file-exists? "/proc/sys/kernel/modprobe")
|
| 489 | (let ((modprobe (call-with-input-file
|
| 490 | "/proc/sys/kernel/modprobe" get-line)))
|
| 491 | (guard (c ((message-condition? c)
|
| 492 | (format (current-error-port) "~a~%"
|
| 493 | (condition-message c))
|
| 494 | #f))
|
| 495 | (every (lambda (module)
|
| 496 | (invoke/quiet modprobe "--" module))
|
| 497 | '#$kernel-modules))))
|
| 498 | (else
|
| 499 | (format (current-error-port) "error: ~a~%"
|
| 500 | "Kernel is missing loadable module support.")
|
| 501 | #f))))))))
|
| 502 |
|
| 503 | (define kernel-module-loader-service-type
|
| 504 | (service-type
|
| 505 | (name 'kernel-module-loader)
|
| 506 | (description "Load kernel modules.")
|
| 507 | (extensions
|
| 508 | (list (service-extension shepherd-root-service-type
|
| 509 | (compose list kernel-module-loader-shepherd-service))))
|
| 510 | (compose concatenate)
|
| 511 | (extend append)
|
| 512 | (default-value '())))
|
| 513 |
|
| 514 |
|
| 515 | |
| 516 | |
| 517 | |
| 518 |
|
| 519 | (define (serialize-string variable-symbol value)
|
| 520 | #~(format #f "~a ~a~%" #$(symbol->string variable-symbol) #$value))
|
| 521 |
|
| 522 | (define-maybe string)
|
| 523 |
|
| 524 | (define (non-negative-integer? val)
|
| 525 | (and (exact-integer? val) (not (negative? val))))
|
| 526 |
|
| 527 | (define (serialize-non-negative-integer variable-symbol value)
|
| 528 | #~(format #f "~a ~d~%" #$(symbol->string variable-symbol) #$value))
|
| 529 |
|
| 530 | (define-maybe non-negative-integer)
|
| 531 |
|
| 532 | (define (make-option-serializer option-symbol)
|
| 533 | (lambda (variable-symbol text)
|
| 534 | (if (maybe-value-set? text)
|
| 535 | #~(format #f "~a ~a~%" #$(symbol->string option-symbol) #$text)
|
| 536 | "")))
|
| 537 |
|
| 538 | (define (make-percentage-threshold-serializer threshold-symbol)
|
| 539 | (lambda (variable-symbol percentage)
|
| 540 | (if (maybe-value-set? percentage)
|
| 541 | #~(format #f "~a ~a%~%" #$(symbol->string threshold-symbol) #$percentage)
|
| 542 | "")))
|
| 543 |
|
| 544 | (define-configuration cachefilesd-configuration
|
| 545 | (cachefilesd
|
| 546 | (file-like cachefilesd)
|
| 547 | "The cachefilesd package to use."
|
| 548 | (serializer empty-serializer))
|
| 549 |
|
| 550 | |
| 551 | (debug-output?
|
| 552 | (boolean #f)
|
| 553 | "Print debugging output to stderr."
|
| 554 | (serializer empty-serializer))
|
| 555 |
|
| 556 | (use-syslog?
|
| 557 | (boolean #t)
|
| 558 | "Log to syslog facility instead of stdout."
|
| 559 | (serializer empty-serializer))
|
| 560 |
|
| 561 | |
| 562 | |
| 563 | (scan?
|
| 564 | (boolean #t)
|
| 565 | "Scan for cacheable objects."
|
| 566 | (serializer empty-serializer))
|
| 567 |
|
| 568 | |
| 569 | (cache-directory
|
| 570 | maybe-string
|
| 571 | "Location of the cache directory."
|
| 572 | (serializer (make-option-serializer 'dir)))
|
| 573 |
|
| 574 | (cache-name
|
| 575 | (maybe-string "CacheFiles")
|
| 576 | "Name of cache (keep unique)."
|
| 577 | (serializer (make-option-serializer 'tag)))
|
| 578 |
|
| 579 | (security-context
|
| 580 | maybe-string
|
| 581 | "SELinux security context."
|
| 582 | (serializer (make-option-serializer 'secctx)))
|
| 583 |
|
| 584 | |
| 585 | (pause-culling-for-block-percentage
|
| 586 | (maybe-non-negative-integer 7)
|
| 587 | "Pause culling when available blocks exceed this percentage."
|
| 588 | (serializer (make-percentage-threshold-serializer 'brun)))
|
| 589 |
|
| 590 | (pause-culling-for-file-percentage
|
| 591 | (maybe-non-negative-integer 7)
|
| 592 | "Pause culling when available files exceed this percentage."
|
| 593 | (serializer (make-percentage-threshold-serializer 'frun)))
|
| 594 |
|
| 595 | (resume-culling-for-block-percentage
|
| 596 | (maybe-non-negative-integer 5)
|
| 597 | "Start culling when available blocks drop below this percentage."
|
| 598 | (serializer (make-percentage-threshold-serializer 'bcull)))
|
| 599 |
|
| 600 | (resume-culling-for-file-percentage
|
| 601 | (maybe-non-negative-integer 5)
|
| 602 | "Start culling when available files drop below this percentage."
|
| 603 | (serializer (make-percentage-threshold-serializer 'fcull)))
|
| 604 |
|
| 605 | (pause-caching-for-block-percentage
|
| 606 | (maybe-non-negative-integer 1)
|
| 607 | "Pause further allocations when available blocks drop below this percentage."
|
| 608 | (serializer (make-percentage-threshold-serializer 'bstop)))
|
| 609 |
|
| 610 | (pause-caching-for-file-percentage
|
| 611 | (maybe-non-negative-integer 1)
|
| 612 | "Pause further allocations when available files drop below this percentage."
|
| 613 | (serializer (make-percentage-threshold-serializer 'fstop)))
|
| 614 |
|
| 615 | |
| 616 | (log2-table-size
|
| 617 | (maybe-non-negative-integer 12)
|
| 618 | "Size of tables holding cullable objects in logarithm of base 2."
|
| 619 | (serializer (make-option-serializer 'culltable)))
|
| 620 |
|
| 621 | (cull?
|
| 622 | (boolean #t)
|
| 623 | "Create free space by culling (consumes system load)."
|
| 624 | (serializer
|
| 625 | (lambda (variable-symbol value)
|
| 626 | (if value "" "nocull\n"))))
|
| 627 |
|
| 628 | |
| 629 | (trace-function-entry-in-kernel-module?
|
| 630 | (boolean #f)
|
| 631 | "Trace function entry in the kernel module (for debugging)."
|
| 632 | (serializer empty-serializer))
|
| 633 |
|
| 634 | (trace-function-exit-in-kernel-module?
|
| 635 | (boolean #f)
|
| 636 | "Trace function exit in the kernel module (for debugging)."
|
| 637 | (serializer empty-serializer))
|
| 638 |
|
| 639 | (trace-internal-checkpoints-in-kernel-module?
|
| 640 | (boolean #f)
|
| 641 | "Trace internal checkpoints in the kernel module (for debugging)."
|
| 642 | (serializer empty-serializer)))
|
| 643 |
|
| 644 | (define (serialize-cachefilesd-configuration configuration)
|
| 645 | (mixed-text-file
|
| 646 | "cachefilesd.conf"
|
| 647 | (serialize-configuration configuration cachefilesd-configuration-fields)))
|
| 648 |
|
| 649 | (define (cachefilesd-shepherd-service config)
|
| 650 | "Return a list of <shepherd-service> for cachefilesd for CONFIG."
|
| 651 | (match-record
|
| 652 | config <cachefilesd-configuration> (cachefilesd
|
| 653 | debug-output?
|
| 654 | use-syslog?
|
| 655 | scan?
|
| 656 | cache-directory)
|
| 657 | (let ((configuration-file (serialize-cachefilesd-configuration config)))
|
| 658 | (shepherd-service
|
| 659 | (documentation "Run the cachefilesd daemon for FS-Cache.")
|
| 660 | (provision '(cachefilesd))
|
| 661 | (requirement (append '(user-processes file-systems)
|
| 662 | (if use-syslog? '(syslogd) '())))
|
| 663 | (start #~(begin
|
| 664 | (and=> #$(maybe-value cache-directory) mkdir-p)
|
| 665 | (make-forkexec-constructor
|
| 666 | `(#$(file-append cachefilesd "/sbin/cachefilesd")
|
| 667 | |
| 668 | "-n"
|
| 669 | #$@(if debug-output? '("-d") '())
|
| 670 | #$@(if use-syslog? '() '("-s"))
|
| 671 | #$@(if scan? '() '("-N"))
|
| 672 | "-f" #$configuration-file))))
|
| 673 | (stop #~(make-kill-destructor))))))
|
| 674 |
|
| 675 | (define cachefilesd-service-type
|
| 676 | (service-type
|
| 677 | (name 'cachefilesd)
|
| 678 | (description
|
| 679 | "Run the file system cache daemon @command{cachefilesd}, which relies on
|
| 680 | the Linux @code{cachefiles} module.")
|
| 681 | (extensions
|
| 682 | (list (service-extension kernel-module-loader-service-type
|
| 683 | (const '("cachefiles")))
|
| 684 | (service-extension shepherd-root-service-type
|
| 685 | (compose list cachefilesd-shepherd-service))))
|
| 686 | (default-value (cachefilesd-configuration))))
|
| 687 |
|
| 688 |
|
| 689 | |
| 690 | |
| 691 | |
| 692 |
|
| 693 | (define-record-type* <rasdaemon-configuration>
|
| 694 | rasdaemon-configuration make-rasdaemon-configuration
|
| 695 | rasdaemon-configuration?
|
| 696 | (record? rasdaemon-configuration-record? (default #f)))
|
| 697 |
|
| 698 | (define (rasdaemon-configuration->command-line-args config)
|
| 699 | "Translate <rasdaemon-configuration> to its command line arguments
|
| 700 | representation"
|
| 701 | (let ((record? (rasdaemon-configuration-record? config)))
|
| 702 | `(,(file-append rasdaemon "/sbin/rasdaemon")
|
| 703 | "--foreground" ,@(if record? '("--record") '()))))
|
| 704 |
|
| 705 | (define (rasdaemon-activation config)
|
| 706 | (let ((record? (rasdaemon-configuration-record? config))
|
| 707 | (rasdaemon-dir "/var/lib/rasdaemon"))
|
| 708 | (with-imported-modules '((guix build utils))
|
| 709 | #~(if #$record? (mkdir-p #$rasdaemon-dir)))))
|
| 710 |
|
| 711 | (define (rasdaemon-shepherd-service config)
|
| 712 | (shepherd-service
|
| 713 | (documentation "Run rasdaemon")
|
| 714 | (provision '(rasdaemon))
|
| 715 | (requirement '(user-processes syslogd))
|
| 716 | (start #~(make-forkexec-constructor
|
| 717 | '#$(rasdaemon-configuration->command-line-args config)))
|
| 718 | (stop #~(make-kill-destructor))))
|
| 719 |
|
| 720 | (define rasdaemon-service-type
|
| 721 | (service-type
|
| 722 | (name 'rasdaemon)
|
| 723 | (default-value (rasdaemon-configuration))
|
| 724 | (extensions
|
| 725 | (list (service-extension shepherd-root-service-type
|
| 726 | (compose list rasdaemon-shepherd-service))
|
| 727 | (service-extension activation-service-type rasdaemon-activation)))
|
| 728 | (compose concatenate)
|
| 729 | (description "Run @command{rasdaemon}, the RAS monitor")))
|
| 730 |
|
| 731 |
|
| 732 | |
| 733 | |
| 734 | |
| 735 |
|
| 736 | (define (uglify-snake-case field-name)
|
| 737 | "Serializes FIELD-NAME, a field name from @code{(gnu services configuration)},
|
| 738 | to a snake case string representation of the field name. Trailing @code{?} in
|
| 739 | the name are dropped and @code{-} get replaced by @code{_}.
|
| 740 |
|
| 741 | For example the procedure would convert @code{'A-Field?} to @code{\"a_field\"}."
|
| 742 | (define str (symbol->string field-name))
|
| 743 | (string-downcase
|
| 744 | (string-replace-substring
|
| 745 | (if (string-suffix? "?" str)
|
| 746 | (string-drop-right str 1)
|
| 747 | str)
|
| 748 | "-" "_")))
|
| 749 |
|
| 750 | (define* (tuned-serialize-pair pair #:key (separator "="))
|
| 751 | (define (valid? member)
|
| 752 | (or (string? member)
|
| 753 | (gexp? member)
|
| 754 | (file-like? member)))
|
| 755 | (match pair
|
| 756 | (((? valid? key) . (? valid? value))
|
| 757 | #~(string-append #$key #$separator #$value))
|
| 758 | (_
|
| 759 | (raise
|
| 760 | (formatted-message
|
| 761 | (G_ "pair members must contain only strings, gexps or file-like objects
|
| 762 | but ~a was found")
|
| 763 | pair)))))
|
| 764 |
|
| 765 | (define* (tuned-ppd-serialize-mixed-list name value #:key (separator " = "))
|
| 766 | (if (zero? (length value))
|
| 767 | ""
|
| 768 | #~(string-append "\n[" #$(uglify-snake-case name) "]\n"
|
| 769 | (string-join
|
| 770 | (list #$@(map tuned-serialize-pair value)) "\n")
|
| 771 | "\n")))
|
| 772 |
|
| 773 | (define (mixed-list? value)
|
| 774 | |
| 775 | |
| 776 | (for-each
|
| 777 | (lambda (el)
|
| 778 | (cond ((string? el) el)
|
| 779 | ((pair? el) (tuned-serialize-pair el))
|
| 780 | (else
|
| 781 | (raise
|
| 782 | (formatted-message
|
| 783 | (G_ "members must be either strings or pairs but ~a was
|
| 784 | found!")
|
| 785 | el)))))
|
| 786 | value)
|
| 787 | #t)
|
| 788 |
|
| 789 | (define (tuned-ppd-serialize-string name value)
|
| 790 | (format #f "~a=~a" (uglify-snake-case name) value))
|
| 791 |
|
| 792 | (define (tuned-ppd-serialize-boolean name value)
|
| 793 | (format #f "~a=~a" (uglify-snake-case name) (if value "true" "false")))
|
| 794 |
|
| 795 | (define %default-tuned-ppd-settings-profiles
|
| 796 | '(("power-saver" . "powersave")
|
| 797 | ("balanced" . "balanced")
|
| 798 | ("performance" . "throughput-performance")))
|
| 799 |
|
| 800 | (define %default-tuned-ppd-settings-battery
|
| 801 | '(("balanced" . "balanced-battery")))
|
| 802 |
|
| 803 | (define-configuration tuned-ppd-settings
|
| 804 | (default
|
| 805 | (string "balanced")
|
| 806 | "Default PPD profile.")
|
| 807 | (battery-detection?
|
| 808 | (boolean #t)
|
| 809 | "Whether to enable battery detection.")
|
| 810 | (sysfs-acpi-monitor?
|
| 811 | (boolean #t)
|
| 812 | "Whether to react to changes of ACPI platform profile done via function keys
|
| 813 | (e.g., Fn-L). This is marked upstream as an experimental feature.")
|
| 814 | (profiles
|
| 815 | (mixed-list %default-tuned-ppd-settings-profiles)
|
| 816 | "Map of PPD profiles states to TuneD profiles. It's supposed to be a list of
|
| 817 | pairs, pair members are supposed to be string. It defaults to
|
| 818 | @code{%default-tuned-ppd-settings-profiles}:
|
| 819 |
|
| 820 | @lisp
|
| 821 | '((\"power-saver\" . \"powersave\")
|
| 822 | (\"balanced\" . \"balanced\")
|
| 823 | (\"performance\" . \"throughput-performance\"))
|
| 824 | @end lisp
|
| 825 |
|
| 826 | Elements can be pairs or strings. Pair members can be either strings, gexps or
|
| 827 | file like objects. Strings are directly passed to the serializer. This can be
|
| 828 | an escape hatch in case the underlying syntax of the output file changes
|
| 829 | slightly and the Scheme API is not adequated in time. This way there is always
|
| 830 | a way to work around Scheme records.")
|
| 831 | (battery
|
| 832 | (mixed-list %default-tuned-ppd-settings-battery)
|
| 833 | "Map of PPD battery states to TuneD profiles. It's supposed to be a list of
|
| 834 | pairs, pair members are supposed to be string. It defaults to
|
| 835 | @code{%default-tuned-ppd-settings-battery}:
|
| 836 |
|
| 837 | @lisp
|
| 838 | '((\"balanced\" . \"balanced-battery\"))
|
| 839 | @end lisp
|
| 840 |
|
| 841 | Elements can be pairs or strings. Pair members can be either strings, gexps or
|
| 842 | file like objects. Strings are directly passed to the serializer. This can be
|
| 843 | an escape hatch in case the underlying syntax of the output file changes
|
| 844 | slightly and the Scheme API is not adequated in time. This way there is always
|
| 845 | a way to work around Scheme records.")
|
| 846 | (extra-content
|
| 847 | (text-config
|
| 848 | (list (plain-file "tuned-ppd-settings-extra-content" "")))
|
| 849 | "A list of file-like objects that are appended to the configuration file."
|
| 850 | (serializer serialize-text-config))
|
| 851 | (prefix tuned-ppd-))
|
| 852 |
|
| 853 | (define (serialize-tuned-ppd-settings config)
|
| 854 | (define fields
|
| 855 | (filter-configuration-fields
|
| 856 | tuned-ppd-settings-fields
|
| 857 | '(default battery-detection? sysfs-acpi-monitor? profiles battery
|
| 858 | extra-content)))
|
| 859 | (define getters
|
| 860 | (map configuration-field-getter fields))
|
| 861 | (define names
|
| 862 | (map configuration-field-name fields))
|
| 863 | (define serializers
|
| 864 | (map configuration-field-serializer fields))
|
| 865 | (define values
|
| 866 | (map (match-lambda ((serializer name getter)
|
| 867 | (serializer name (getter config))))
|
| 868 | (zip serializers names getters)))
|
| 869 |
|
| 870 | (match values
|
| 871 | ((default battery-detection? sysfs-acpi-monitor? profiles battery
|
| 872 | extra-content)
|
| 873 |
|
| 874 | (mixed-text-file "ppd.conf"
|
| 875 | "[main]\n"
|
| 876 | (string-append default "\n")
|
| 877 | (string-append battery-detection? "\n")
|
| 878 | (string-append sysfs-acpi-monitor? "\n")
|
| 879 | "\n"
|
| 880 | profiles
|
| 881 | battery
|
| 882 | extra-content
|
| 883 | "\n"))))
|
| 884 |
|
| 885 | (define (serialize-list-of-profile-dirs name value)
|
| 886 | (if (zero? (length value))
|
| 887 | ""
|
| 888 | #~(string-append
|
| 889 | #$(uglify-snake-case name) " = " (string-join (list #$@value) ","))))
|
| 890 |
|
| 891 | (define (list-of-profile-dirs? value)
|
| 892 | (for-each
|
| 893 | (lambda (el)
|
| 894 | (unless (or (string? el) (file-like? el))
|
| 895 | (raise
|
| 896 | (formatted-message
|
| 897 | (G_ "tuned-settings profile-dirs members must be either a string
|
| 898 | or a file-like object but ~a was found!")
|
| 899 | el))))
|
| 900 | value)
|
| 901 | #t)
|
| 902 |
|
| 903 | (define tuned-serialize-boolean tuned-ppd-serialize-boolean)
|
| 904 | (define tuned-serialize-integer tuned-ppd-serialize-string)
|
| 905 |
|
| 906 | (define-configuration tuned-settings
|
| 907 | (daemon?
|
| 908 | (boolean #t)
|
| 909 | "Whether to use daemon. Without daemon TuneD just applies tuning.")
|
| 910 | (dynamic-tuning?
|
| 911 | (boolean #f)
|
| 912 | "Dynamically tune devices, if disabled only static tuning will be used.")
|
| 913 | (default-instance-priority
|
| 914 | (integer 0)
|
| 915 | "Default priority assigned to instances.")
|
| 916 | (recommend-command?
|
| 917 | (boolean #t)
|
| 918 | "Recommend functionality, if disabled @code{recommend} command will be not
|
| 919 | available in CLI, daemon will not parse @file{recommend.conf} but will return
|
| 920 | one hardcoded profile (by default @code{balanced}).")
|
| 921 | (sleep-interval
|
| 922 | (integer 1)
|
| 923 | "How long to sleep before checking for events (in seconds),
|
| 924 | higher number means lower overhead but longer response time.")
|
| 925 | (update-interval
|
| 926 | (integer 10)
|
| 927 | "Update interval for dynamic tunings (in seconds). It must be a multiple of
|
| 928 | the @code{sleep-interval}.")
|
| 929 | (profile-dirs
|
| 930 | (list-of-profile-dirs
|
| 931 | (list (file-append tuned "/lib/tuned/profiles") "/etc/tuned/profiles"))
|
| 932 | "List of strings or gexps representing directories to search for
|
| 933 | profiles. In case of collisions in profile names, the latter directory takes
|
| 934 | precedence."
|
| 935 | (serializer serialize-list-of-profile-dirs))
|
| 936 | (extra-content
|
| 937 | (text-config
|
| 938 | (list (plain-file "tuned-settings-extra-content" "")))
|
| 939 | "A list of file-like objects that are appended to the configuration file."
|
| 940 | (serializer serialize-text-config))
|
| 941 | (prefix tuned-))
|
| 942 |
|
| 943 | (define (serialize-tuned-settings config)
|
| 944 | (define fields
|
| 945 | (filter-configuration-fields
|
| 946 | tuned-settings-fields
|
| 947 | '(daemon? dynamic-tuning? default-instance-priority
|
| 948 | recommend-command? sleep-interval update-interval profile-dirs
|
| 949 | extra-content)))
|
| 950 | (define getters
|
| 951 | (map configuration-field-getter fields))
|
| 952 | (define names
|
| 953 | (map configuration-field-name fields))
|
| 954 | (define serializers
|
| 955 | (map configuration-field-serializer fields))
|
| 956 | (define values
|
| 957 | (map (match-lambda ((serializer name getter)
|
| 958 | (serializer name (getter config))))
|
| 959 | (zip serializers names getters)))
|
| 960 |
|
| 961 | (match values
|
| 962 | ((daemon? dynamic-tuning? default-instance-priority
|
| 963 | recommend-command? sleep-interval update-interval profile-dirs
|
| 964 | extra-content)
|
| 965 | (mixed-text-file
|
| 966 | "tuned-main.conf"
|
| 967 | (string-append daemon? "\n\n")
|
| 968 | (string-append dynamic-tuning? "\n\n")
|
| 969 | (string-append default-instance-priority "\n\n")
|
| 970 | (string-append recommend-command? "\n\n")
|
| 971 | (string-append sleep-interval "\n\n")
|
| 972 | (string-append update-interval "\n\n")
|
| 973 | profile-dirs
|
| 974 | extra-content
|
| 975 | "\n"))))
|
| 976 |
|
| 977 | (define (tuned-plugin? value)
|
| 978 | (if (and (= 2 (length value))
|
| 979 | (string? (first value))
|
| 980 | (file-like? (second value)))
|
| 981 | #t
|
| 982 | (raise
|
| 983 | (formatted-message
|
| 984 | (G_ "tuned-configuration profiles members must be lists with two
|
| 985 | elements, the first being a string and the second a file-like object, but ~a was
|
| 986 | found!")
|
| 987 | value))))
|
| 988 |
|
| 989 | (define (list-of-tuned-plugins? value)
|
| 990 | (list-of tuned-plugin?))
|
| 991 |
|
| 992 | (define %default-tuned-configuration-recommend.conf
|
| 993 | (file-append tuned "/lib/tuned/recommend.d/50-tuned.conf"))
|
| 994 |
|
| 995 | (define-configuration/no-serialization tuned-configuration
|
| 996 | (tuned
|
| 997 | (package tuned)
|
| 998 | "The TuneD package.")
|
| 999 | (auto-start?
|
| 1000 | (boolean #t)
|
| 1001 | "Whether this service should be started automatically by the Shepherd. If it
|
| 1002 | is @code{#f} the service has to be started manually with @command{herd start}.")
|
| 1003 | (power-profiles-daemon-support?
|
| 1004 | (boolean #f)
|
| 1005 | "Whether the power-profiles-daemon emulation layer should be
|
| 1006 | enabled.")
|
| 1007 | (profiles
|
| 1008 | (list-of-tuned-plugins '())
|
| 1009 | "User provided profiles for TuneD. Each element of the list is supposed to be
|
| 1010 | a list where the first element is the name of the directory where plugin files
|
| 1011 | will be placed under @file{/etc/tuned/profiles} and the second a file like
|
| 1012 | object containing the plugin files:
|
| 1013 |
|
| 1014 | @lisp
|
| 1015 | (list
|
| 1016 | (list \"plugin-name\"
|
| 1017 | (plain-file \"plugin.conf\" \"content\"))
|
| 1018 | (list \"other-plugin\"
|
| 1019 | (file-union \"plugin-data\"
|
| 1020 | (list (list \"other-plugin.conf\"
|
| 1021 | (plain-file \"other-plugin.conf\" \"content\"))
|
| 1022 | (list \"other-plugin.scm\"
|
| 1023 | (program-file \"other-plugin.scm\"
|
| 1024 | #~(display \"content\")))))))
|
| 1025 | @end lisp")
|
| 1026 | (settings
|
| 1027 | (tuned-settings (tuned-settings))
|
| 1028 | "Configuration for TuneD.")
|
| 1029 | (ppd-settings
|
| 1030 | (tuned-ppd-settings (tuned-ppd-settings))
|
| 1031 | "Configuration for the @code{power-profiles-daemon} compatibility layer of
|
| 1032 | TuneD.")
|
| 1033 | (recommend.conf
|
| 1034 | (file-like %default-tuned-configuration-recommend.conf)
|
| 1035 | "File like object containing the recommended profile configuration. Defaults
|
| 1036 | to @code{%default-tuned-configuration-recommend.conf}."))
|
| 1037 |
|
| 1038 | (define (tuned-file-systems config)
|
| 1039 | (list
|
| 1040 | (file-system
|
| 1041 | (device "none")
|
| 1042 | (mount-point "/run/tuned")
|
| 1043 | (type "ramfs")
|
| 1044 | (check? #f))))
|
| 1045 |
|
| 1046 | (define (tuned-activation config)
|
| 1047 | (match-record config <tuned-configuration>
|
| 1048 | (profiles settings ppd-settings recommend.conf)
|
| 1049 | #~(begin
|
| 1050 | (use-modules (guix build utils))
|
| 1051 | (let ((data-directory "/var/lib/tuned")
|
| 1052 | (config-directory "/etc/tuned"))
|
| 1053 | |
| 1054 | (for-each
|
| 1055 | (lambda (dir)
|
| 1056 | (mkdir-p dir)
|
| 1057 | (chmod dir #o755))
|
| 1058 | (list data-directory config-directory
|
| 1059 | |
| 1060 | |
| 1061 | "/etc/tuned/modprobe.d"))
|
| 1062 | |
| 1063 | (invoke #$(file-append coreutils-minimal "/bin/touch")
|
| 1064 | "/etc/tuned/modprobe.d/tuned.conf")
|
| 1065 | |
| 1066 | |
| 1067 | |
| 1068 | |
| 1069 | |
| 1070 | (activate-special-files
|
| 1071 | '(("/etc/tuned/recommend.conf" #$recommend.conf)
|
| 1072 | ("/etc/tuned/profiles"
|
| 1073 | #$(file-union "tuned-profiles" profiles))
|
| 1074 | ("/etc/tuned/tuned-main.conf"
|
| 1075 | #$(serialize-tuned-settings settings))
|
| 1076 | ("/etc/tuned/ppd.conf"
|
| 1077 | #$(serialize-tuned-ppd-settings ppd-settings))))))))
|
| 1078 |
|
| 1079 | (define (tuned-shepherd-services config)
|
| 1080 | (match-record config <tuned-configuration>
|
| 1081 | (tuned auto-start? power-profiles-daemon-support?)
|
| 1082 | (append
|
| 1083 | (list
|
| 1084 | (shepherd-service
|
| 1085 | (documentation "TuneD daemon")
|
| 1086 | (provision '(tuned))
|
| 1087 | (requirement '(dbus-system user-processes udev))
|
| 1088 | (start #~(make-forkexec-constructor
|
| 1089 | '(#$(file-append tuned "/sbin/tuned"))
|
| 1090 | #:log-file "/var/log/tuned/tuned.log"))
|
| 1091 | (stop #~(make-kill-destructor))
|
| 1092 | (auto-start? auto-start?)))
|
| 1093 | (if power-profiles-daemon-support?
|
| 1094 | (list (shepherd-service
|
| 1095 | (documentation "TuneD power-profiles-daemon emulation daemon")
|
| 1096 | (provision '(tuned-ppd power-profiles-daemon))
|
| 1097 | (requirement '(dbus-system user-processes udev tuned))
|
| 1098 | (start
|
| 1099 | #~(make-forkexec-constructor
|
| 1100 | '(#$(file-append tuned "/sbin/tuned-ppd"))
|
| 1101 | #:log-file "/var/log/tuned/tuned-ppd.log"))
|
| 1102 | (stop #~(make-kill-destructor))
|
| 1103 | (auto-start? auto-start?)))
|
| 1104 | '()))))
|
| 1105 |
|
| 1106 | (define tuned-service-type
|
| 1107 | (let ((config->package
|
| 1108 | (compose list tuned-configuration-tuned)))
|
| 1109 | (service-type
|
| 1110 | (name 'tuned)
|
| 1111 | (extensions (list
|
| 1112 | (service-extension shepherd-root-service-type
|
| 1113 | tuned-shepherd-services)
|
| 1114 | (service-extension dbus-root-service-type
|
| 1115 | config->package)
|
| 1116 | (service-extension polkit-service-type
|
| 1117 | config->package)
|
| 1118 | (service-extension profile-service-type
|
| 1119 | config->package)
|
| 1120 | (service-extension file-system-service-type
|
| 1121 | tuned-file-systems)
|
| 1122 | (service-extension activation-service-type
|
| 1123 | tuned-activation)))
|
| 1124 | (default-value (tuned-configuration))
|
| 1125 | (description "Run the TuneD daemon. It is daemon that tunes system settings
|
| 1126 | dynamically. It does so by monitoring the usage of several system components
|
| 1127 | periodically."))))
|
| 1128 |
|
| 1129 |
|
| 1130 | |
| 1131 | |
| 1132 | |
| 1133 | (define-record-type* <zram-device-configuration>
|
| 1134 | zram-device-configuration make-zram-device-configuration
|
| 1135 | zram-device-configuration?
|
| 1136 | (size zram-device-configuration-size
|
| 1137 | (default "1G")) |
| 1138 | (compression-algorithm zram-device-configuration-compression-algorithm
|
| 1139 | (default 'lzo)) |
| 1140 | (memory-limit zram-device-configuration-memory-limit
|
| 1141 | (default 0)) |
| 1142 | (priority zram-device-configuration-priority
|
| 1143 | (default #f) |
| 1144 | (delayed) |
| 1145 | |
| 1146 | (sanitize warn-zram-priority-change)))
|
| 1147 |
|
| 1148 | (define-with-syntax-properties
|
| 1149 | (warn-zram-priority-change (priority properties))
|
| 1150 | (if (eqv? priority -1)
|
| 1151 | (begin
|
| 1152 | (warning (source-properties->location properties)
|
| 1153 | (G_ "using -1 for zram priority is deprecated~%"))
|
| 1154 | (display-hint (G_ "Use #f or leave as default instead (@pxref{Linux \
|
| 1155 | Services})."))
|
| 1156 | #f)
|
| 1157 | priority))
|
| 1158 |
|
| 1159 | (define (zram-device-configuration->udev-string config)
|
| 1160 | "Translate a <zram-device-configuration> into a string which can be
|
| 1161 | placed in a udev rules file."
|
| 1162 | (match config
|
| 1163 | (($ <zram-device-configuration> size compression-algorithm memory-limit priority)
|
| 1164 | (string-append
|
| 1165 | "KERNEL==\"zram0\", "
|
| 1166 | "ATTR{comp_algorithm}=\"" (symbol->string compression-algorithm) "\" "
|
| 1167 | (if (not (or (equal? "0" size)
|
| 1168 | (equal? 0 size)))
|
| 1169 | (string-append "ATTR{disksize}=\"" (if (number? size)
|
| 1170 | (number->string size)
|
| 1171 | size)
|
| 1172 | "\" ")
|
| 1173 | "")
|
| 1174 | (if (not (or (equal? "0" memory-limit)
|
| 1175 | (equal? 0 memory-limit)))
|
| 1176 | (string-append "ATTR{mem_limit}=\"" (if (number? memory-limit)
|
| 1177 | (number->string memory-limit)
|
| 1178 | memory-limit)
|
| 1179 | "\" ")
|
| 1180 | "")
|
| 1181 | "RUN+=\"/run/current-system/profile/sbin/mkswap /dev/zram0\" "
|
| 1182 | "RUN+=\"/run/current-system/profile/sbin/swapon "
|
| 1183 | |
| 1184 | |
| 1185 | (let ((priority* (force priority)))
|
| 1186 | (if priority*
|
| 1187 | (format #f "--priority ~a " priority*)
|
| 1188 | ""))
|
| 1189 | "/dev/zram0\"\n"))))
|
| 1190 |
|
| 1191 | (define %zram-device-config
|
| 1192 | `("modprobe.d/zram.conf"
|
| 1193 | ,(plain-file "zram.conf"
|
| 1194 | "options zram num_devices=1")))
|
| 1195 |
|
| 1196 | (define (zram-device-udev-rule config)
|
| 1197 | (file->udev-rule "99-zram.rules"
|
| 1198 | (plain-file "99-zram.rules"
|
| 1199 | (zram-device-configuration->udev-string config))))
|
| 1200 |
|
| 1201 | (define zram-device-service-type
|
| 1202 | (service-type
|
| 1203 | (name 'zram)
|
| 1204 | (default-value (zram-device-configuration))
|
| 1205 | (extensions
|
| 1206 | (list (service-extension kernel-module-loader-service-type
|
| 1207 | (const (list "zram")))
|
| 1208 | (service-extension etc-service-type
|
| 1209 | (const (list %zram-device-config)))
|
| 1210 | (service-extension udev-service-type
|
| 1211 | (compose list zram-device-udev-rule))))
|
| 1212 | (description "Creates a zram swap device.")))
|
| 1213 |
|
| 1214 |
|
| 1215 | |
| 1216 | |
| 1217 | |
| 1218 |
|
| 1219 | (define-record-type* <vfs-mapping>
|
| 1220 | vfs-mapping make-vfs-mapping
|
| 1221 | vfs-mapping?
|
| 1222 | (source vfs-mapping-source)
|
| 1223 | (destination vfs-mapping-destination)
|
| 1224 | (policy vfs-mapping-policy
|
| 1225 | (default 'translate))
|
| 1226 | (user vfs-mapping-user
|
| 1227 | (default #f))
|
| 1228 | (group vfs-mapping-group
|
| 1229 | (default "users"))
|
| 1230 | (name vfs-mapping-name
|
| 1231 | (default (format #f "~a-on-~a"
|
| 1232 | (vfs-mapping-policy this-record)
|
| 1233 | (vfs-mapping-destination this-record)))
|
| 1234 | (thunked))
|
| 1235 | (requirement vfs-mapping-requirement
|
| 1236 | (default '(file-systems user-homes))))
|
| 1237 |
|
| 1238 | (define (vfs-mapping-policy? x)
|
| 1239 | (and (symbol? x)
|
| 1240 | (or (memq x '(bind translate overlay)))))
|
| 1241 |
|
| 1242 | (define (path-like? x)
|
| 1243 | (or (string? x)
|
| 1244 | (file-like? x)
|
| 1245 | (gexp? x)))
|
| 1246 |
|
| 1247 | (define (valid-vfs-mapping? x)
|
| 1248 | |
| 1249 | (and (vfs-mapping? x)
|
| 1250 | (path-like? (vfs-mapping-source x))
|
| 1251 | (path-like? (vfs-mapping-destination x))
|
| 1252 | (string? (vfs-mapping-name x))
|
| 1253 | (vfs-mapping-policy? (vfs-mapping-policy x))
|
| 1254 | (cond
|
| 1255 | ((eq? (vfs-mapping-policy x) 'bind)
|
| 1256 | (not (vfs-mapping-user x)))
|
| 1257 | (#t
|
| 1258 | (and (string? (vfs-mapping-user x))
|
| 1259 | (string? (vfs-mapping-group x)))))))
|
| 1260 |
|
| 1261 | (define list-of-vfs-mapping? (list-of valid-vfs-mapping?))
|
| 1262 |
|
| 1263 | (define-configuration/no-serialization vfs-mapping-configuration
|
| 1264 | (bindfs (gexp #~(string-append #$bindfs "/bin/bindfs"))
|
| 1265 | "The bindfs command to use.")
|
| 1266 | (fusermount (gexp #~(string-append #$fuse-2 "/bin/fusermount"))
|
| 1267 | "The fusermount command to use.")
|
| 1268 | (umount (gexp #~(string-append #$util-linux+udev "/bin/umount"))
|
| 1269 | "The umount command to use.")
|
| 1270 | (bindings (list-of-vfs-mapping '())
|
| 1271 | "The list of bindings to mount"))
|
| 1272 |
|
| 1273 | (define vfs-mapping-shepherd-services
|
| 1274 | (match-record-lambda <vfs-mapping-configuration>
|
| 1275 | (fusermount bindfs umount bindings)
|
| 1276 | (map
|
| 1277 | (match-record-lambda <vfs-mapping>
|
| 1278 | (source destination policy user group name requirement)
|
| 1279 | (shepherd-service
|
| 1280 | |
| 1281 | (provision (list (string->symbol name)))
|
| 1282 | |
| 1283 | (requirement requirement)
|
| 1284 | (modules `((ice-9 match)
|
| 1285 | ,@%default-modules))
|
| 1286 | (stop
|
| 1287 | #~(lambda args
|
| 1288 | (match (quote #$policy)
|
| 1289 | ('bind (invoke #$umount #$destination))
|
| 1290 | ('translate (invoke #$fusermount "-u" #$destination))
|
| 1291 | ('overlay (begin
|
| 1292 | |
| 1293 | (invoke #$fusermount "-u" #$destination)
|
| 1294 | |
| 1295 | (invoke #$umount #$destination))))
|
| 1296 | #f))
|
| 1297 | (start
|
| 1298 | #~(lambda args
|
| 1299 | (define (mkdir-recursively dir user group)
|
| 1300 | |
| 1301 | |
| 1302 | (unless (eq? dir "/")
|
| 1303 | (when (not (file-exists? dir))
|
| 1304 | (mkdir-recursively (dirname dir) user group)
|
| 1305 | (mkdir dir)
|
| 1306 | (let* ((pw (getpw user))
|
| 1307 | (uid (passwd:uid pw))
|
| 1308 | (gid (passwd:gid pw)))
|
| 1309 | (chown dir uid gid)))))
|
| 1310 | (mkdir-recursively #$destination #$user #$group)
|
| 1311 | (let* ((stat (stat #$source))
|
| 1312 | (uid (stat:uid stat))
|
| 1313 | (gid (stat:gid stat))
|
| 1314 | (source-user (passwd:name (getpwuid uid)))
|
| 1315 | (source-group (group:name (getgrgid gid))))
|
| 1316 | (match (quote #$policy)
|
| 1317 | ('bind
|
| 1318 | (mount #$source #$destination
|
| 1319 | #f |
| 1320 | MS_BIND)) |
| 1321 | ('translate
|
| 1322 | (invoke
|
| 1323 | #$bindfs
|
| 1324 | (string-append "--create-for-group=" source-group)
|
| 1325 | (string-append "--create-for-user=" source-user)
|
| 1326 | (string-append "--force-user=" #$user)
|
| 1327 | (string-append "--force-group=" #$group)
|
| 1328 | "-o" "nonempty"
|
| 1329 | #$source #$destination))
|
| 1330 | ('overlay
|
| 1331 | (let ((overlay (string-append #$destination "-overlay"))
|
| 1332 | (workdir (string-append #$destination "-workdir")))
|
| 1333 | (mkdir-recursively overlay #$user #$group)
|
| 1334 | (mkdir-recursively workdir #$user #$group)
|
| 1335 | (mount "overlay" |
| 1336 | #$destination
|
| 1337 | "overlay" |
| 1338 | 0 |
| 1339 | (string-append |
| 1340 | "lowerdir=" #$source ","
|
| 1341 | "upperdir=" overlay ","
|
| 1342 | "workdir=" workdir))
|
| 1343 | |
| 1344 | |
| 1345 | (invoke
|
| 1346 | #$bindfs
|
| 1347 | (string-append "--create-for-group=" source-group)
|
| 1348 | (string-append "--create-for-user=" source-user)
|
| 1349 | (string-append "--force-user=" #$user)
|
| 1350 | (string-append "--force-group=" #$group)
|
| 1351 | #$destination #$destination)))))
|
| 1352 | #t))))
|
| 1353 | bindings)))
|
| 1354 |
|
| 1355 | (define vfs-mapping-service-type
|
| 1356 | (service-type
|
| 1357 | (name 'vfs-mapping)
|
| 1358 | (extensions (list
|
| 1359 | (service-extension shepherd-root-service-type
|
| 1360 | vfs-mapping-shepherd-services)))
|
| 1361 | (compose concatenate)
|
| 1362 | (extend (lambda (original extensions)
|
| 1363 | (vfs-mapping-configuration
|
| 1364 | (inherit original)
|
| 1365 | (bindings (append (vfs-mapping-configuration-bindings original)
|
| 1366 | extensions)))))
|
| 1367 | (default-value (vfs-mapping-configuration))
|
| 1368 | (description "Share or expose a file name under a different name.")))
|