Skip to content
Snippets Groups Projects
Commit 150e20dd authored by Ludovic Courtès's avatar Ludovic Courtès
Browse files

vm: Support initialization of the store DB when the store is shared.

* gnu/system/vm.scm (qemu-image): Rename #:inputs-to-copy to #:inputs,
  and #:initialize-store? to #:register-closures?.  Add #:copy-inputs?.
  Adjust build gexp accordingly.
  (system-qemu-image): Remove #:initialize-store? argument and add
  #:copy-inputs?.
  (system-qemu-image/shared-store): Add #:inputs, #:register-closures?,
  and #:copy-inputs? arguments.
* guix/build/vm.scm (register-closure): New procedure.
  (MS_BIND): New variable.
  (initialize-hard-disk): Rename #:initialize-store? to
  #:register-closures?, #:closures-to-copy to #:closures, and add
  #:copy-closures?.
  Add 'target-directory' and 'target-store' variables.
  Call 'populate-store' only when COPY-CLOSURES?.
  Bind-mount the store to TARGET-STORE when REGISTER-CLOSURES? and not
  COPY-CLOSURES?.  Add call to 'register-closure'.
parent c336a66f
No related branches found
No related tags found
No related merge requests found
...@@ -192,25 +192,26 @@ (define* (qemu-image #:key ...@@ -192,25 +192,26 @@ (define* (qemu-image #:key
(disk-image-size (* 100 (expt 2 20))) (disk-image-size (* 100 (expt 2 20)))
(file-system-type "ext4") (file-system-type "ext4")
grub-configuration grub-configuration
(initialize-store? #f) (register-closures? #t)
(populate #f) (populate #f)
(inputs-to-copy '())) (inputs '())
copy-inputs?)
"Return a bootable, stand-alone QEMU image, with a root partition of type "Return a bootable, stand-alone QEMU image, with a root partition of type
FILE-SYSTEM-TYPE. The returned image is a full disk image, with a GRUB FILE-SYSTEM-TYPE. The returned image is a full disk image, with a GRUB
installation that uses GRUB-CONFIGURATION as its configuration installation that uses GRUB-CONFIGURATION as its configuration
file (GRUB-CONFIGURATION must be the name of a file in the VM.) file (GRUB-CONFIGURATION must be the name of a file in the VM.)
INPUTS-TO-COPY is a list of inputs (as for packages) whose closure is copied INPUTS is a list of inputs (as for packages). When COPY-INPUTS? is true, copy
into the image being built. When INITIALIZE-STORE? is true, initialize the all of INPUTS into the image being built. When REGISTER-CLOSURES? is true,
store database in the image so that Guix can be used in the image. register INPUTS in the store database of the image so that Guix can be used in
the image.
POPULATE is a list of directives stating directories or symlinks to be created POPULATE is a list of directives stating directories or symlinks to be created
in the disk image partition. It is evaluated once the image has been in the disk image partition. It is evaluated once the image has been
populated with INPUTS-TO-COPY. It can be used to provide additional files, populated with INPUTS-TO-COPY. It can be used to provide additional files,
such as /etc files." such as /etc files."
(mlet %store-monad (mlet %store-monad
((graph (sequence %store-monad ((graph (sequence %store-monad (map input->name+output inputs))))
(map input->name+output inputs-to-copy))))
(expression->derivation-in-linux-vm (expression->derivation-in-linux-vm
name name
#~(begin #~(begin
...@@ -221,26 +222,27 @@ (define* (qemu-image #:key ...@@ -221,26 +222,27 @@ (define* (qemu-image #:key
'#$(append (list qemu parted grub e2fsprogs util-linux) '#$(append (list qemu parted grub e2fsprogs util-linux)
(map (compose car (cut assoc-ref %final-inputs <>)) (map (compose car (cut assoc-ref %final-inputs <>))
'("sed" "grep" "coreutils" "findutils" "gawk")) '("sed" "grep" "coreutils" "findutils" "gawk"))
(if initialize-store? (list guix) '()))) (if register-closures? (list guix) '())))
;; This variable is unused but allows us to add INPUTS-TO-COPY ;; This variable is unused but allows us to add INPUTS-TO-COPY
;; as inputs. ;; as inputs.
(to-copy (to-register
'#$(map (match-lambda '#$(map (match-lambda
((name thing) thing) ((name thing) thing)
((name thing output) `(,thing ,output))) ((name thing output) `(,thing ,output)))
inputs-to-copy))) inputs)))
(set-path-environment-variable "PATH" '("bin" "sbin") inputs) (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
(let ((graphs '#$(match inputs-to-copy (let ((graphs '#$(match inputs
(((names . _) ...) (((names . _) ...)
names)))) names))))
(initialize-hard-disk #:grub.cfg #$grub-configuration (initialize-hard-disk #:grub.cfg #$grub-configuration
#:closures-to-copy graphs #:closures graphs
#:copy-closures? #$copy-inputs?
#:register-closures? #$register-closures?
#:disk-image-size #$disk-image-size #:disk-image-size #$disk-image-size
#:file-system-type #$file-system-type #:file-system-type #$file-system-type
#:initialize-store? #$initialize-store?
#:directives '#$populate) #:directives '#$populate)
(reboot)))) (reboot))))
#:system system #:system system
...@@ -318,8 +320,8 @@ (define file-systems-to-keep ...@@ -318,8 +320,8 @@ (define file-systems-to-keep
#:populate populate #:populate populate
#:disk-image-size disk-image-size #:disk-image-size disk-image-size
#:file-system-type file-system-type #:file-system-type file-system-type
#:initialize-store? #t #:inputs `(("system" ,os-drv))
#:inputs-to-copy `(("system" ,os-drv)))))) #:copy-inputs? #t))))
(define (virtualized-operating-system os) (define (virtualized-operating-system os)
"Return an operating system based on OS suitable for use in a virtualized "Return an operating system based on OS suitable for use in a virtualized
...@@ -358,10 +360,14 @@ (define* (system-qemu-image/shared-store ...@@ -358,10 +360,14 @@ (define* (system-qemu-image/shared-store
(os-dir -> (derivation->output-path os-drv)) (os-dir -> (derivation->output-path os-drv))
(grub.cfg -> (string-append os-dir "/grub.cfg")) (grub.cfg -> (string-append os-dir "/grub.cfg"))
(populate (operating-system-default-contents os))) (populate (operating-system-default-contents os)))
;; TODO: Initialize the database so Guix can be used in the guest.
(qemu-image #:grub-configuration grub.cfg (qemu-image #:grub-configuration grub.cfg
#:populate populate #:populate populate
#:disk-image-size disk-image-size))) #:disk-image-size disk-image-size
#:inputs `(("system" ,os-drv))
;; XXX: Passing #t here is too slow, so let it off by default.
#:register-closures? #f
#:copy-inputs? #f)))
(define* (system-qemu-image/shared-store-script (define* (system-qemu-image/shared-store-script
os os
......
...@@ -180,13 +180,36 @@ (define (reset-timestamps directory) ...@@ -180,13 +180,36 @@ (define (reset-timestamps directory)
(utime file 0 0 0 0)))) (utime file 0 0 0 0))))
(find-files directory ""))) (find-files directory "")))
(define (register-closure store closure)
"Register CLOSURE in STORE, where STORE is the directory name of the target
store and CLOSURE is the name of a file containing a reference graph as used
by 'guix-register'."
(let ((status (system* "guix-register" "--prefix" store
closure)))
(unless (zero? status)
(error "failed to register store items" closure))))
(define MS_BIND 4096) ; <sys/mounts.h> again!
(define* (initialize-hard-disk #:key (define* (initialize-hard-disk #:key
grub.cfg grub.cfg
disk-image-size disk-image-size
(file-system-type "ext4") (file-system-type "ext4")
initialize-store? (closures '())
(closures-to-copy '()) copy-closures?
(register-closures? #t)
(directives '())) (directives '()))
"Initialize /dev/sda, a disk of DISK-IMAGE-SIZE bytes, with a
FILE-SYSTEM-TYPE partition, and with GRUB installed. If REGISTER-CLOSURES? is
true, register all of CLOSURES is the partition's store. If COPY-CLOSURES? is
true, copy all of CLOSURES to the partition. Lastly, apply DIRECTIVES to
further populate the partition."
(define target-directory
"/fs")
(define target-store
(string-append target-directory (%store-directory)))
(unless (initialize-partition-table "/dev/sda" (unless (initialize-partition-table "/dev/sda"
#:partition-size #:partition-size
(- disk-image-size (* 5 (expt 2 20)))) (- disk-image-size (* 5 (expt 2 20))))
...@@ -198,36 +221,43 @@ (define* (initialize-hard-disk #:key ...@@ -198,36 +221,43 @@ (define* (initialize-hard-disk #:key
(error "failed to create partition")) (error "failed to create partition"))
(display "mounting partition...\n") (display "mounting partition...\n")
(mkdir "/fs") (mkdir target-directory)
(mount "/dev/sda1" "/fs" file-system-type) (mount "/dev/sda1" target-directory file-system-type)
(when (pair? closures-to-copy) (when copy-closures?
;; Populate the store. ;; Populate the store.
(populate-store (map (cut string-append "/xchg/" <>) (populate-store (map (cut string-append "/xchg/" <>) closures)
closures-to-copy) target-directory))
"/fs"))
;; Populate /dev. ;; Populate /dev.
(make-essential-device-nodes #:root "/fs") (make-essential-device-nodes #:root target-directory)
;; Optionally, register the inputs in the image's store. ;; Optionally, register the inputs in the image's store.
(when initialize-store? (when register-closures?
(unless copy-closures?
;; XXX: 'guix-register' wants to palpate the things it registers, so
;; bind-mount the store on the target.
(mkdir-p target-store)
(mount (%store-directory) target-store "" MS_BIND))
(display "registering closures...\n")
(for-each (lambda (closure) (for-each (lambda (closure)
(let ((status (system* "guix-register" "--prefix" "/fs" (register-closure target-directory
(string-append "/xchg/" closure)))) (string-append "/xchg/" closure)))
(unless (zero? status) closures)
(error "failed to register store items" closure)))) (unless copy-closures?
closures-to-copy)) (system* "umount" target-store)))
;; Evaluate the POPULATE directives. ;; Evaluate the POPULATE directives.
(for-each (cut evaluate-populate-directive <> "/fs") (display "populating...\n")
(for-each (cut evaluate-populate-directive <> target-directory)
directives) directives)
(unless (install-grub grub.cfg "/dev/sda" "/fs") (unless (install-grub grub.cfg "/dev/sda" target-directory)
(error "failed to install GRUB")) (error "failed to install GRUB"))
(reset-timestamps "/fs") (reset-timestamps target-directory)
(zero? (system* "umount" "/fs"))) (zero? (system* "umount" target-directory)))
;;; vm.scm ends here ;;; vm.scm ends here
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment