diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2015-11-02 18:44:17 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2015-11-02 22:25:11 +0100 |
| commit | d62e201cfd0f1e48c14586489d0e2b80ce943d4f (patch) | |
| tree | d6c4989b36b54f154f21363ac72bd9896729f2de | |
| parent | 3a391e68dafe81560d3e4936a1ec5ac3b06d43bb (diff) | |
services: Add 'system-service-type'.
* gnu/services.scm (system-derivation): New procedure.
(system-service-type): New variable.
(boot-script-entry): New procedure.
(boot-service-type): Extend SYSTEM-SERVICE-TYPE.
(etc-entry): New procedure.
(etc-service-type): Extend SYSTEM-SERVICE-TYPE.
(fold-services): Change default #:target-type to SYSTEM-SERVICE-TYPE.
* gnu/system.scm (operating-system-directory-base-entries): New procedure.
(essential-services): Use it. Add an instance of
SYSTEM-SERVICE-TYPE.
(operating-system-boot-script): Pass #:target-type to 'fold-services'.
(operating-system-derivation): Rewrite in terms of 'fold-services'.
* gnu/system/linux-container.scm (system-container): Remove.
(container-script): Use 'operating-system-derivation'.
* guix/scripts/system.scm (export-extension-graph): Replace
BOOT-SERVICE-TYPE by SYSTEM-SERVICE-TYPE.
* doc/images/service-graph.dot: Add 'system' node and edges.
* doc/guix.texi (Service Composition): Mention SYSTEM-SERVICE-TYPE.
(Service Reference): Document it. Update 'fold-services'
documentation.
| -rw-r--r-- | doc/guix.texi | 26 | ||||
| -rw-r--r-- | doc/images/service-graph.dot | 5 | ||||
| -rw-r--r-- | gnu/services.scm | 51 | ||||
| -rw-r--r-- | gnu/system.scm | 54 | ||||
| -rw-r--r-- | gnu/system/linux-container.scm | 18 | ||||
| -rw-r--r-- | guix/scripts/system.scm | 6 |
6 files changed, 103 insertions, 57 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index 74e0977db50..6ab98deef3a 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -7589,8 +7589,11 @@ as arrows, a typical system might provide something like this: | |||
| 7589 | 7589 | ||
| 7590 | @image{images/service-graph,,5in,Typical service extension graph.} | 7590 | @image{images/service-graph,,5in,Typical service extension graph.} |
| 7591 | 7591 | ||
| 7592 | At the bottom, we see the @dfn{boot service}, which produces the boot | 7592 | @cindex system service |
| 7593 | script that is executed at boot time from the initial RAM disk. | 7593 | At the bottom, we see the @dfn{system service}, which produces the |
| 7594 | directory containing everything to run and boot the system, as returned | ||
| 7595 | by the @command{guix system build} command. @xref{Service Reference}, | ||
| 7596 | to learn about the other service types shown here. | ||
| 7594 | @xref{system-extension-graph, the @command{guix system extension-graph} | 7597 | @xref{system-extension-graph, the @command{guix system extension-graph} |
| 7595 | command}, for information on how to generate this representation for a | 7598 | command}, for information on how to generate this representation for a |
| 7596 | particular operating system definition. | 7599 | particular operating system definition. |
| @@ -7853,12 +7856,14 @@ Return true if @var{obj} is a service extension. | |||
| 7853 | 7856 | ||
| 7854 | At the core of the service abstraction lies the @code{fold-services} | 7857 | At the core of the service abstraction lies the @code{fold-services} |
| 7855 | procedure, which is responsible for ``compiling'' a list of services | 7858 | procedure, which is responsible for ``compiling'' a list of services |
| 7856 | down to a single boot script. In essence, it propagates service | 7859 | down to a single directory that contains everything needed to boot and |
| 7857 | extensions down the service graph, updating each node parameters on the | 7860 | run the system---the directory shown by the @command{guix system build} |
| 7858 | way, until it reaches the root node. | 7861 | command (@pxref{Invoking guix system}). In essence, it propagates |
| 7862 | service extensions down the service graph, updating each node parameters | ||
| 7863 | on the way, until it reaches the root node. | ||
| 7859 | 7864 | ||
| 7860 | @deffn {Scheme Procedure} fold-services @var{services} @ | 7865 | @deffn {Scheme Procedure} fold-services @var{services} @ |
| 7861 | [#:target-type @var{boot-service-type}] | 7866 | [#:target-type @var{system-service-type}] |
| 7862 | Fold @var{services} by propagating their extensions down to the root of | 7867 | Fold @var{services} by propagating their extensions down to the root of |
| 7863 | type @var{target-type}; return the root service adjusted accordingly. | 7868 | type @var{target-type}; return the root service adjusted accordingly. |
| 7864 | @end deffn | 7869 | @end deffn |
| @@ -7866,9 +7871,14 @@ type @var{target-type}; return the root service adjusted accordingly. | |||
| 7866 | Lastly, the @code{(gnu services)} module also defines several essential | 7871 | Lastly, the @code{(gnu services)} module also defines several essential |
| 7867 | service types, some of which are listed below. | 7872 | service types, some of which are listed below. |
| 7868 | 7873 | ||
| 7874 | @defvr {Scheme Variable} system-service-type | ||
| 7875 | This is the root of the service graph. It produces the system directory | ||
| 7876 | as returned by the @command{guix system build} command. | ||
| 7877 | @end defvr | ||
| 7878 | |||
| 7869 | @defvr {Scheme Variable} boot-service-type | 7879 | @defvr {Scheme Variable} boot-service-type |
| 7870 | The type of the ``boot service'', which is the root of the service | 7880 | The type of the ``boot service'', which produces the @dfn{boot script}. |
| 7871 | graph. | 7881 | The boot script is what the initial RAM disk runs when booting. |
| 7872 | @end defvr | 7882 | @end defvr |
| 7873 | 7883 | ||
| 7874 | @defvr {Scheme Variable} etc-service-type | 7884 | @defvr {Scheme Variable} etc-service-type |
diff --git a/doc/images/service-graph.dot b/doc/images/service-graph.dot index 3397b878e96..04f231bb098 100644 --- a/doc/images/service-graph.dot +++ b/doc/images/service-graph.dot | |||
| @@ -4,7 +4,8 @@ digraph "Service Type Dependencies" { | |||
| 4 | etc [shape = box, fontname = Helvetica]; | 4 | etc [shape = box, fontname = Helvetica]; |
| 5 | accounts [shape = box, fontname = Helvetica]; | 5 | accounts [shape = box, fontname = Helvetica]; |
| 6 | activation [shape = box, fontname = Helvetica]; | 6 | activation [shape = box, fontname = Helvetica]; |
| 7 | boot [shape = house, fontname = Helvetica]; | 7 | boot [shape = box, fontname = Helvetica]; |
| 8 | system [shape = house, fontname = Helvetica]; | ||
| 8 | lshd -> dmd; | 9 | lshd -> dmd; |
| 9 | lshd -> pam; | 10 | lshd -> pam; |
| 10 | udev -> dmd; | 11 | udev -> dmd; |
| @@ -32,4 +33,6 @@ digraph "Service Type Dependencies" { | |||
| 32 | guix -> dmd; | 33 | guix -> dmd; |
| 33 | guix -> activation; | 34 | guix -> activation; |
| 34 | guix -> accounts; | 35 | guix -> accounts; |
| 36 | boot -> system; | ||
| 37 | etc -> system; | ||
| 35 | } | 38 | } |
diff --git a/gnu/services.scm b/gnu/services.scm index ecf3532e52e..8a66d453dfd 100644 --- a/gnu/services.scm +++ b/gnu/services.scm | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | ambiguous-target-service-error-service | 60 | ambiguous-target-service-error-service |
| 61 | ambiguous-target-service-error-target-type | 61 | ambiguous-target-service-error-target-type |
| 62 | 62 | ||
| 63 | system-service-type | ||
| 63 | boot-service-type | 64 | boot-service-type |
| 64 | activation-service-type | 65 | activation-service-type |
| 65 | activation-service->script | 66 | activation-service->script |
| @@ -89,9 +90,10 @@ | |||
| 89 | ;;; by providing one procedure to compose extensions, and one procedure to | 90 | ;;; by providing one procedure to compose extensions, and one procedure to |
| 90 | ;;; extend itself. | 91 | ;;; extend itself. |
| 91 | ;;; | 92 | ;;; |
| 92 | ;;; A notable service type is BOOT-SERVICE-TYPE, which has a single instance, | 93 | ;;; A notable service type is SYSTEM-SERVICE-TYPE, which has a single |
| 93 | ;;; %BOOT-SERVICE. %BOOT-SERVICE constitutes the root of the service DAG. It | 94 | ;;; instance, which is the root of the service DAG. Its value is the |
| 94 | ;;; produces the boot script that the initrd loads. | 95 | ;;; derivation that produces the 'system' directory as returned by |
| 96 | ;;; 'operating-system-derivation'. | ||
| 95 | ;;; | 97 | ;;; |
| 96 | ;;; The 'fold-services' procedure can be passed a list of procedures, which it | 98 | ;;; The 'fold-services' procedure can be passed a list of procedures, which it |
| 97 | ;;; "folds" by propagating extensions down the graph; it returns the root | 99 | ;;; "folds" by propagating extensions down the graph; it returns the root |
| @@ -182,6 +184,25 @@ This is a shorthand for (map (lambda (svc) ...) %base-services)." | |||
| 182 | ;;; Core services. | 184 | ;;; Core services. |
| 183 | ;;; | 185 | ;;; |
| 184 | 186 | ||
| 187 | (define (system-derivation mentries mextensions) | ||
| 188 | "Return as a monadic value the derivation of the 'system' directory | ||
| 189 | containing the given entries." | ||
| 190 | (mlet %store-monad ((entries mentries) | ||
| 191 | (extensions (sequence %store-monad mextensions))) | ||
| 192 | (lower-object | ||
| 193 | (file-union "system" | ||
| 194 | (append entries (concatenate extensions)))))) | ||
| 195 | |||
| 196 | (define system-service-type | ||
| 197 | ;; This is the ultimate service type, the root of the service DAG. The | ||
| 198 | ;; service of this type is extended by monadic name/item pairs. These items | ||
| 199 | ;; end up in the "system directory" as returned by | ||
| 200 | ;; 'operating-system-derivation'. | ||
| 201 | (service-type (name 'system) | ||
| 202 | (extensions '()) | ||
| 203 | (compose identity) | ||
| 204 | (extend system-derivation))) | ||
| 205 | |||
| 185 | (define (compute-boot-script _ mexps) | 206 | (define (compute-boot-script _ mexps) |
| 186 | (mlet %store-monad ((gexps (sequence %store-monad mexps))) | 207 | (mlet %store-monad ((gexps (sequence %store-monad mexps))) |
| 187 | (gexp->file "boot" | 208 | (gexp->file "boot" |
| @@ -203,17 +224,25 @@ This is a shorthand for (map (lambda (svc) ...) %base-services)." | |||
| 203 | ;; Activate the system and spawn dmd. | 224 | ;; Activate the system and spawn dmd. |
| 204 | #$@gexps)))) | 225 | #$@gexps)))) |
| 205 | 226 | ||
| 227 | (define (boot-script-entry mboot) | ||
| 228 | "Return, as a monadic value, an entry for the boot script in the system | ||
| 229 | directory." | ||
| 230 | (mlet %store-monad ((boot mboot)) | ||
| 231 | (return `(("boot" ,boot))))) | ||
| 232 | |||
| 206 | (define boot-service-type | 233 | (define boot-service-type |
| 207 | ;; The service of this type is extended by being passed gexps as monadic | 234 | ;; The service of this type is extended by being passed gexps as monadic |
| 208 | ;; values. It aggregates them in a single script, as a monadic value, which | 235 | ;; values. It aggregates them in a single script, as a monadic value, which |
| 209 | ;; becomes its 'parameters'. It is the only service that extends nothing. | 236 | ;; becomes its 'parameters'. It is the only service that extends nothing. |
| 210 | (service-type (name 'boot) | 237 | (service-type (name 'boot) |
| 211 | (extensions '()) | 238 | (extensions |
| 239 | (list (service-extension system-service-type | ||
| 240 | boot-script-entry))) | ||
| 212 | (compose append) | 241 | (compose append) |
| 213 | (extend compute-boot-script))) | 242 | (extend compute-boot-script))) |
| 214 | 243 | ||
| 215 | (define %boot-service | 244 | (define %boot-service |
| 216 | ;; This is the ultimate service, the root of the service DAG. | 245 | ;; The service that produces the boot script. |
| 217 | (service boot-service-type #t)) | 246 | (service boot-service-type #t)) |
| 218 | 247 | ||
| 219 | (define* (file-union name files) ;FIXME: Factorize. | 248 | (define* (file-union name files) ;FIXME: Factorize. |
| @@ -351,6 +380,12 @@ ACTIVATION-SCRIPT-TYPE." | |||
| 351 | (define (files->etc-directory files) | 380 | (define (files->etc-directory files) |
| 352 | (file-union "etc" files)) | 381 | (file-union "etc" files)) |
| 353 | 382 | ||
| 383 | (define (etc-entry files) | ||
| 384 | "Return an entry for the /etc directory consisting of FILES in the system | ||
| 385 | directory." | ||
| 386 | (with-monad %store-monad | ||
| 387 | (return `(("etc" ,(files->etc-directory files)))))) | ||
| 388 | |||
| 354 | (define etc-service-type | 389 | (define etc-service-type |
| 355 | (service-type (name 'etc) | 390 | (service-type (name 'etc) |
| 356 | (extensions | 391 | (extensions |
| @@ -359,7 +394,8 @@ ACTIVATION-SCRIPT-TYPE." | |||
| 359 | (lambda (files) | 394 | (lambda (files) |
| 360 | (let ((etc | 395 | (let ((etc |
| 361 | (files->etc-directory files))) | 396 | (files->etc-directory files))) |
| 362 | #~(activate-etc #$etc)))))) | 397 | #~(activate-etc #$etc)))) |
| 398 | (service-extension system-service-type etc-entry))) | ||
| 363 | (compose concatenate) | 399 | (compose concatenate) |
| 364 | (extend append))) | 400 | (extend append))) |
| 365 | 401 | ||
| @@ -450,7 +486,8 @@ kernel." | |||
| 450 | (lambda (node) | 486 | (lambda (node) |
| 451 | (reverse (vhash-foldq* cons '() node edges))))) | 487 | (reverse (vhash-foldq* cons '() node edges))))) |
| 452 | 488 | ||
| 453 | (define* (fold-services services #:key (target-type boot-service-type)) | 489 | (define* (fold-services services |
| 490 | #:key (target-type system-service-type)) | ||
| 454 | "Fold SERVICES by propagating their extensions down to the root of type | 491 | "Fold SERVICES by propagating their extensions down to the root of type |
| 455 | TARGET-TYPE; return the root service adjusted accordingly." | 492 | TARGET-TYPE; return the root service adjusted accordingly." |
| 456 | (define dependents | 493 | (define dependents |
diff --git a/gnu/system.scm b/gnu/system.scm index 8fed857b399..c26d27028b0 100644 --- a/gnu/system.scm +++ b/gnu/system.scm | |||
| @@ -254,6 +254,24 @@ from the initrd." | |||
| 254 | "Return the list of swap services for OS." | 254 | "Return the list of swap services for OS." |
| 255 | (map swap-service (operating-system-swap-devices os))) | 255 | (map swap-service (operating-system-swap-devices os))) |
| 256 | 256 | ||
| 257 | (define* (operating-system-directory-base-entries os #:key container?) | ||
| 258 | "Return the basic entries of the 'system' directory of OS for use as the | ||
| 259 | value of the SYSTEM-SERVICE-TYPE service." | ||
| 260 | (mlet* %store-monad ((profile (operating-system-profile os)) | ||
| 261 | (locale (operating-system-locale-directory os))) | ||
| 262 | (if container? | ||
| 263 | (return `(("profile" ,profile) | ||
| 264 | ("locale" ,locale))) | ||
| 265 | (mlet %store-monad | ||
| 266 | ((kernel -> (operating-system-kernel os)) | ||
| 267 | (initrd (operating-system-initrd-file os)) | ||
| 268 | (params (operating-system-parameters-file os))) | ||
| 269 | (return `(("kernel" ,kernel) | ||
| 270 | ("parameters" ,params) | ||
| 271 | ("initrd" ,initrd) | ||
| 272 | ("profile" ,profile) | ||
| 273 | ("locale" ,locale))))))) ;used by libc | ||
| 274 | |||
| 257 | (define* (essential-services os #:key container?) | 275 | (define* (essential-services os #:key container?) |
| 258 | "Return the list of essential services for OS. These are special services | 276 | "Return the list of essential services for OS. These are special services |
| 259 | that implement part of what's declared in OS are responsible for low-level | 277 | that implement part of what's declared in OS are responsible for low-level |
| @@ -269,8 +287,11 @@ a container or that of a \"bare metal\" system." | |||
| 269 | (swaps (swap-services os)) | 287 | (swaps (swap-services os)) |
| 270 | (procs (user-processes-service | 288 | (procs (user-processes-service |
| 271 | (map service-parameters other-fs))) | 289 | (map service-parameters other-fs))) |
| 272 | (host-name (host-name-service (operating-system-host-name os)))) | 290 | (host-name (host-name-service (operating-system-host-name os))) |
| 273 | (cons* %boot-service | 291 | (entries (operating-system-directory-base-entries |
| 292 | os #:container? container?))) | ||
| 293 | (cons* (service system-service-type entries) | ||
| 294 | %boot-service | ||
| 274 | 295 | ||
| 275 | ;; %DMD-ROOT-SERVICE must come first so that the gexp that execs | 296 | ;; %DMD-ROOT-SERVICE must come first so that the gexp that execs |
| 276 | ;; dmd comes last in the boot script (XXX). | 297 | ;; dmd comes last in the boot script (XXX). |
| @@ -607,10 +628,17 @@ etc." | |||
| 607 | we're running in the final root. When CONTAINER? is true, skip all | 628 | we're running in the final root. When CONTAINER? is true, skip all |
| 608 | hardware-related operations as necessary when booting a Linux container." | 629 | hardware-related operations as necessary when booting a Linux container." |
| 609 | (let* ((services (operating-system-services os #:container? container?)) | 630 | (let* ((services (operating-system-services os #:container? container?)) |
| 610 | (boot (fold-services services))) | 631 | (boot (fold-services services #:target-type boot-service-type))) |
| 611 | ;; BOOT is the script as a monadic value. | 632 | ;; BOOT is the script as a monadic value. |
| 612 | (service-parameters boot))) | 633 | (service-parameters boot))) |
| 613 | 634 | ||
| 635 | (define* (operating-system-derivation os #:key container?) | ||
| 636 | "Return a derivation that builds OS." | ||
| 637 | (let* ((services (operating-system-services os #:container? container?)) | ||
| 638 | (system (fold-services services))) | ||
| 639 | ;; SYSTEM contains the derivation as a monadic value. | ||
| 640 | (service-parameters system))) | ||
| 641 | |||
| 614 | (define (operating-system-root-file-system os) | 642 | (define (operating-system-root-file-system os) |
| 615 | "Return the root file system of OS." | 643 | "Return the root file system of OS." |
| 616 | (find (match-lambda | 644 | (find (match-lambda |
| @@ -693,24 +721,4 @@ this file is the reconstruction of GRUB menu entries for old configurations." | |||
| 693 | #$(operating-system-kernel-arguments os)) | 721 | #$(operating-system-kernel-arguments os)) |
| 694 | (initrd #$initrd))))) | 722 | (initrd #$initrd))))) |
| 695 | 723 | ||
| 696 | (define (operating-system-derivation os) | ||
| 697 | "Return a derivation that builds OS." | ||
| 698 | (mlet* %store-monad | ||
| 699 | ((profile (operating-system-profile os)) | ||
| 700 | (etc -> (operating-system-etc-directory os)) | ||
| 701 | (boot (operating-system-boot-script os)) | ||
| 702 | (kernel -> (operating-system-kernel os)) | ||
| 703 | (initrd (operating-system-initrd-file os)) | ||
| 704 | (locale (operating-system-locale-directory os)) | ||
| 705 | (params (operating-system-parameters-file os))) | ||
| 706 | (lower-object | ||
| 707 | (file-union "system" | ||
| 708 | `(("boot" ,#~#$boot) | ||
| 709 | ("kernel" ,#~#$kernel) | ||
| 710 | ("parameters" ,#~#$params) | ||
| 711 | ("initrd" ,initrd) | ||
| 712 | ("profile" ,#~#$profile) | ||
| 713 | ("locale" ,#~#$locale) ;used by libc | ||
| 714 | ("etc" ,#~#$etc)))))) | ||
| 715 | |||
| 716 | ;;; system.scm ends here | 724 | ;;; system.scm ends here |
diff --git a/gnu/system/linux-container.scm b/gnu/system/linux-container.scm index c2eb773931d..4f38c5cb0aa 100644 --- a/gnu/system/linux-container.scm +++ b/gnu/system/linux-container.scm | |||
| @@ -47,20 +47,6 @@ | |||
| 47 | (check? #f) | 47 | (check? #f) |
| 48 | (create-mount-point? #t))))) | 48 | (create-mount-point? #t))))) |
| 49 | 49 | ||
| 50 | (define (system-container os) | ||
| 51 | "Return a derivation that builds OS as a Linux container." | ||
| 52 | (mlet* %store-monad | ||
| 53 | ((profile (operating-system-profile os)) | ||
| 54 | (etc -> (operating-system-etc-directory os)) | ||
| 55 | (boot (operating-system-boot-script os #:container? #t)) | ||
| 56 | (locale (operating-system-locale-directory os))) | ||
| 57 | (lower-object | ||
| 58 | (file-union "system-container" | ||
| 59 | `(("boot" ,#~#$boot) | ||
| 60 | ("profile" ,#~#$profile) | ||
| 61 | ("locale" ,#~#$locale) | ||
| 62 | ("etc" ,#~#$etc)))))) | ||
| 63 | |||
| 64 | (define (containerized-operating-system os mappings) | 50 | (define (containerized-operating-system os mappings) |
| 65 | "Return an operating system based on OS for use in a Linux container | 51 | "Return an operating system based on OS for use in a Linux container |
| 66 | environment. MAPPINGS is a list of <file-system-mapping> to realize in the | 52 | environment. MAPPINGS is a list of <file-system-mapping> to realize in the |
| @@ -95,7 +81,9 @@ that will be shared with the host system." | |||
| 95 | (operating-system-file-systems os))) | 81 | (operating-system-file-systems os))) |
| 96 | (specs (map file-system->spec file-systems))) | 82 | (specs (map file-system->spec file-systems))) |
| 97 | 83 | ||
| 98 | (mlet* %store-monad ((os-drv (system-container os))) | 84 | (mlet* %store-monad ((os-drv (operating-system-derivation |
| 85 | os | ||
| 86 | #:container? #t))) | ||
| 99 | 87 | ||
| 100 | (define script | 88 | (define script |
| 101 | #~(begin | 89 | #~(begin |
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm index 7be734785a1..7a8a751df98 100644 --- a/guix/scripts/system.scm +++ b/guix/scripts/system.scm | |||
| @@ -491,10 +491,10 @@ building anything." | |||
| 491 | (define (export-extension-graph os port) | 491 | (define (export-extension-graph os port) |
| 492 | "Export the service extension graph of OS to PORT." | 492 | "Export the service extension graph of OS to PORT." |
| 493 | (let* ((services (operating-system-services os)) | 493 | (let* ((services (operating-system-services os)) |
| 494 | (boot (find (lambda (service) | 494 | (system (find (lambda (service) |
| 495 | (eq? (service-kind service) boot-service-type)) | 495 | (eq? (service-kind service) system-service-type)) |
| 496 | services))) | 496 | services))) |
| 497 | (export-graph (list boot) (current-output-port) | 497 | (export-graph (list system) (current-output-port) |
| 498 | #:node-type (service-node-type services) | 498 | #:node-type (service-node-type services) |
| 499 | #:reverse-edges? #t))) | 499 | #:reverse-edges? #t))) |
| 500 | 500 | ||
