;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr>
;;;
;;; This file is part of GNU Guix.
;;;
(define-module (gnu tests install)
#:use-module (gnu)
+ #:use-module (gnu bootloader extlinux)
#:use-module (gnu tests)
#:use-module (gnu tests base)
#:use-module (gnu system)
#:use-module (gnu system install)
#:use-module (gnu system vm)
#:use-module ((gnu build vm) #:select (qemu-command))
- #:use-module (gnu packages qemu)
+ #:use-module (gnu packages admin)
+ #:use-module (gnu packages bootloaders)
+ #:use-module (gnu packages cryptsetup)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages ocr)
#:use-module (gnu packages package-management)
+ #:use-module (gnu packages virtualization)
+ #:use-module (gnu services networking)
#:use-module (guix store)
#:use-module (guix monads)
#:use-module (guix packages)
#:use-module (guix gexp)
#:use-module (guix utils)
#:export (%test-installed-os
- %test-encrypted-os))
+ %test-installed-extlinux-os
+ %test-iso-image-installer
+ %test-separate-store-os
+ %test-separate-home-os
+ %test-raid-root-os
+ %test-encrypted-root-os
+ %test-btrfs-root-os
+ %test-jfs-root-os
+
+ %test-gui-installed-os
+ %test-gui-installed-os-encrypted))
;;; Commentary:
;;;
-;;; Test the installation of GuixSD using the documented approach at the
+;;; Test the installation of Guix using the documented approach at the
;;; command line.
;;;
;;; Code:
(timezone "Europe/Paris")
(locale "en_US.UTF-8")
- (bootloader (grub-configuration (device "/dev/vdb")))
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vdb")))
(kernel-arguments '("console=ttyS0"))
(file-systems (cons (file-system
- (device "my-root")
- (title 'label)
+ (device (file-system-label "my-root"))
(mount-point "/")
(type "ext4"))
%base-file-systems))
(name "alice")
(comment "Bob's sister")
(group "users")
- (supplementary-groups '("wheel" "audio" "video"))
- (home-directory "/home/alice"))
+ (supplementary-groups '("wheel" "audio" "video")))
%base-user-accounts))
+ (services (cons (service marionette-service-type
+ (marionette-configuration
+ (imported-modules '((gnu services herd)
+ (guix build utils)
+ (guix combinators)))))
+ %base-services))))
+
+(define (operating-system-add-packages os packages)
+ "Append PACKAGES to OS packages list."
+ (operating-system
+ (inherit os)
+ (packages (append packages (operating-system-packages os)))))
+
+(define-os-with-source (%minimal-extlinux-os
+ %minimal-extlinux-os-source)
+ (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
+ (srfi srfi-1))
+
+ (operating-system
+ (host-name "liberigilo")
+ (timezone "Europe/Paris")
+ (locale "en_US.UTF-8")
+
+ (bootloader (bootloader-configuration
+ (bootloader extlinux-bootloader-gpt)
+ (target "/dev/vdb")))
+ (kernel-arguments '("console=ttyS0"))
+ (file-systems (cons (file-system
+ (device (file-system-label "my-root"))
+ (mount-point "/")
+ (type "ext4"))
+ %base-file-systems))
(services (cons (service marionette-service-type
(marionette-configuration
(imported-modules '((gnu services herd)
(inherit config)
(guix (current-guix))))))))
-(define (operating-system-with-gc-roots os roots)
- "Return a variant of OS where ROOTS are registered as GC roots."
- (operating-system
- (inherit os)
- (services (cons (service gc-root-service-type roots)
- (operating-system-user-services os)))))
-
\f
(define MiB (expt 2 20))
guix build isc-dhcp
parted --script /dev/vdb mklabel gpt \\
mkpart primary ext2 1M 3M \\
- mkpart primary ext2 3M 1G \\
+ mkpart primary ext2 3M 1.4G \\
set 1 boot on \\
set 1 bios_grub on
mkfs.ext4 -L my-root /dev/vdb2
sync
reboot\n")
+(define %extlinux-gpt-installation-script
+ ;; Shell script of a simple installation.
+ ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
+ ;; we make sure to pass -O '^64bit' to mkfs.
+ "\
+. /etc/profile
+set -e -x
+guix --version
+
+export GUIX_BUILD_OPTIONS=--no-grafts
+guix build isc-dhcp
+parted --script /dev/vdb mklabel gpt \\
+ mkpart ext2 1M 1.4G \\
+ set 1 legacy_boot on
+mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
+mount /dev/vdb1 /mnt
+df -h /mnt
+herd start cow-store /mnt
+mkdir /mnt/etc
+cp /etc/target-config.scm /mnt/etc/config.scm
+guix system init /mnt/etc/config.scm /mnt --no-substitutes
+sync
+reboot\n")
+
(define* (run-install target-os target-os-source
#:key
(script %simple-installation-script)
+ (gui-test #f)
+ (packages '())
(os (marionette-operating-system
- ;; Since the image has no network access, use the
- ;; current Guix so the store items we need are in
- ;; the image.
(operating-system
- (inherit (operating-system-with-current-guix
- installation-os))
+ ;; Since the image has no network access, use the
+ ;; current Guix so the store items we need are in
+ ;; the image and add packages provided.
+ (inherit (operating-system-add-packages
+ (operating-system-with-current-guix
+ installation-os)
+ packages))
(kernel-arguments '("console=ttyS0")))
#:imported-modules '((gnu services herd)
+ (gnu installer tests)
(guix combinators))))
- (target-size (* 1200 MiB)))
- "Run SCRIPT (a shell script following the GuixSD installation procedure) in
+ (installation-disk-image-file-system-type "ext4")
+ (target-size (* 2200 MiB)))
+ "Run SCRIPT (a shell script following the system installation procedure) in
OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
-the installed system."
+the installed system. The packages specified in PACKAGES will be appended to
+packages defined in installation-os."
(mlet* %store-monad ((_ (set-grafting #f))
(system (current-system))
(image (system-disk-image
(operating-system-with-gc-roots
os (list target))
- #:disk-image-size (* 1500 MiB))))
+ #:disk-image-size 'guess
+ #:file-system-type
+ installation-disk-image-file-system-type)))
(define install
(with-imported-modules '((guix build utils)
(gnu build marionette))
(define marionette
(make-marionette
- (cons (which #$(qemu-command system))
- (cons* "-no-reboot" "-m" "800"
- "-drive"
- (string-append "file=" #$image
- ",if=virtio,readonly")
- "-drive"
- (string-append "file=" #$output ",if=virtio")
- (if (file-exists? "/dev/kvm")
- '("-enable-kvm")
- '())))))
+ `(,(which #$(qemu-command system))
+ "-no-reboot"
+ "-m" "800"
+ #$@(cond
+ ((string=? "ext4" installation-disk-image-file-system-type)
+ #~("-drive"
+ ,(string-append "file=" #$image
+ ",if=virtio,readonly")))
+ ((string=? "iso9660" installation-disk-image-file-system-type)
+ #~("-cdrom" #$image))
+ (else
+ (error
+ "unsupported installation-disk-image-file-system-type:"
+ installation-disk-image-file-system-type)))
+ "-drive"
+ ,(string-append "file=" #$output ",if=virtio")
+ ,@(if (file-exists? "/dev/kvm")
+ '("-enable-kvm")
+ '()))))
(pk 'uname (marionette-eval '(uname) marionette))
(start 'term-tty1))
marionette)
- (marionette-eval '(call-with-output-file "/etc/target-config.scm"
- (lambda (port)
- (write '#$target-os-source port)))
- marionette)
+ (when #$(->bool script)
+ (marionette-eval '(call-with-output-file "/etc/target-config.scm"
+ (lambda (port)
+ (write '#$target-os-source port)))
+ marionette)
+ (exit (marionette-eval '(zero? (system #$script))
+ marionette)))
- (exit (marionette-eval '(zero? (system #$script))
- marionette)))))
+ (when #$(->bool gui-test)
+ (wait-for-unix-socket "/var/guix/installer-socket"
+ marionette)
+ (format #t "installer socket ready~%")
+ (force-output)
+ (exit #$(and gui-test
+ (gui-test #~marionette)))))))
(gexp->derivation "installation" install)))
-(define (qemu-command/writable-image image)
+(define* (qemu-command/writable-image image #:key (memory-size 256))
"Return as a monadic value the command to run QEMU on a writable copy of
-IMAGE, a disk image."
+IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
(mlet %store-monad ((system (current-system)))
(return #~(let ((image #$image))
;; First we need a writable copy of the image.
- (format #t "copying image '~a'...~%" image)
- (copy-file image "disk.img")
+ (format #t "creating writable image from '~a'...~%" image)
+ (unless (zero? (system* #+(file-append qemu-minimal
+ "/bin/qemu-img")
+ "create" "-f" "qcow2"
+ "-o"
+ (string-append "backing_file=" image)
+ "disk.img"))
+ (error "failed to create writable QEMU image" image))
+
(chmod "disk.img" #o644)
`(,(string-append #$qemu-minimal "/bin/"
#$(qemu-command system))
,@(if (file-exists? "/dev/kvm")
'("-enable-kvm")
'())
- "-no-reboot" "-m" "256"
+ "-no-reboot" "-m" #$(number->string memory-size)
"-drive" "file=disk.img,if=virtio")))))
-\f
(define %test-installed-os
(system-test
(name "installed-os")
(run-basic-test %minimal-os command
"installed-os")))))
+(define %test-installed-extlinux-os
+ (system-test
+ (name "installed-extlinux-os")
+ (description
+ "Test basic functionality of an OS booted with an extlinux bootloader. As
+per %test-installed-os, this test is expensive in terms of CPU and storage.")
+ (value
+ (mlet* %store-monad ((image (run-install %minimal-extlinux-os
+ %minimal-extlinux-os-source
+ #:packages
+ (list syslinux)
+ #:script
+ %extlinux-gpt-installation-script))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test %minimal-extlinux-os command
+ "installed-extlinux-os")))))
+
\f
-(define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
+;;;
+;;; Installation through an ISO image.
+;;;
+
+(define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
;; The OS we want to install.
(use-modules (gnu) (gnu tests) (srfi srfi-1))
(timezone "Europe/Paris")
(locale "en_US.UTF-8")
- (bootloader (grub-configuration (device "/dev/vdb")))
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vda")))
(kernel-arguments '("console=ttyS0"))
(file-systems (cons (file-system
- (device "/dev/mapper/the-root-device")
- (title 'device)
+ (device (file-system-label "my-root"))
(mount-point "/")
(type "ext4"))
%base-file-systems))
+ (users (cons (user-account
+ (name "alice")
+ (comment "Bob's sister")
+ (group "users")
+ (supplementary-groups '("wheel" "audio" "video")))
+ %base-user-accounts))
+ (services (cons (service marionette-service-type
+ (marionette-configuration
+ (imported-modules '((gnu services herd)
+ (guix combinators)))))
+ %base-services))))
+
+(define %simple-installation-script-for-/dev/vda
+ ;; Shell script of a simple installation.
+ "\
+. /etc/profile
+set -e -x
+guix --version
+
+export GUIX_BUILD_OPTIONS=--no-grafts
+guix build isc-dhcp
+parted --script /dev/vda mklabel gpt \\
+ mkpart primary ext2 1M 3M \\
+ mkpart primary ext2 3M 1.4G \\
+ set 1 boot on \\
+ set 1 bios_grub on
+mkfs.ext4 -L my-root /dev/vda2
+mount /dev/vda2 /mnt
+df -h /mnt
+herd start cow-store /mnt
+mkdir /mnt/etc
+cp /etc/target-config.scm /mnt/etc/config.scm
+guix system init /mnt/etc/config.scm /mnt --no-substitutes
+sync
+reboot\n")
+
+(define %test-iso-image-installer
+ (system-test
+ (name "iso-image-installer")
+ (description
+ "")
+ (value
+ (mlet* %store-monad ((image (run-install
+ %minimal-os-on-vda
+ %minimal-os-on-vda-source
+ #:script
+ %simple-installation-script-for-/dev/vda
+ #:installation-disk-image-file-system-type
+ "iso9660"))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test %minimal-os-on-vda command name)))))
+
+\f
+;;;
+;;; Separate /home.
+;;;
+
+(define-os-with-source (%separate-home-os %separate-home-os-source)
+ ;; The OS we want to install.
+ (use-modules (gnu) (gnu tests) (srfi srfi-1))
+
+ (operating-system
+ (host-name "liberigilo")
+ (timezone "Europe/Paris")
+ (locale "en_US.utf8")
+
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vdb")))
+ (kernel-arguments '("console=ttyS0"))
+ (file-systems (cons* (file-system
+ (device (file-system-label "my-root"))
+ (mount-point "/")
+ (type "ext4"))
+ (file-system
+ (device "none")
+ (mount-point "/home")
+ (type "tmpfs"))
+ %base-file-systems))
+ (users (cons* (user-account
+ (name "alice")
+ (group "users"))
+ (user-account
+ (name "charlie")
+ (group "users"))
+ %base-user-accounts))
+ (services (cons (service marionette-service-type
+ (marionette-configuration
+ (imported-modules '((gnu services herd)
+ (guix combinators)))))
+ %base-services))))
+
+(define %test-separate-home-os
+ (system-test
+ (name "separate-home-os")
+ (description
+ "Test basic functionality of an installed OS with a separate /home
+partition. In particular, home directories must be correctly created (see
+<https://bugs.gnu.org/21108>).")
+ (value
+ (mlet* %store-monad ((image (run-install %separate-home-os
+ %separate-home-os-source
+ #:script
+ %simple-installation-script))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test %separate-home-os command "separate-home-os")))))
+
+\f
+;;;
+;;; Separate /gnu/store partition.
+;;;
+
+(define-os-with-source (%separate-store-os %separate-store-os-source)
+ ;; The OS we want to install.
+ (use-modules (gnu) (gnu tests) (srfi srfi-1))
+
+ (operating-system
+ (host-name "liberigilo")
+ (timezone "Europe/Paris")
+ (locale "en_US.UTF-8")
+
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vdb")))
+ (kernel-arguments '("console=ttyS0"))
+ (file-systems (cons* (file-system
+ (device (file-system-label "root-fs"))
+ (mount-point "/")
+ (type "ext4"))
+ (file-system
+ (device (file-system-label "store-fs"))
+ (mount-point "/gnu")
+ (type "ext4"))
+ %base-file-systems))
+ (users %base-user-accounts)
+ (services (cons (service marionette-service-type
+ (marionette-configuration
+ (imported-modules '((gnu services herd)
+ (guix combinators)))))
+ %base-services))))
+
+(define %separate-store-installation-script
+ ;; Installation with a separate /gnu partition.
+ "\
+. /etc/profile
+set -e -x
+guix --version
+
+export GUIX_BUILD_OPTIONS=--no-grafts
+guix build isc-dhcp
+parted --script /dev/vdb mklabel gpt \\
+ mkpart primary ext2 1M 3M \\
+ mkpart primary ext2 3M 400M \\
+ mkpart primary ext2 400M 2.1G \\
+ set 1 boot on \\
+ set 1 bios_grub on
+mkfs.ext4 -L root-fs /dev/vdb2
+mkfs.ext4 -L store-fs /dev/vdb3
+mount /dev/vdb2 /mnt
+mkdir /mnt/gnu
+mount /dev/vdb3 /mnt/gnu
+df -h /mnt
+df -h /mnt/gnu
+herd start cow-store /mnt
+mkdir /mnt/etc
+cp /etc/target-config.scm /mnt/etc/config.scm
+guix system init /mnt/etc/config.scm /mnt --no-substitutes
+sync
+reboot\n")
+
+(define %test-separate-store-os
+ (system-test
+ (name "separate-store-os")
+ (description
+ "Test basic functionality of an OS installed like one would do by hand,
+where /gnu lives on a separate partition.")
+ (value
+ (mlet* %store-monad ((image (run-install %separate-store-os
+ %separate-store-os-source
+ #:script
+ %separate-store-installation-script))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test %separate-store-os command "separate-store-os")))))
+
+\f
+;;;
+;;; RAID root device.
+;;;
+
+(define-os-with-source (%raid-root-os %raid-root-os-source)
+ ;; An OS whose root partition is a RAID partition.
+ (use-modules (gnu) (gnu tests))
+
+ (operating-system
+ (host-name "raidified")
+ (timezone "Europe/Paris")
+ (locale "en_US.utf8")
+
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vdb")))
+ (kernel-arguments '("console=ttyS0"))
+
+ ;; Add a kernel module for RAID-1 (aka. "mirror").
+ (initrd-modules (cons "raid1" %base-initrd-modules))
+
(mapped-devices (list (mapped-device
- (source "REPLACE-WITH-LUKS-UUID")
+ (source (list "/dev/vda2" "/dev/vda3"))
+ (target "/dev/md0")
+ (type raid-device-mapping))))
+ (file-systems (cons (file-system
+ (device (file-system-label "root-fs"))
+ (mount-point "/")
+ (type "ext4")
+ (dependencies mapped-devices))
+ %base-file-systems))
+ (users %base-user-accounts)
+ (services (cons (service marionette-service-type
+ (marionette-configuration
+ (imported-modules '((gnu services herd)
+ (guix combinators)))))
+ %base-services))))
+
+(define %raid-root-installation-script
+ ;; Installation with a separate /gnu partition. See
+ ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
+ ;; mdadm.
+ "\
+. /etc/profile
+set -e -x
+guix --version
+
+export GUIX_BUILD_OPTIONS=--no-grafts
+parted --script /dev/vdb mklabel gpt \\
+ mkpart primary ext2 1M 3M \\
+ mkpart primary ext2 3M 1.4G \\
+ mkpart primary ext2 1.4G 2.8G \\
+ set 1 boot on \\
+ set 1 bios_grub on
+yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
+ /dev/vdb2 /dev/vdb3
+mkfs.ext4 -L root-fs /dev/md0
+mount /dev/md0 /mnt
+df -h /mnt
+herd start cow-store /mnt
+mkdir /mnt/etc
+cp /etc/target-config.scm /mnt/etc/config.scm
+guix system init /mnt/etc/config.scm /mnt --no-substitutes
+sync
+reboot\n")
+
+(define %test-raid-root-os
+ (system-test
+ (name "raid-root-os")
+ (description
+ "Test functionality of an OS installed with a RAID root partition managed
+by 'mdadm'.")
+ (value
+ (mlet* %store-monad ((image (run-install %raid-root-os
+ %raid-root-os-source
+ #:script
+ %raid-root-installation-script
+ #:target-size (* 2800 MiB)))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test %raid-root-os
+ `(,@command) "raid-root-os")))))
+
+\f
+;;;
+;;; LUKS-encrypted root file system.
+;;;
+
+(define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
+ ;; The OS we want to install.
+ (use-modules (gnu) (gnu tests) (srfi srfi-1))
+
+ (operating-system
+ (host-name "liberigilo")
+ (timezone "Europe/Paris")
+ (locale "en_US.UTF-8")
+
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vdb")))
+
+ ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
+ ;; detection logic in 'enter-luks-passphrase'.
+
+ (mapped-devices (list (mapped-device
+ (source (uuid "12345678-1234-1234-1234-123456789abc"))
(target "the-root-device")
(type luks-device-mapping))))
+ (file-systems (cons (file-system
+ (device "/dev/mapper/the-root-device")
+ (mount-point "/")
+ (type "ext4"))
+ %base-file-systems))
(users (cons (user-account
(name "charlie")
(group "users")
- (home-directory "/home/charlie")
(supplementary-groups '("wheel" "audio" "video")))
%base-user-accounts))
(services (cons (service marionette-service-type
(guix combinators)))))
%base-services))))
+(define %luks-passphrase
+ ;; LUKS encryption passphrase used in tests.
+ "thepassphrase")
+
(define %encrypted-root-installation-script
;; Shell script of a simple installation.
- "\
+ (string-append "\
. /etc/profile
set -e -x
guix --version
ls -l /run/current-system/gc-roots
parted --script /dev/vdb mklabel gpt \\
mkpart primary ext2 1M 3M \\
- mkpart primary ext2 3M 1G \\
+ mkpart primary ext2 3M 1.4G \\
set 1 boot on \\
set 1 bios_grub on
-echo -n thepassphrase | cryptsetup luksFormat -q /dev/vdb2 -
-echo -n thepassphrase | \\
+echo -n " %luks-passphrase " | \\
+ cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
+echo -n " %luks-passphrase " | \\
cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
mkfs.ext4 -L my-root /dev/mapper/the-root-device
mount LABEL=my-root /mnt
herd start cow-store /mnt
mkdir /mnt/etc
cp /etc/target-config.scm /mnt/etc/config.scm
-cat /mnt/etc/config
-luks_uuid=`cryptsetup luksUUID /dev/vdb2`
-sed -i /mnt/etc/config.scm \\
- -e \"s/\\\"REPLACE-WITH-LUKS-UUID\\\"/(uuid \\\"$luks_uuid\\\")/g\"
guix system build /mnt/etc/config.scm
guix system init /mnt/etc/config.scm /mnt --no-substitutes
sync
-reboot\n")
+reboot\n"))
+
+(define (enter-luks-passphrase marionette)
+ "Return a gexp to be inserted in the basic system test running on MARIONETTE
+to enter the LUKS passphrase."
+ (let ((ocrad (file-append ocrad "/bin/ocrad")))
+ #~(begin
+ (define (passphrase-prompt? text)
+ (string-contains (pk 'screen-text text) "Enter pass"))
+
+ (define (bios-boot-screen? text)
+ ;; Return true if TEXT corresponds to the boot screen, before GRUB's
+ ;; menu.
+ (string-prefix? "SeaBIOS" text))
+
+ (test-assert "enter LUKS passphrase for GRUB"
+ (begin
+ ;; At this point we have no choice but to use OCR to determine
+ ;; when the passphrase should be entered.
+ (wait-for-screen-text #$marionette passphrase-prompt?
+ #:ocrad #$ocrad)
+ (marionette-type #$(string-append %luks-passphrase "\n")
+ #$marionette)
+
+ ;; Now wait until we leave the boot screen. This is necessary so
+ ;; we can then be sure we match the "Enter passphrase" prompt from
+ ;; 'cryptsetup', in the initrd.
+ (wait-for-screen-text #$marionette (negate bios-boot-screen?)
+ #:ocrad #$ocrad
+ #:timeout 20)))
+
+ (test-assert "enter LUKS passphrase for the initrd"
+ (begin
+ ;; XXX: Here we use OCR as well but we could instead use QEMU
+ ;; '-serial stdio' and run it in an input pipe,
+ (wait-for-screen-text #$marionette passphrase-prompt?
+ #:ocrad #$ocrad
+ #:timeout 60)
+ (marionette-type #$(string-append %luks-passphrase "\n")
+ #$marionette)
-(define %test-encrypted-os
+ ;; Take a screenshot for debugging purposes.
+ (marionette-control (string-append "screendump " #$output
+ "/post-initrd-passphrase.ppm")
+ #$marionette))))))
+
+(define %test-encrypted-root-os
(system-test
(name "encrypted-root-os")
(description
#:script
%encrypted-root-installation-script))
(command (qemu-command/writable-image image)))
- (run-basic-test %encrypted-root-os command "encrypted-root-os")))))
+ (run-basic-test %encrypted-root-os command "encrypted-root-os"
+ #:initialization enter-luks-passphrase)))))
+
+\f
+;;;
+;;; Btrfs root file system.
+;;;
+
+(define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
+ ;; The OS we want to install.
+ (use-modules (gnu) (gnu tests) (srfi srfi-1))
+
+ (operating-system
+ (host-name "liberigilo")
+ (timezone "Europe/Paris")
+ (locale "en_US.UTF-8")
+
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vdb")))
+ (kernel-arguments '("console=ttyS0"))
+ (file-systems (cons (file-system
+ (device (file-system-label "my-root"))
+ (mount-point "/")
+ (type "btrfs"))
+ %base-file-systems))
+ (users (cons (user-account
+ (name "charlie")
+ (group "users")
+ (supplementary-groups '("wheel" "audio" "video")))
+ %base-user-accounts))
+ (services (cons (service marionette-service-type
+ (marionette-configuration
+ (imported-modules '((gnu services herd)
+ (guix combinators)))))
+ %base-services))))
+
+(define %btrfs-root-installation-script
+ ;; Shell script of a simple installation.
+ "\
+. /etc/profile
+set -e -x
+guix --version
+
+export GUIX_BUILD_OPTIONS=--no-grafts
+ls -l /run/current-system/gc-roots
+parted --script /dev/vdb mklabel gpt \\
+ mkpart primary ext2 1M 3M \\
+ mkpart primary ext2 3M 2G \\
+ set 1 boot on \\
+ set 1 bios_grub on
+mkfs.btrfs -L my-root /dev/vdb2
+mount /dev/vdb2 /mnt
+btrfs subvolume create /mnt/home
+herd start cow-store /mnt
+mkdir /mnt/etc
+cp /etc/target-config.scm /mnt/etc/config.scm
+guix system build /mnt/etc/config.scm
+guix system init /mnt/etc/config.scm /mnt --no-substitutes
+sync
+reboot\n")
+
+(define %test-btrfs-root-os
+ (system-test
+ (name "btrfs-root-os")
+ (description
+ "Test basic functionality of an OS installed like one would do by hand.
+This test is expensive in terms of CPU and storage usage since we need to
+build (current-guix) and then store a couple of full system images.")
+ (value
+ (mlet* %store-monad ((image (run-install %btrfs-root-os
+ %btrfs-root-os-source
+ #:script
+ %btrfs-root-installation-script))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
+
+\f
+;;;
+;;; JFS root file system.
+;;;
+
+(define-os-with-source (%jfs-root-os %jfs-root-os-source)
+ ;; The OS we want to install.
+ (use-modules (gnu) (gnu tests) (srfi srfi-1))
+
+ (operating-system
+ (host-name "liberigilo")
+ (timezone "Europe/Paris")
+ (locale "en_US.UTF-8")
+
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vdb")))
+ (kernel-arguments '("console=ttyS0"))
+ (file-systems (cons (file-system
+ (device (file-system-label "my-root"))
+ (mount-point "/")
+ (type "jfs"))
+ %base-file-systems))
+ (users (cons (user-account
+ (name "charlie")
+ (group "users")
+ (supplementary-groups '("wheel" "audio" "video")))
+ %base-user-accounts))
+ (services (cons (service marionette-service-type
+ (marionette-configuration
+ (imported-modules '((gnu services herd)
+ (guix combinators)))))
+ %base-services))))
+
+(define %jfs-root-installation-script
+ ;; Shell script of a simple installation.
+ "\
+. /etc/profile
+set -e -x
+guix --version
+
+export GUIX_BUILD_OPTIONS=--no-grafts
+ls -l /run/current-system/gc-roots
+parted --script /dev/vdb mklabel gpt \\
+ mkpart primary ext2 1M 3M \\
+ mkpart primary ext2 3M 2G \\
+ set 1 boot on \\
+ set 1 bios_grub on
+jfs_mkfs -L my-root -q /dev/vdb2
+mount /dev/vdb2 /mnt
+herd start cow-store /mnt
+mkdir /mnt/etc
+cp /etc/target-config.scm /mnt/etc/config.scm
+guix system build /mnt/etc/config.scm
+guix system init /mnt/etc/config.scm /mnt --no-substitutes
+sync
+reboot\n")
+
+(define %test-jfs-root-os
+ (system-test
+ (name "jfs-root-os")
+ (description
+ "Test basic functionality of an OS installed like one would do by hand.
+This test is expensive in terms of CPU and storage usage since we need to
+build (current-guix) and then store a couple of full system images.")
+ (value
+ (mlet* %store-monad ((image (run-install %jfs-root-os
+ %jfs-root-os-source
+ #:script
+ %jfs-root-installation-script))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test %jfs-root-os command "jfs-root-os")))))
+
+\f
+;;;
+;;; Installation through the graphical interface.
+;;;
+
+(define %syslog-conf
+ ;; Syslog configuration that dumps to /dev/console, so we can see the
+ ;; installer's messages during the test.
+ (computed-file "syslog.conf"
+ #~(begin
+ (copy-file #$%default-syslog.conf #$output)
+ (chmod #$output #o644)
+ (let ((port (open-file #$output "a")))
+ (display "\n*.info /dev/console\n" port)
+ #t))))
+
+(define (operating-system-with-console-syslog os)
+ "Return OS with a syslog service that writes to /dev/console."
+ (operating-system
+ (inherit os)
+ (services (modify-services (operating-system-user-services os)
+ (syslog-service-type config
+ =>
+ (syslog-configuration
+ (inherit config)
+ (config-file %syslog-conf)))))))
+
+(define %root-password "foo")
+
+(define* (gui-test-program marionette #:key (encrypted? #f))
+ #~(let ()
+ (define (screenshot file)
+ (marionette-control (string-append "screendump " file)
+ #$marionette))
+
+ (setvbuf (current-output-port) 'none)
+ (setvbuf (current-error-port) 'none)
+
+ (marionette-eval '(use-modules (gnu installer tests))
+ #$marionette)
+
+ ;; Arrange so that 'converse' prints debugging output to the console.
+ (marionette-eval '(let ((console (open-output-file "/dev/console")))
+ (setvbuf console 'none)
+ (conversation-log-port console))
+ #$marionette)
+
+ ;; Tell the installer to not wait for the Connman "online" status.
+ (marionette-eval '(call-with-output-file "/tmp/installer-assume-online"
+ (const #t))
+ #$marionette)
+
+ ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
+ ;; network access.
+ (marionette-eval '(call-with-output-file
+ "/tmp/installer-system-init-options"
+ (lambda (port)
+ (write '("--no-grafts" "--no-substitutes")
+ port)))
+ #$marionette)
+
+ (marionette-eval '(define installer-socket
+ (open-installer-socket))
+ #$marionette)
+ (screenshot "installer-start.ppm")
+
+ (marionette-eval '(choose-locale+keyboard installer-socket)
+ #$marionette)
+ (screenshot "installer-locale.ppm")
+
+ ;; Choose the host name that the "basic" test expects.
+ (marionette-eval '(enter-host-name+passwords installer-socket
+ #:host-name "liberigilo"
+ #:root-password
+ #$%root-password
+ #:users
+ '(("alice" "pass1")
+ ("bob" "pass2")))
+ #$marionette)
+ (screenshot "installer-services.ppm")
+
+ (marionette-eval '(choose-services installer-socket
+ #:desktop-environments '()
+ #:choose-network-service?
+ (const #f))
+ #$marionette)
+ (screenshot "installer-partitioning.ppm")
+
+ (marionette-eval '(choose-partitioning installer-socket
+ #:encrypted? #$encrypted?
+ #:passphrase #$%luks-passphrase)
+ #$marionette)
+ (screenshot "installer-run.ppm")
+
+ (marionette-eval '(conclude-installation installer-socket)
+ #$marionette)
+
+ (sync)
+ #t))
+
+(define %extra-packages
+ ;; Packages needed when installing with an encrypted root.
+ (list isc-dhcp
+ lvm2-static cryptsetup-static e2fsck/static
+ loadkeys-static))
+
+(define installation-os-for-gui-tests
+ ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
+ ;; target OS, as well as syslog output redirected to the console so we can
+ ;; see what the installer is up to.
+ (marionette-operating-system
+ (operating-system
+ (inherit (operating-system-with-console-syslog
+ (operating-system-add-packages
+ (operating-system-with-current-guix
+ installation-os)
+ %extra-packages)))
+ (kernel-arguments '("console=ttyS0")))
+ #:imported-modules '((gnu services herd)
+ (gnu installer tests)
+ (guix combinators))))
+
+(define* (guided-installation-test name #:key encrypted?)
+ (define os
+ (operating-system
+ (inherit %minimal-os)
+ (users (append (list (user-account
+ (name "alice")
+ (comment "Bob's sister")
+ (group "users")
+ (supplementary-groups
+ '("wheel" "audio" "video")))
+ (user-account
+ (name "bob")
+ (comment "Alice's brother")
+ (group "users")
+ (supplementary-groups
+ '("wheel" "audio" "video"))))
+ %base-user-accounts))
+ ;; The installer does not create a swap device in guided mode with
+ ;; encryption support.
+ (swap-devices (if encrypted? '() '("/dev/vdb2")))
+ (services (cons (service dhcp-client-service-type)
+ (operating-system-user-services %minimal-os)))))
+
+ (system-test
+ (name name)
+ (description
+ "Install an OS using the graphical installer and test it.")
+ (value
+ (mlet* %store-monad ((image (run-install os '(this is unused)
+ #:script #f
+ #:os installation-os-for-gui-tests
+ #:gui-test
+ (lambda (marionette)
+ (gui-test-program
+ marionette
+ #:encrypted? encrypted?))))
+ (command (qemu-command/writable-image image)))
+ (run-basic-test os command name
+ #:initialization (and encrypted? enter-luks-passphrase)
+ #:root-password %root-password)))))
+
+(define %test-gui-installed-os
+ (guided-installation-test "gui-installed-os"
+ #:encrypted? #f))
+
+(define %test-gui-installed-os-encrypted
+ (guided-installation-test "gui-installed-os-encrypted"
+ #:encrypted? #t))
;;; install.scm ends here