guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

03/03: system: image: Factorize image creation.


From: guix-commits
Subject: 03/03: system: image: Factorize image creation.
Date: Fri, 24 Apr 2020 13:16:54 -0400 (EDT)

mothacehe pushed a commit to branch wip-disk-image
in repository guix.

commit eb6bd610def3497cd6173dad718930bc9582687b
Author: Mathieu Othacehe <address@hidden>
AuthorDate: Fri Apr 24 19:16:25 2020 +0200

    system: image: Factorize image creation.
---
 gnu/system.scm       |  50 ++++++
 gnu/system/image.scm | 430 ++++++++++++++++++++++++++++-----------------------
 gnu/system/vm.scm    |  49 ------
 3 files changed, 283 insertions(+), 246 deletions(-)

diff --git a/gnu/system.scm b/gnu/system.scm
index d79ea23..3affa57 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -117,6 +117,7 @@
             operating-system-etc-directory
             operating-system-locale-directory
             operating-system-boot-script
+            operating-system-uuid
 
             system-linux-image-file-name
             operating-system-with-gc-roots
@@ -944,6 +945,55 @@ we're running in the final root."
                #:mapped-devices mapped-devices
                #:keyboard-layout (operating-system-keyboard-layout os)))
 
+(define* (operating-system-uuid os #:optional (type 'dce))
+  "Compute UUID object with a deterministic \"UUID\" for OS, of the given
+TYPE (one of 'iso9660 or 'dce).  Return a UUID object."
+  ;; Note: For this to be deterministic, we must not hash things that contains
+  ;; (directly or indirectly) procedures, for example.  That rules out
+  ;; anything that contains gexps, thunk or delayed record fields, etc.
+
+  (define service-name
+    (compose service-type-name service-kind))
+
+  (define (file-system-digest fs)
+    ;; Return a hashable digest that does not contain 'dependencies' since
+    ;; this field can contain procedures.
+    (let ((device (file-system-device fs)))
+      (list (file-system-mount-point fs)
+            (file-system-type fs)
+            (file-system-device->string device)
+            (file-system-options fs))))
+
+  (if (eq? type 'iso9660)
+      (let ((pad (compose (cut string-pad <> 2 #\0)
+                          number->string))
+            (h   (hash (map service-name (operating-system-services os))
+                       3600)))
+        (bytevector->uuid
+         (string->iso9660-uuid
+          (string-append "1970-01-01-"
+                         (pad (hash (operating-system-host-name os) 24)) "-"
+                         (pad (quotient h 60)) "-"
+                         (pad (modulo h 60)) "-"
+                         (pad (hash (map file-system-digest
+                                         (operating-system-file-systems os))
+                                    100))))
+         'iso9660))
+      (bytevector->uuid
+       (uint-list->bytevector
+        (list (hash (map file-system-digest
+                         (operating-system-file-systems os))
+                    (- (expt 2 32) 1))
+              (hash (operating-system-host-name os)
+                    (- (expt 2 32) 1))
+              (hash (map service-name (operating-system-services os))
+                    (- (expt 2 32) 1))
+              (hash (map file-system-digest (operating-system-file-systems os))
+                    (- (expt 2 32) 1)))
+        (endianness little)
+        4)
+       type)))
+
 (define (locale-name->definition* name)
   "Variant of 'locale-name->definition' that raises an error upon failure."
   (match (locale-name->definition name)
diff --git a/gnu/system/image.scm b/gnu/system/image.scm
index 9554239..64b5ce2 100644
--- a/gnu/system/image.scm
+++ b/gnu/system/image.scm
@@ -26,6 +26,7 @@
   #:use-module (gnu bootloader grub)
   #:use-module (gnu image)
   #:use-module (gnu services)
+  #:use-module (gnu services base)
   #:use-module (gnu system)
   #:use-module (gnu system file-systems)
   #:use-module (gnu system uuid)
@@ -40,7 +41,7 @@
   #:autoload   (gnu packages gnupg) (guile-gcrypt)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages mtools)
-  #:use-module ((srfi srfi-1) #:select (append-map remove))
+  #:use-module ((srfi srfi-1) #:select (append-map remove find))
   #:use-module (srfi srfi-26)
   #:use-module (rnrs bytevectors)
   #:use-module (ice-9 match)
@@ -50,8 +51,6 @@
             efi-disk-image
             iso9660-image
 
-            system-iso9660-image
-            system-disk-image
             system-image))
 
 
@@ -87,63 +86,27 @@
   (image
    (format 'iso9660)))
 
-(define root-iso-label
-  "GUIX_IMAGE")
-
-(define* (operating-system-uuid os #:optional (type 'dce))
-  "Compute UUID object with a deterministic \"UUID\" for OS, of the given
-TYPE (one of 'iso9660 or 'dce).  Return a UUID object."
-  ;; Note: For this to be deterministic, we must not hash things that contains
-  ;; (directly or indirectly) procedures, for example.  That rules out
-  ;; anything that contains gexps, thunk or delayed record fields, etc.
-
-  (define service-name
-    (compose service-type-name service-kind))
-
-  (define (file-system-digest fs)
-    ;; Return a hashable digest that does not contain 'dependencies' since
-    ;; this field can contain procedures.
-    (let ((device (file-system-device fs)))
-      (list (file-system-mount-point fs)
-            (file-system-type fs)
-            (file-system-device->string device)
-            (file-system-options fs))))
-
-  (if (eq? type 'iso9660)
-      (let ((pad (compose (cut string-pad <> 2 #\0)
-                          number->string))
-            (h   (hash (map service-name (operating-system-services os))
-                       3600)))
-        (bytevector->uuid
-         (string->iso9660-uuid
-          (string-append "1970-01-01-"
-                         (pad (hash (operating-system-host-name os) 24)) "-"
-                         (pad (quotient h 60)) "-"
-                         (pad (modulo h 60)) "-"
-                         (pad (hash (map file-system-digest
-                                         (operating-system-file-systems os))
-                                    100))))
-         'iso9660))
-      (bytevector->uuid
-       (uint-list->bytevector
-        (list (hash (map file-system-digest
-                         (operating-system-file-systems os))
-                    (- (expt 2 32) 1))
-              (hash (operating-system-host-name os)
-                    (- (expt 2 32) 1))
-              (hash (map service-name (operating-system-services os))
-                    (- (expt 2 32) 1))
-              (hash (map file-system-digest (operating-system-file-systems os))
-                    (- (expt 2 32) 1)))
-        (endianness little)
-        4)
-       type)))
-
-(define (root-iso-uuid os)
+
+;;
+;; Helpers.
+;;
+
+(define (root-label image)
+  (let ((label "Guix_image")
+        (format (image-format image)))
+    (if (eq? format 'iso9660)
+        (string-upcase label)
+        label)))
+
+(define (root-uuid image)
   ;; UUID of the root file system, computed in a deterministic fashion.
   ;; This is what we use to locate the root file system so it has to be
   ;; different from the user's own file system UUIDs.
-  (operating-system-uuid os 'iso9660))
+  (let ((os (image-operating-system image))
+        (type (if (eq? (image-format image) 'iso9660)
+                  'iso9660
+                  'dce)))
+    (operating-system-uuid os type)))
 
 (define not-config?
   ;; Select (guix …) and (gnu …) modules, except (guix config).
@@ -182,130 +145,136 @@ TYPE (one of 'iso9660 or 'dce).  Return a UUID object."
                        (guix build utils))
           exp ...))))
 
-(define (partition-image image partition)
-  (let* ((os (image-operating-system image))
-         (bootloader (bootloader-configuration-bootloader
-                      (operating-system-bootloader os)))
-         (bootcfg (operating-system-bootcfg os))
-         (inputs `(("system" ,os)
-                   ("bootcfg" ,bootcfg)))
-         (schema (local-file (search-path %load-path
-                                          "guix/store/schema.sql")))
-         (graph (match inputs
-                  (((names . _) ...)
-                   names)))
-         (root-builder
-          (with-imported-modules*
-           (let* ((initializer #$(partition-initializer partition)))
-             (sql-schema #$schema)
-
-             ;; Allow non-ASCII file names--e.g., 'nss-certs'--to be decoded.
-             (setenv "GUIX_LOCPATH"
-                     #+(file-append glibc-utf8-locales "/lib/locale"))
-             (setlocale LC_ALL "en_US.utf8")
-
-             (initializer #$output
-                          #:references-graphs '#$graph
-                          #:deduplicate? #f
-                          #:system-directory #$os
-                          #:bootloader-package
-                          #$(bootloader-package bootloader)
-                          #:bootcfg #$bootcfg
-                          #:bootcfg-location
-                          #$(bootloader-configuration-file bootloader)))))
-         (image-root
-          (computed-file "partition-image-root" root-builder
-                         #:options `(#:references-graphs ,inputs)))
-         (type (partition-file-system partition))
-         (image-builder
-          (with-imported-modules*
-           (let ((inputs '#$(list e2fsprogs ;mke2fs
-                                  dosfstools ;mkdosfs
-                                  mtools ;mcopy
-                                  )))
-             (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
-             (make-partition-image #$(partition->gexp partition)
-                                   #$output
-                                   #$image-root)))))
-    (computed-file "partition.img" image-builder)))
-
-(define genimage-name "image")
-
-(define (image->genimage-cfg image)
-  (define (format->image-type format)
-    (case format
-      ((disk-image) "hdimage")
-      (else
-       (error
-        (format #f "Unsupported image type ~a~%." format)))))
-
-  (define (partition->dos-type partition)
-    (let ((flags (partition-flags partition)))
-      (cond
-       ((member 'esp flags) "0xEF")
-       (else "0x83"))))
-
-  (define (partition->config partition)
-    (let ((label (partition-label partition))
-          (dos-type (partition->dos-type partition))
-          (image (partition-image image partition)))
-      #~(format #f "~/partition ~a {
+
+;;
+;; Disk image.
+;;
+
+(define* (system-disk-image image
+                            #:key
+                            (name "disk-image")
+                            label
+                            uuid
+                            bootcfg
+                            bootloader
+                            register-closures?
+                            (inputs '())
+                            (substitutable? #t))
+
+  (define genimage-name "image")
+
+  (define (image->genimage-cfg image)
+    (define (format->image-type format)
+      (case format
+        ((disk-image) "hdimage")
+        (else
+         (error
+          (format #f "Unsupported image type ~a~%." format)))))
+
+    (define (partition->dos-type partition)
+      (let ((flags (partition-flags partition)))
+        (cond
+         ((member 'esp flags) "0xEF")
+         (else "0x83"))))
+
+    (define (partition->config partition)
+      (let ((label (partition-label partition))
+            (dos-type (partition->dos-type partition))
+            (image (partition-image partition)))
+        #~(format #f "~/partition ~a {
 ~/~/partition-type = ~a
 ~/~/image = \"~a\"
 ~/}"  #$label #$dos-type #$image)))
 
-  (let* ((format (image-format image))
-         (image-type (format->image-type format))
-         (partitions (image-partitions image))
-         (partitions-config (map partition->config partitions))
-         (builder
-          #~(begin
-              (let ((format (@ (ice-9 format) format)))
-                (call-with-output-file #$output
-                  (lambda (port)
-                    (format port
-                            "\
+    (let* ((format (image-format image))
+           (image-type (format->image-type format))
+           (partitions (image-partitions image))
+           (partitions-config (map partition->config partitions))
+           (builder
+            #~(begin
+                (let ((format (@ (ice-9 format) format)))
+                  (call-with-output-file #$output
+                    (lambda (port)
+                      (format port
+                              "\
 image ~a {
 ~/~a {}
 ~{~a~^~%~}
 }~%" #$genimage-name #$image-type (list #$@partitions-config))))))))
-    (computed-file "genimage.cfg" builder)))
+      (computed-file "genimage.cfg" builder)))
 
-(define (system-iso9660-image image)
-  (let* ((image-os (image-operating-system image))
-         (file-systems-to-keep
-          (remove (lambda (fs)
-                    (string=? (file-system-mount-point fs) "/"))
-                  (operating-system-file-systems image-os)))
-         (os (operating-system
-               (inherit image-os)
-               (initrd (lambda (file-systems . rest)
-                         (apply (operating-system-initrd image-os)
-                                file-systems
-                                #:volatile-root? #t
-                                rest)))
-               (bootloader (bootloader-configuration
-                            (inherit (operating-system-bootloader
-                                      image-os))
-                            (bootloader grub-mkrescue-bootloader)))
-               (file-systems (cons (file-system
-                                     (mount-point "/")
-                                     (device "/dev/placeholder")
-                                     (type "iso9660"))
-                                   file-systems-to-keep))))
-         (uuid (root-iso-uuid os))
-         (os (operating-system
-               (inherit os)
-               (file-systems (cons (file-system
-                                     (mount-point "/")
-                                     (device uuid)
-                                     (type "iso9660"))
-                                   file-systems-to-keep))))
-         (bootloader (bootloader-configuration-bootloader
-                      (operating-system-bootloader os)))
-         (bootcfg (operating-system-bootcfg os))
-         (inputs `(("system" ,os)
-                   ("bootcfg" ,bootcfg)))
+  (define (partition-image partition)
+    (let* ((os (image-operating-system image))
+           (schema (local-file (search-path %load-path
+                                            "guix/store/schema.sql")))
+           (graph (match inputs
+                    (((names . _) ...)
+                     names)))
+           (root-builder
+            (with-imported-modules*
+             (let* ((initializer #$(partition-initializer partition)))
+               (sql-schema #$schema)
+
+               ;; Allow non-ASCII file names--e.g., 'nss-certs'--to be decoded.
+               (setenv "GUIX_LOCPATH"
+                       #+(file-append glibc-utf8-locales "/lib/locale"))
+               (setlocale LC_ALL "en_US.utf8")
+
+               (initializer #$output
+                            #:references-graphs '#$graph
+                            #:deduplicate? #f
+                            #:system-directory #$os
+                            #:bootloader-package #$bootloader
+                            #:bootcfg #$bootcfg
+                            #:bootcfg-location
+                            #$(bootloader-configuration-file bootloader)))))
+           (image-root
+            (computed-file "partition-image-root" root-builder
+                           #:options `(#:references-graphs ,inputs)))
+           (type (partition-file-system partition))
+           (image-builder
+            (with-imported-modules*
+             (let ((inputs '#$(list e2fsprogs dosfstools mtools)))
+               (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
+               (make-partition-image #$(partition->gexp partition)
+                                     #$output
+                                     #$image-root)))))
+      (computed-file "partition.img" image-builder)))
+
+  (let* ((builder
+          (with-imported-modules*
+           (let ((inputs '#$(list genimage coreutils findutils)))
+             (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
+             (genimage #$(image->genimage-cfg image) #$output))))
+         (image-dir (computed-file "image-dir" builder)))
+    (gexp->derivation "image"
+                      #~(symlink
+                         (string-append #$image-dir "/" #$genimage-name)
+                         #$output))))
+
+
+;;
+;; ISO9660 image.
+;;
+
+(define (has-guix-service-type? os)
+  "Return true if OS contains a service of the type GUIX-SERVICE-TYPE."
+  (not (not (find (lambda (service)
+                     (eq? (service-kind service) guix-service-type))
+                   (operating-system-services os)))))
+
+(define* (system-iso9660-image image
+                               #:key
+                               (name "iso9660-image")
+                               label
+                               uuid
+                               bootcfg
+                               bootloader
+                               register-closures?
+                               (inputs '())
+                               (grub-mkrescue-environment '())
+                               (substitutable? #t))
+  (let* ((os (image-operating-system image))
          (schema (local-file (search-path %load-path
                                           "guix/store/schema.sql")))
          (graph (match inputs
@@ -333,39 +302,106 @@ image ~a {
                                    sed grep coreutils findutils gawk)))
              (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
              (make-iso9660-image #$xorriso
-                                 '(("MKRESCUE_SED_MODE" . "mbr_hfs"))
-                                 #$(bootloader-package bootloader)
+                                 '#$grub-mkrescue-environment
+                                 #$bootloader
                                  #$bootcfg
                                  #$os
                                  #$image-root
                                  #$output
                                  #:references-graphs '#$graph
-                                 #:register-closures? #t
+                                 #:register-closures? #$register-closures?
                                  #:compression? #f
-                                 #:volume-id #$root-iso-label
+                                 #:volume-id #$label
                                  #:volume-uuid #$(and=> uuid
                                                         uuid-bytevector))))))
-    (gexp->derivation "iso.img" builder
+    (gexp->derivation name builder
                       #:references-graphs inputs)))
 
-(define* (system-disk-image image)
-  (let* ((builder
-          (with-imported-modules*
-           (let ((inputs '#$(list genimage ;genimage
-                                  coreutils ;rm
-                                  findutils ;find
-                                  )))
-             (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
-             (genimage #$(image->genimage-cfg image) #$output))))
-         (image-dir (computed-file "image-dir" builder)))
-    (gexp->derivation "image"
-                      #~(symlink
-                         (string-append #$image-dir "/" #$genimage-name)
-                         #$output))))
+
+;;
+;; Image creation.
+;;
+
+(define (image->root-file-system image)
+  (define (find-root-partition)
+    (let ((partitions (image-partitions image)))
+      (find (lambda (partition)
+              (member (partition-flags partition) 'boot))
+            partitions)))
+
+  (let ((format (image-format image)))
+    (if (eq? format 'iso9660)
+        "iso9660"
+        (partition-file-system (find-root-partition)))))
 
-(define (system-image image)
-  (case (image-format image)
-    ((disk-image)
-     (system-disk-image image))
-    ((iso9660)
-     (system-iso9660-image image))))
+(define-syntax-rule (image-with-os base-image os)
+  (image
+   (inherit base-image)
+   (operating-system os)))
+
+(define* (system-image image
+                       #:key
+                       (substitutable? #t))
+  (let* ((image-os (image-operating-system image))
+         (format (image-format image))
+         (file-systems-to-keep
+          (remove (lambda (fs)
+                    (string=? (file-system-mount-point fs) "/"))
+                  (operating-system-file-systems image-os)))
+         (root-file-system-type (image->root-file-system image))
+         (os (operating-system
+               (inherit image-os)
+               (initrd (lambda (file-systems . rest)
+                         (apply (operating-system-initrd image-os)
+                                file-systems
+                                #:volatile-root? #t
+                                rest)))
+               (bootloader (if (eq? format 'iso9660)
+                               (bootloader-configuration
+                                (inherit
+                                 (operating-system-bootloader image-os))
+                                 (bootloader grub-mkrescue-bootloader))
+                               (operating-system-bootloader image-os)))
+               (file-systems (cons (file-system
+                                     (mount-point "/")
+                                     (device "/dev/placeholder")
+                                     (type root-file-system-type))
+                                   file-systems-to-keep))))
+         (uuid (root-uuid image))
+         (label (root-label image))
+         (os (operating-system
+               (inherit os)
+               (file-systems (cons (file-system
+                                     (mount-point "/")
+                                     (device uuid)
+                                     (type root-file-system-type))
+                                   file-systems-to-keep))))
+         (image* (image-with-os image os))
+         (register-closures? (has-guix-service-type? os))
+         (bootcfg (operating-system-bootcfg os))
+         (bootloader (bootloader-package
+                      (bootloader-configuration-bootloader
+                       (operating-system-bootloader os)))))
+    (case (image-format image)
+      ((disk-image)
+       (system-disk-image image*
+                          #:label label
+                          #:uuid uuid
+                          #:bootcfg bootcfg
+                          #:bootloader bootloader
+                          #:register-closures? register-closures?
+                          #:inputs `(("system" ,os)
+                                     ("bootcfg" ,bootcfg))
+                          #:substitutable? substitutable?))
+      ((iso9660)
+       (system-iso9660-image image*
+                             #:label label
+                             #:uuid uuid
+                             #:bootcfg bootcfg
+                             #:bootloader bootloader
+                             #:register-closures? register-closures?
+                             #:inputs `(("system" ,os)
+                                        ("bootcfg" ,bootcfg))
+                             #:grub-mkrescue-environment
+                             '(("MKRESCUE_SED_MODE" . "mbr_hfs"))
+                             #:substitutable? substitutable?)))))
diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm
index c9741fb..78f6f2d 100644
--- a/gnu/system/vm.scm
+++ b/gnu/system/vm.scm
@@ -606,55 +606,6 @@ system."
 ;;; VM and disk images.
 ;;;
 
-(define* (operating-system-uuid os #:optional (type 'dce))
-  "Compute UUID object with a deterministic \"UUID\" for OS, of the given
-TYPE (one of 'iso9660 or 'dce).  Return a UUID object."
-  ;; Note: For this to be deterministic, we must not hash things that contains
-  ;; (directly or indirectly) procedures, for example.  That rules out
-  ;; anything that contains gexps, thunk or delayed record fields, etc.
-
-  (define service-name
-    (compose service-type-name service-kind))
-
-  (define (file-system-digest fs)
-    ;; Return a hashable digest that does not contain 'dependencies' since
-    ;; this field can contain procedures.
-    (let ((device (file-system-device fs)))
-      (list (file-system-mount-point fs)
-            (file-system-type fs)
-            (file-system-device->string device)
-            (file-system-options fs))))
-
-  (if (eq? type 'iso9660)
-      (let ((pad (compose (cut string-pad <> 2 #\0)
-                          number->string))
-            (h   (hash (map service-name (operating-system-services os))
-                       3600)))
-        (bytevector->uuid
-         (string->iso9660-uuid
-          (string-append "1970-01-01-"
-                         (pad (hash (operating-system-host-name os) 24)) "-"
-                         (pad (quotient h 60)) "-"
-                         (pad (modulo h 60)) "-"
-                         (pad (hash (map file-system-digest
-                                         (operating-system-file-systems os))
-                                    100))))
-         'iso9660))
-      (bytevector->uuid
-       (uint-list->bytevector
-        (list (hash (map file-system-digest
-                         (operating-system-file-systems os))
-                    (- (expt 2 32) 1))
-              (hash (operating-system-host-name os)
-                    (- (expt 2 32) 1))
-              (hash (map service-name (operating-system-services os))
-                    (- (expt 2 32) 1))
-              (hash (map file-system-digest (operating-system-file-systems os))
-                    (- (expt 2 32) 1)))
-        (endianness little)
-        4)
-       type)))
-
 (define* (system-disk-image-in-vm os
                                   #:key
                                   (name "disk-image")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]