summary refs log tree commit diff
path: root/gnu/system/vm.scm
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/system/vm.scm')
-rw-r--r--gnu/system/vm.scm487
1 files changed, 2 insertions, 485 deletions
diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm
index db5c4132c0..3370df1c81 100644
--- a/gnu/system/vm.scm
+++ b/gnu/system/vm.scm
@@ -35,7 +35,7 @@
   #:use-module (guix base32)
   #:use-module ((guix self) #:select (make-config.scm))
 
-  #:use-module ((gnu build vm)
+  #:use-module ((gnu build marionette)
                 #:select (qemu-command))
   #:use-module (gnu packages base)
   #:use-module (gnu packages bootloaders)
@@ -67,13 +67,8 @@
   #:use-module (rnrs bytevectors)
   #:use-module (ice-9 match)
 
-  #:export (expression->derivation-in-linux-vm
-            qemu-image
-            virtualized-operating-system
-
-            system-qemu-image/shared-store
+  #:export (virtualized-operating-system
             system-qemu-image/shared-store-script
-            system-docker-image
 
             virtual-machine
             virtual-machine?))
@@ -126,444 +121,6 @@
                            %default-msize-value))
           (check? #f))))
 
-(define not-config?
-  ;; Select (guix …) and (gnu …) modules, except (guix config).
-  (match-lambda
-    (('guix 'config) #f)
-    (('guix rest ...) #t)
-    (('gnu rest ...) #t)
-    (rest #f)))
-
-(define gcrypt-sqlite3&co
-  ;; Guile-Gcrypt, Guile-SQLite3, and their propagated inputs.
-  (append-map (lambda (package)
-                (cons package
-                      (match (package-transitive-propagated-inputs package)
-                        (((labels packages) ...)
-                         packages))))
-              (list guile-gcrypt guile-sqlite3)))
-
-(define* (expression->derivation-in-linux-vm name exp
-                                             #:key
-                                             (system (%current-system))
-                                             (linux linux-libre)
-                                             initrd
-                                             (qemu qemu-minimal)
-                                             (env-vars '())
-                                             (guile-for-build
-                                              (%guile-for-build))
-                                             (file-systems
-                                              %linux-vm-file-systems)
-
-                                             (single-file-output? #f)
-                                             (make-disk-image? #f)
-                                             (references-graphs #f)
-                                             (memory-size 256)
-                                             (disk-image-format "qcow2")
-                                             (disk-image-size 'guess)
-
-                                             (substitutable? #t))
-  "Evaluate EXP in a QEMU virtual machine running LINUX with INITRD (a
-derivation).  The virtual machine runs with MEMORY-SIZE MiB of memory.  In the
-virtual machine, EXP has access to FILE-SYSTEMS, which, by default, includes a
-9p share of the store, the '/xchg' where EXP should put its output file(s),
-and a 9p share of /tmp.
-
-If SINGLE-FILE-OUTPUT? is true, copy a single file from '/xchg' to OUTPUT.
-Otherwise, copy the contents of /xchg to a new directory OUTPUT.
-
-When MAKE-DISK-IMAGE? is true, then create a QEMU disk image of type
-DISK-IMAGE-FORMAT (e.g., 'qcow2' or 'raw'), of DISK-IMAGE-SIZE bytes and
-return it.  When DISK-IMAGE-SIZE is 'guess, estimate the image size based
-based on the size of the closure of REFERENCES-GRAPHS.
-
-When REFERENCES-GRAPHS is true, it must be a list of file name/store path
-pairs, as for `derivation'.  The files containing the reference graphs are
-made available under the /xchg CIFS share.
-
-SUBSTITUTABLE? determines whether the returned derivation should be marked as
-substitutable."
-  (define user-builder
-    (program-file "builder-in-linux-vm" exp))
-
-  (define loader
-    ;; Invoke USER-BUILDER instead using 'primitive-load'.  The reason for
-    ;; this is to allow USER-BUILDER to dlopen stuff by using a full-featured
-    ;; Guile, which it couldn't do using the statically-linked guile used in
-    ;; the initrd.  See example at
-    ;; <https://lists.gnu.org/archive/html/guix-devel/2017-10/msg00233.html>.
-    (program-file "linux-vm-loader"
-                  ;; Communicate USER-BUILDER's exit status via /xchg so that
-                  ;; the host can distinguish between success, failure, and
-                  ;; kernel panic.
-                  #~(let ((status (system* #$user-builder)))
-                      (call-with-output-file "/xchg/.exit-status"
-                        (lambda (port)
-                          (write status port)))
-                      (sync)
-                      (reboot))))
-
-  (define-syntax-rule (check predicate)
-    (let-system (system target)
-      (predicate (or target system))))
-
-  (let ((initrd (or initrd
-                    (base-initrd file-systems
-                                 #:on-error 'backtrace
-                                 #:linux linux
-                                 #:linux-modules %base-initrd-modules
-                                 #:qemu-networking? #t))))
-
-    (define builder
-      ;; Code that launches the VM that evaluates EXP.
-      (with-extensions gcrypt-sqlite3&co
-        (with-imported-modules `(,@(source-module-closure
-                                    '((guix build utils)
-                                      (gnu build vm))
-                                    #:select? not-config?)
-
-                                 ;; For consumption by (gnu store database).
-                                 ((guix config) => ,(make-config.scm)))
-          #~(begin
-              (use-modules (guix build utils)
-                           (gnu build vm))
-
-              ;; Allow non-ASCII file names--e.g., 'nss-certs'--to be decoded
-              ;; by 'estimated-partition-size' below.
-              (setenv "GUIX_LOCPATH"
-                      #+(file-append glibc-utf8-locales "/lib/locale"))
-              (setlocale LC_ALL "en_US.utf8")
-
-              (let* ((native-inputs
-                      '#+(list qemu (canonical-package coreutils)))
-                     (linux   (string-append
-                               #+linux "/"
-                               #+(system-linux-image-file-name system)))
-                     (initrd  #+initrd)
-                     (loader  #+loader)
-                     (graphs  '#$(match references-graphs
-                                   (((graph-files . _) ...) graph-files)
-                                   (_ #f)))
-                     (target  #$(let-system (system target)
-                                  (or target system)))
-                     (size    #$(if (eq? 'guess disk-image-size)
-                                    #~(+ (* 70 (expt 2 20)) ;ESP
-                                         (estimated-partition-size graphs))
-                                    disk-image-size)))
-
-                (set-path-environment-variable "PATH" '("bin") native-inputs)
-
-                (load-in-linux-vm loader
-                                  #:output #$output
-                                  #:linux linux #:initrd initrd
-                                  #:qemu (qemu-command target)
-                                  #:memory-size #$memory-size
-                                  #:make-disk-image? #$make-disk-image?
-                                  #:single-file-output? #$single-file-output?
-                                  #:disk-image-format #$disk-image-format
-                                  #:disk-image-size size
-                                  #:references-graphs graphs))))))
-
-    (gexp->derivation name builder
-                      ;; TODO: Require the "kvm" feature.
-                      #:system system
-                      #:target #f             ;EXP is always executed natively
-                      #:env-vars env-vars
-                      #:guile-for-build guile-for-build
-                      #:references-graphs references-graphs
-                      #:substitutable? substitutable?)))
-
-(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* (qemu-image #:key
-                     (name "qemu-image")
-                     (system (%current-system))
-                     (target (%current-target-system))
-                     (qemu qemu-minimal)
-                     (disk-image-size 'guess)
-                     (disk-image-format "qcow2")
-                     (file-system-type "ext4")
-                     (file-system-options '())
-                     (device-nodes 'linux)
-                     (extra-directives '())
-                     file-system-label
-                     file-system-uuid
-                     os
-                     bootcfg-drv
-                     bootloader
-                     (register-closures? (has-guix-service-type? os))
-                     (inputs '())
-                     copy-inputs?
-                     (substitutable? #t))
-  "Return a bootable, stand-alone QEMU image of type DISK-IMAGE-FORMAT (e.g.,
-'qcow2' or 'raw'), with a root partition of type FILE-SYSTEM-TYPE.
-Optionally, FILE-SYSTEM-LABEL can be specified as the volume name for the root
-partition; likewise FILE-SYSTEM-UUID, if true, specifies the UUID of the root
-partition (a UUID object).  FILE-SYSTEM-OPTIONS is an optional list of
-command-line options passed to 'mkfs.ext4' (or similar).
-
-The returned image is a full disk image that runs OS-DERIVATION,
-with a GRUB installation that uses GRUB-CONFIGURATION as its configuration
-file (GRUB-CONFIGURATION must be the name of a file in the VM.)
-
-INPUTS is a list of inputs (as for packages).  When COPY-INPUTS? is true, copy
-all of INPUTS into the image being built.  When REGISTER-CLOSURES? is true,
-register INPUTS in the store database of the image so that Guix can be used in
-the image.  By default, REGISTER-CLOSURES? is set to true only if a service of
-type GUIX-SERVICE-TYPE is present in the services definition of the operating
-system.
-
-When DEVICE-NODES is 'linux, create Linux-device block and character devices
-under /dev.  When it is 'hurd, do Hurdish things.
-
-EXTRA-DIRECTIVES is an optional list of directives to populate the root file
-system that is passed to 'populate-root-file-system'."
-  (define schema
-    (and register-closures?
-         (local-file (search-path %load-path
-                                  "guix/store/schema.sql"))))
-
-  (define preserve-target
-    (if target
-        (lambda (obj)
-          (with-parameters ((%current-target-system target))
-            obj))
-        identity))
-
-  (define inputs*
-    (map (match-lambda
-           ((name thing)
-            `(,name ,(preserve-target thing)))
-           ((name thing output)
-            `(,name ,(preserve-target thing) ,output)))
-         inputs))
-
-  (expression->derivation-in-linux-vm
-   name
-   (with-extensions gcrypt-sqlite3&co
-     (with-imported-modules `(,@(source-module-closure '((gnu build vm)
-                                                         (gnu build bootloader)
-                                                         (gnu build hurd-boot)
-                                                         (guix store database)
-                                                         (guix build utils))
-                                                       #:select? not-config?)
-                              ((guix config) => ,(make-config.scm)))
-       #~(begin
-           (use-modules (gnu build bootloader)
-                        (gnu build vm)
-                        ((gnu build hurd-boot)
-                         #:select (make-hurd-device-nodes))
-                        ((gnu build linux-boot)
-                         #:select (make-essential-device-nodes))
-                        (guix store database)
-                        (guix build utils)
-                        (srfi srfi-26)
-                        (ice-9 binary-ports))
-
-           (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")
-
-           (let ((inputs
-                  '#+(append (list parted e2fsprogs dosfstools)
-                             (map canonical-package
-                                  (list sed grep coreutils findutils gawk))))
-
-                 ;; This variable is unused but allows us to add INPUTS-TO-COPY
-                 ;; as inputs.
-                 (to-register
-                  '#$(map (match-lambda
-                            ((name thing) thing)
-                            ((name thing output) `(,thing ,output)))
-                          inputs*)))
-
-             (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
-
-             (let* ((graphs     '#$(match inputs
-                                     (((names . _) ...)
-                                      names)))
-                    (initialize (root-partition-initializer
-                                 #:extra-directives '#$extra-directives
-                                 #:closures graphs
-                                 #:copy-closures? #$copy-inputs?
-                                 #:register-closures? #$register-closures?
-                                 #:system-directory #$(preserve-target os)
-
-                                 #:make-device-nodes
-                                 #$(match device-nodes
-                                     ('linux #~make-essential-device-nodes)
-                                     ('hurd #~make-hurd-device-nodes))
-
-                                 ;; Disable deduplication to speed things up,
-                                 ;; and because it doesn't help much for a
-                                 ;; single system generation.
-                                 #:deduplicate? #f))
-                    (root-size  #$(if (eq? 'guess disk-image-size)
-                                      #~(max
-                                         ;; Minimum 20 MiB root size
-                                         (* 20 (expt 2 20))
-                                         (estimated-partition-size
-                                          (map (cut string-append "/xchg/" <>)
-                                               graphs)))
-                                      (- disk-image-size
-                                         (* 50 (expt 2 20)))))
-                    (partitions
-                     (append
-                      (list (partition
-                             (size root-size)
-                             (label #$file-system-label)
-                             (uuid #$(and=> file-system-uuid
-                                            uuid-bytevector))
-                             (file-system #$file-system-type)
-                             (file-system-options '#$file-system-options)
-                             (flags '(boot))
-                             (initializer initialize)))
-                      ;; Append a small EFI System Partition for use with UEFI
-                      ;; bootloaders if we are not targeting ARM because UEFI
-                      ;; support in U-Boot is experimental.
-                      ;;
-                      ;; FIXME: ‘target-arm?’ may be not operate on the right
-                      ;; system/target values.  Rewrite using ‘let-system’ when
-                      ;; available.
-                      (if #$(target-arm?)
-                          '()
-                          (list (partition
-                                 ;; The standalone grub image is about 10MiB, but
-                                 ;; leave some room for custom or multiple images.
-                                 (size (* 40 (expt 2 20)))
-                                 (label "GNU-ESP") ;cosmetic only
-                                 ;; Use "vfat" here since this property is used
-                                 ;; when mounting. The actual FAT-ness is based
-                                 ;; on file system size (16 in this case).
-                                 (file-system "vfat")
-                                 (flags '(esp)))))))
-                    (grub-efi #$(and (not (target-arm?)) grub-efi)))
-               (initialize-hard-disk "/dev/vda"
-                                     #:partitions partitions
-                                     #:grub-efi grub-efi
-                                     #:bootloader-package
-                                     #+(bootloader-package bootloader)
-                                     #:bootcfg #$(preserve-target bootcfg-drv)
-                                     #:bootcfg-location
-                                     #$(bootloader-configuration-file bootloader)
-                                     #:bootloader-installer
-                                     #+(bootloader-installer bootloader)))))))
-   #:system system
-   #:make-disk-image? #t
-   #:disk-image-size disk-image-size
-   #:disk-image-format disk-image-format
-   #:references-graphs inputs*
-   #:substitutable? substitutable?))
-
-(define* (system-docker-image os
-                              #:key
-                              (name "guix-docker-image")
-                              (memory-size 256)
-                              (register-closures? (has-guix-service-type? os))
-                              shared-network?)
-  "Build a docker image.  OS is the desired <operating-system>.  NAME is the
-base name to use for the output file.  When SHARED-NETWORK? is true, assume
-that the container will share network with the host and thus doesn't need a
-DHCP client, nscd, and so on.
-
-When REGISTER-CLOSURES? is true, register the closure of OS with Guix in the
-resulting Docker image.  By default, REGISTER-CLOSURES? is set to true only if
-a service of type GUIX-SERVICE-TYPE is present in the services definition of
-the operating system."
-  (define schema
-    (and register-closures?
-         (local-file (search-path %load-path
-                                  "guix/store/schema.sql"))))
-
-  (define boot-program
-    ;; Program that runs the boot script of OS, which in turn starts shepherd.
-    (program-file "boot-program"
-                  #~(let ((system (cadr (command-line))))
-                      (setenv "GUIX_NEW_SYSTEM" system)
-                      (execl #$(file-append guile-3.0 "/bin/guile")
-                             "guile" "--no-auto-compile"
-                             (string-append system "/boot")))))
-
-
-  (let ((os    (operating-system-with-gc-roots
-                (containerized-operating-system os '()
-                                                #:shared-network?
-                                                shared-network?)
-                (list boot-program)))
-        (name  (string-append name ".tar.gz"))
-        (graph "system-graph"))
-    (define build
-      (with-extensions (cons guile-json-3         ;for (guix docker)
-                             gcrypt-sqlite3&co)   ;for (guix store database)
-        (with-imported-modules `(,@(source-module-closure
-                                    '((guix docker)
-                                      (guix store database)
-                                      (guix build utils)
-                                      (guix build store-copy)
-                                      (gnu build vm))
-                                    #:select? not-config?)
-                                 ((guix config) => ,(make-config.scm)))
-          #~(begin
-              (use-modules (guix docker)
-                           (guix build utils)
-                           (gnu build vm)
-                           (srfi srfi-19)
-                           (guix build store-copy)
-                           (guix store database))
-
-              ;; Set the SQL schema location.
-              (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")
-
-              (let* (;; This initializer requires elevated privileges that are
-                     ;; not normally available in the build environment (e.g.,
-                     ;; it needs to create device nodes).  In order to obtain
-                     ;; such privileges, we run it as root in a VM.
-                     (initialize (root-partition-initializer
-                                  #:closures '(#$graph)
-                                  #:register-closures? #$register-closures?
-                                  #:system-directory #$os
-                                  ;; De-duplication would fail due to
-                                  ;; cross-device link errors, so don't do it.
-                                  #:deduplicate? #f))
-                     ;; Even as root in a VM, the initializer would fail due to
-                     ;; lack of privileges if we use a root-directory that is on
-                     ;; a file system that is shared with the host (e.g., /tmp).
-                     (root-directory "/guix-system-root"))
-                (set-path-environment-variable "PATH" '("bin" "sbin") '(#+tar))
-                (mkdir root-directory)
-                (initialize root-directory)
-                (build-docker-image
-                 (string-append "/xchg/" #$name) ;; The output file.
-                 (cons* root-directory
-                        (map store-info-item
-                             (call-with-input-file
-                                 (string-append "/xchg/" #$graph)
-                               read-reference-graph)))
-                 #$os
-                 #:entry-point '(#$boot-program #$os)
-                 #:compressor '(#+(file-append gzip "/bin/gzip") "-9n")
-                 #:creation-time (make-time time-utc 0 1)
-                 #:transformations `((,root-directory -> ""))))))))
-
-    (expression->derivation-in-linux-vm
-     name build
-     #:memory-size memory-size
-     #:make-disk-image? #f
-     #:single-file-output? #t
-     #:references-graphs `((,graph ,os)))))
-
 
 ;;;
 ;;; VMs that share file systems with the host.
@@ -655,46 +212,6 @@ environment with the store shared with the host.  MAPPINGS is a list of
                          (needed-for-boot? #t))
                        virtual-file-systems)))))
 
-(define* (system-qemu-image/shared-store
-          os
-          #:key
-          (system (%current-system))
-          (target (%current-target-system))
-          full-boot?
-          (disk-image-size (* (if full-boot? 500 30) (expt 2 20))))
-  "Return a derivation that builds a QEMU image of OS that shares its store
-with the host.
-
-When FULL-BOOT? is true, return an image that does a complete boot sequence,
-bootloaded included; thus, make a disk image that contains everything the
-bootloader refers to: OS kernel, initrd, bootloader data, etc."
-  (define root-uuid
-    ;; Use a fixed UUID to improve determinism.
-    (operating-system-uuid os 'dce))
-
-  (define bootcfg
-    (operating-system-bootcfg os))
-
-  ;; XXX: When FULL-BOOT? is true, we end up creating an image that contains
-  ;; BOOTCFG and all its dependencies, including the output of OS.
-  ;; This is more than needed (we only need the kernel, initrd, GRUB for its
-  ;; font, and the background image), but it's hard to filter that.
-  (qemu-image #:os os
-              #:system system
-              #:target target
-              #:bootcfg-drv bootcfg
-              #:bootloader (bootloader-configuration-bootloader
-                            (operating-system-bootloader os))
-              #:disk-image-size disk-image-size
-              #:file-system-uuid root-uuid
-              #:inputs (if full-boot?
-                           `(("bootcfg" ,bootcfg))
-                           '())
-
-              ;; XXX: Passing #t here is too slow, so let it off by default.
-              #:register-closures? #f
-              #:copy-inputs? full-boot?))
-
 (define* (common-qemu-options image shared-fs
                               #:key rw-image?)
   "Return the a string-value gexp with the common QEMU options to boot IMAGE,