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'.
This commit is contained in:
parent
c336a66fe8
commit
150e20ddde
|
@ -192,25 +192,26 @@ made available under the /xchg CIFS share."
|
||||||
(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 @@ such as /etc files."
|
||||||
'#$(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 @@ of the GNU system as described by OS."
|
||||||
#: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 @@ with the host."
|
||||||
(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 @@ as created and modified at the Epoch."
|
||||||
(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 @@ as created and modified at the Epoch."
|
||||||
(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
|
||||||
|
|
Loading…
Reference in New Issue