1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr>
4 ;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
5 ;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
6 ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
8 ;;; This file is part of GNU Guix.
10 ;;; GNU Guix is free software; you can redistribute it and/or modify it
11 ;;; under the terms of the GNU General Public License as published by
12 ;;; the Free Software Foundation; either version 3 of the License, or (at
13 ;;; your option) any later version.
15 ;;; GNU Guix is distributed in the hope that it will be useful, but
16 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;;; GNU General Public License for more details.
20 ;;; You should have received a copy of the GNU General Public License
21 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
23 (define-module (gnu tests install)
25 #:use-module (gnu bootloader extlinux)
26 #:use-module (gnu image)
27 #:use-module (gnu tests)
28 #:use-module (gnu tests base)
29 #:use-module (gnu system)
30 #:use-module (gnu system image)
31 #:use-module (gnu system install)
32 #:use-module (gnu system vm)
33 #:use-module ((gnu build vm) #:select (qemu-command))
34 #:use-module (gnu packages admin)
35 #:use-module (gnu packages bootloaders)
36 #:use-module (gnu packages commencement) ;for 'guile-final'
37 #:use-module (gnu packages cryptsetup)
38 #:use-module (gnu packages linux)
39 #:use-module (gnu packages ocr)
40 #:use-module (gnu packages openbox)
41 #:use-module (gnu packages package-management)
42 #:use-module (gnu packages ratpoison)
43 #:use-module (gnu packages suckless)
44 #:use-module (gnu packages virtualization)
45 #:use-module (gnu packages wm)
46 #:use-module (gnu packages xorg)
47 #:use-module (gnu services desktop)
48 #:use-module (gnu services networking)
49 #:use-module (gnu services xorg)
50 #:use-module (guix store)
51 #:use-module (guix monads)
52 #:use-module (guix packages)
53 #:use-module (guix grafts)
54 #:use-module (guix gexp)
55 #:use-module (guix utils)
56 #:use-module (srfi srfi-1)
57 #:export (%test-installed-os
58 %test-installed-extlinux-os
59 %test-iso-image-installer
60 %test-separate-store-os
61 %test-separate-home-os
63 %test-encrypted-root-os
65 %test-btrfs-root-on-subvolume-os
69 %test-gui-installed-os
70 %test-gui-installed-os-encrypted
71 %test-gui-installed-desktop-os-encrypted))
75 ;;; Test the installation of Guix using the documented approach at the
80 (define-os-with-source (%minimal-os %minimal-os-source)
81 ;; The OS we want to install.
82 (use-modules (gnu) (gnu tests) (srfi srfi-1))
85 (host-name "liberigilo")
86 (timezone "Europe/Paris")
87 (locale "en_US.UTF-8")
89 (bootloader (bootloader-configuration
90 (bootloader grub-bootloader)
92 (kernel-arguments '("console=ttyS0"))
93 (file-systems (cons (file-system
94 (device (file-system-label "my-root"))
98 (users (cons (user-account
100 (comment "Bob's sister")
102 (supplementary-groups '("wheel" "audio" "video")))
103 %base-user-accounts))
104 (services (cons (service marionette-service-type
105 (marionette-configuration
106 (imported-modules '((gnu services herd)
108 (guix combinators)))))
111 (define (operating-system-add-packages os packages)
112 "Append PACKAGES to OS packages list."
115 (packages (append packages (operating-system-packages os)))))
117 (define-os-with-source (%minimal-extlinux-os
118 %minimal-extlinux-os-source)
119 (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
123 (host-name "liberigilo")
124 (timezone "Europe/Paris")
125 (locale "en_US.UTF-8")
127 (bootloader (bootloader-configuration
128 (bootloader extlinux-bootloader-gpt)
129 (target "/dev/vdb")))
130 (kernel-arguments '("console=ttyS0"))
131 (file-systems (cons (file-system
132 (device (file-system-label "my-root"))
136 (services (cons (service marionette-service-type
137 (marionette-configuration
138 (imported-modules '((gnu services herd)
139 (guix combinators)))))
142 (define (operating-system-with-current-guix os)
143 "Return a variant of OS that uses the current Guix."
146 (services (modify-services (operating-system-user-services os)
147 (guix-service-type config =>
150 (guix (current-guix))))))))
153 (define MiB (expt 2 20))
155 (define %simple-installation-script
156 ;; Shell script of a simple installation.
162 export GUIX_BUILD_OPTIONS=--no-grafts
164 parted --script /dev/vdb mklabel gpt \\
165 mkpart primary ext2 1M 3M \\
166 mkpart primary ext2 3M 1.6G \\
169 mkfs.ext4 -L my-root /dev/vdb2
172 herd start cow-store /mnt
174 cp /etc/target-config.scm /mnt/etc/config.scm
175 guix system init /mnt/etc/config.scm /mnt --no-substitutes
179 (define %extlinux-gpt-installation-script
180 ;; Shell script of a simple installation.
181 ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
182 ;; we make sure to pass -O '^64bit' to mkfs.
188 export GUIX_BUILD_OPTIONS=--no-grafts
190 parted --script /dev/vdb mklabel gpt \\
191 mkpart ext2 1M 1.6G \\
193 mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
196 herd start cow-store /mnt
198 cp /etc/target-config.scm /mnt/etc/config.scm
199 guix system init /mnt/etc/config.scm /mnt --no-substitutes
203 (define* (run-install target-os target-os-source
205 (script %simple-installation-script)
208 (os (marionette-operating-system
210 ;; Since the image has no network access, use the
211 ;; current Guix so the store items we need are in
212 ;; the image and add packages provided.
213 (inherit (operating-system-add-packages
214 (operating-system-with-current-guix
217 (kernel-arguments '("console=ttyS0")))
218 #:imported-modules '((gnu services herd)
219 (gnu installer tests)
220 (guix combinators))))
221 (installation-image-type 'raw)
222 (install-size 'guess)
223 (target-size (* 2200 MiB)))
224 "Run SCRIPT (a shell script following the system installation procedure) in
225 OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
226 the installed system. The packages specified in PACKAGES will be appended to
227 packages defined in installation-os."
229 (mlet* %store-monad ((_ (set-grafting #f))
230 (system (current-system))
232 ;; Since the installation system has no network access,
233 ;; we cheat a little bit by adding TARGET to its GC
234 ;; roots. This way, we know 'guix system init' will
235 ;; succeed. Also add guile-final, which is pulled in
236 ;; through provenance.drv and may not always be present.
237 (target (operating-system-derivation target-os))
240 (operating-system-with-gc-roots
241 os (list target guile-final))
242 #:type (lookup-image-type-by-name
243 installation-image-type)))
250 ;; Don't provide substitutes; too big.
251 (substitutable? #f)))))
253 (with-imported-modules '((guix build utils)
254 (gnu build marionette))
256 (use-modules (guix build utils)
257 (gnu build marionette))
259 (set-path-environment-variable "PATH" '("bin")
260 (list #$qemu-minimal))
262 (system* "qemu-img" "create" "-f" "qcow2"
263 #$output #$(number->string target-size))
267 `(,(which #$(qemu-command system))
271 ((eq? 'raw installation-image-type)
273 ,(string-append "file=" #$image
274 ",if=virtio,readonly")))
275 ((eq? 'uncompressed-iso9660 installation-image-type)
276 #~("-cdrom" #$image))
279 "unsupported installation-image-type:"
280 installation-image-type)))
282 ,(string-append "file=" #$output ",if=virtio")
283 ,@(if (file-exists? "/dev/kvm")
287 (pk 'uname (marionette-eval '(uname) marionette))
290 (marionette-eval '(begin
291 (use-modules (gnu services herd))
295 (when #$(->bool script)
296 (marionette-eval '(call-with-output-file "/etc/target-config.scm"
298 (write '#$target-os-source port)))
301 ;; Run SCRIPT. It typically invokes 'reboot' as a last step and
302 ;; thus normally gets killed with SIGTERM by PID 1.
303 (let ((status (marionette-eval '(system #$script) marionette)))
304 (exit (or (eof-object? status)
305 (equal? (status:term-sig status) SIGTERM)
306 (equal? (status:exit-val status) 0)))))
308 (when #$(->bool gui-test)
309 (wait-for-unix-socket "/var/guix/installer-socket"
311 (format #t "installer socket ready~%")
313 (exit #$(and gui-test
314 (gui-test #~marionette)))))))
316 (gexp->derivation "installation" install
317 #:substitutable? #f))) ;too big
319 (define* (qemu-command/writable-image image #:key (memory-size 256))
320 "Return as a monadic value the command to run QEMU on a writable copy of
321 IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
322 (mlet %store-monad ((system (current-system)))
323 (return #~(let ((image #$image))
324 ;; First we need a writable copy of the image.
325 (format #t "creating writable image from '~a'...~%" image)
326 (unless (zero? (system* #+(file-append qemu-minimal
328 "create" "-f" "qcow2"
330 (string-append "backing_file=" image)
332 (error "failed to create writable QEMU image" image))
334 (chmod "disk.img" #o644)
335 `(,(string-append #$qemu-minimal "/bin/"
336 #$(qemu-command system))
337 ,@(if (file-exists? "/dev/kvm")
340 "-no-reboot" "-m" #$(number->string memory-size)
341 "-drive" "file=disk.img,if=virtio")))))
343 (define %test-installed-os
345 (name "installed-os")
347 "Test basic functionality of an OS installed like one would do by hand.
348 This test is expensive in terms of CPU and storage usage since we need to
349 build (current-guix) and then store a couple of full system images.")
351 (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
352 (command (qemu-command/writable-image image)))
353 (run-basic-test %minimal-os command
356 (define %test-installed-extlinux-os
358 (name "installed-extlinux-os")
360 "Test basic functionality of an OS booted with an extlinux bootloader. As
361 per %test-installed-os, this test is expensive in terms of CPU and storage.")
363 (mlet* %store-monad ((image (run-install %minimal-extlinux-os
364 %minimal-extlinux-os-source
368 %extlinux-gpt-installation-script))
369 (command (qemu-command/writable-image image)))
370 (run-basic-test %minimal-extlinux-os command
371 "installed-extlinux-os")))))
375 ;;; Installation through an ISO image.
378 (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
379 ;; The OS we want to install.
380 (use-modules (gnu) (gnu tests) (srfi srfi-1))
383 (host-name "liberigilo")
384 (timezone "Europe/Paris")
385 (locale "en_US.UTF-8")
387 (bootloader (bootloader-configuration
388 (bootloader grub-bootloader)
389 (target "/dev/vda")))
390 (kernel-arguments '("console=ttyS0"))
391 (file-systems (cons (file-system
392 (device (file-system-label "my-root"))
396 (users (cons (user-account
398 (comment "Bob's sister")
400 (supplementary-groups '("wheel" "audio" "video")))
401 %base-user-accounts))
402 (services (cons (service marionette-service-type
403 (marionette-configuration
404 (imported-modules '((gnu services herd)
406 (guix combinators)))))
409 (define %simple-installation-script-for-/dev/vda
410 ;; Shell script of a simple installation.
416 export GUIX_BUILD_OPTIONS=--no-grafts
418 parted --script /dev/vda mklabel gpt \\
419 mkpart primary ext2 1M 3M \\
420 mkpart primary ext2 3M 1.6G \\
423 mkfs.ext4 -L my-root /dev/vda2
426 herd start cow-store /mnt
428 cp /etc/target-config.scm /mnt/etc/config.scm
429 guix system init /mnt/etc/config.scm /mnt --no-substitutes
433 (define %test-iso-image-installer
435 (name "iso-image-installer")
439 (mlet* %store-monad ((image (run-install
441 %minimal-os-on-vda-source
443 %simple-installation-script-for-/dev/vda
444 #:installation-image-type
445 'uncompressed-iso9660))
446 (command (qemu-command/writable-image image)))
447 (run-basic-test %minimal-os-on-vda command name)))))
454 (define-os-with-source (%separate-home-os %separate-home-os-source)
455 ;; The OS we want to install.
456 (use-modules (gnu) (gnu tests) (srfi srfi-1))
459 (host-name "liberigilo")
460 (timezone "Europe/Paris")
461 (locale "en_US.utf8")
463 (bootloader (bootloader-configuration
464 (bootloader grub-bootloader)
465 (target "/dev/vdb")))
466 (kernel-arguments '("console=ttyS0"))
467 (file-systems (cons* (file-system
468 (device (file-system-label "my-root"))
473 (mount-point "/home")
476 (users (cons* (user-account
482 %base-user-accounts))
483 (services (cons (service marionette-service-type
484 (marionette-configuration
485 (imported-modules '((gnu services herd)
486 (guix combinators)))))
489 (define %test-separate-home-os
491 (name "separate-home-os")
493 "Test basic functionality of an installed OS with a separate /home
494 partition. In particular, home directories must be correctly created (see
495 <https://bugs.gnu.org/21108>).")
497 (mlet* %store-monad ((image (run-install %separate-home-os
498 %separate-home-os-source
500 %simple-installation-script))
501 (command (qemu-command/writable-image image)))
502 (run-basic-test %separate-home-os command "separate-home-os")))))
506 ;;; Separate /gnu/store partition.
509 (define-os-with-source (%separate-store-os %separate-store-os-source)
510 ;; The OS we want to install.
511 (use-modules (gnu) (gnu tests) (srfi srfi-1))
514 (host-name "liberigilo")
515 (timezone "Europe/Paris")
516 (locale "en_US.UTF-8")
518 (bootloader (bootloader-configuration
519 (bootloader grub-bootloader)
520 (target "/dev/vdb")))
521 (kernel-arguments '("console=ttyS0"))
522 (file-systems (cons* (file-system
523 (device (file-system-label "root-fs"))
527 (device (file-system-label "store-fs"))
531 (users %base-user-accounts)
532 (services (cons (service marionette-service-type
533 (marionette-configuration
534 (imported-modules '((gnu services herd)
535 (guix combinators)))))
538 (define %separate-store-installation-script
539 ;; Installation with a separate /gnu partition.
545 export GUIX_BUILD_OPTIONS=--no-grafts
547 parted --script /dev/vdb mklabel gpt \\
548 mkpart primary ext2 1M 3M \\
549 mkpart primary ext2 3M 400M \\
550 mkpart primary ext2 400M 2.1G \\
553 mkfs.ext4 -L root-fs /dev/vdb2
554 mkfs.ext4 -L store-fs /dev/vdb3
557 mount /dev/vdb3 /mnt/gnu
560 herd start cow-store /mnt
562 cp /etc/target-config.scm /mnt/etc/config.scm
563 guix system init /mnt/etc/config.scm /mnt --no-substitutes
567 (define %test-separate-store-os
569 (name "separate-store-os")
571 "Test basic functionality of an OS installed like one would do by hand,
572 where /gnu lives on a separate partition.")
574 (mlet* %store-monad ((image (run-install %separate-store-os
575 %separate-store-os-source
577 %separate-store-installation-script))
578 (command (qemu-command/writable-image image)))
579 (run-basic-test %separate-store-os command "separate-store-os")))))
583 ;;; RAID root device.
586 (define-os-with-source (%raid-root-os %raid-root-os-source)
587 ;; An OS whose root partition is a RAID partition.
588 (use-modules (gnu) (gnu tests))
591 (host-name "raidified")
592 (timezone "Europe/Paris")
593 (locale "en_US.utf8")
595 (bootloader (bootloader-configuration
596 (bootloader grub-bootloader)
597 (target "/dev/vdb")))
598 (kernel-arguments '("console=ttyS0"))
600 ;; Add a kernel module for RAID-1 (aka. "mirror").
601 (initrd-modules (cons "raid1" %base-initrd-modules))
603 (mapped-devices (list (mapped-device
604 (source (list "/dev/vda2" "/dev/vda3"))
606 (type raid-device-mapping))))
607 (file-systems (cons (file-system
608 (device (file-system-label "root-fs"))
611 (dependencies mapped-devices))
613 (users %base-user-accounts)
614 (services (cons (service marionette-service-type
615 (marionette-configuration
616 (imported-modules '((gnu services herd)
617 (guix combinators)))))
620 (define %raid-root-installation-script
621 ;; Installation with a separate /gnu partition. See
622 ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
629 export GUIX_BUILD_OPTIONS=--no-grafts
630 parted --script /dev/vdb mklabel gpt \\
631 mkpart primary ext2 1M 3M \\
632 mkpart primary ext2 3M 1.6G \\
633 mkpart primary ext2 1.6G 3.2G \\
636 yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
638 mkfs.ext4 -L root-fs /dev/md0
641 herd start cow-store /mnt
643 cp /etc/target-config.scm /mnt/etc/config.scm
644 guix system init /mnt/etc/config.scm /mnt --no-substitutes
648 (define %test-raid-root-os
650 (name "raid-root-os")
652 "Test functionality of an OS installed with a RAID root partition managed
655 (mlet* %store-monad ((image (run-install %raid-root-os
658 %raid-root-installation-script
659 #:target-size (* 3200 MiB)))
660 (command (qemu-command/writable-image image)))
661 (run-basic-test %raid-root-os
662 `(,@command) "raid-root-os")))))
666 ;;; LUKS-encrypted root file system.
669 (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
670 ;; The OS we want to install.
671 (use-modules (gnu) (gnu tests) (srfi srfi-1))
674 (host-name "liberigilo")
675 (timezone "Europe/Paris")
676 (locale "en_US.UTF-8")
678 (bootloader (bootloader-configuration
679 (bootloader grub-bootloader)
680 (target "/dev/vdb")))
682 ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
683 ;; detection logic in 'enter-luks-passphrase'.
685 (mapped-devices (list (mapped-device
686 (source (uuid "12345678-1234-1234-1234-123456789abc"))
687 (target "the-root-device")
688 (type luks-device-mapping))))
689 (file-systems (cons (file-system
690 (device "/dev/mapper/the-root-device")
694 (users (cons (user-account
697 (supplementary-groups '("wheel" "audio" "video")))
698 %base-user-accounts))
699 (services (cons (service marionette-service-type
700 (marionette-configuration
701 (imported-modules '((gnu services herd)
702 (guix combinators)))))
705 (define %luks-passphrase
706 ;; LUKS encryption passphrase used in tests.
709 (define %encrypted-root-installation-script
710 ;; Shell script of a simple installation.
716 export GUIX_BUILD_OPTIONS=--no-grafts
717 ls -l /run/current-system/gc-roots
718 parted --script /dev/vdb mklabel gpt \\
719 mkpart primary ext2 1M 3M \\
720 mkpart primary ext2 3M 1.6G \\
723 echo -n " %luks-passphrase " | \\
724 cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
725 echo -n " %luks-passphrase " | \\
726 cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
727 mkfs.ext4 -L my-root /dev/mapper/the-root-device
728 mount LABEL=my-root /mnt
729 herd start cow-store /mnt
731 cp /etc/target-config.scm /mnt/etc/config.scm
732 guix system build /mnt/etc/config.scm
733 guix system init /mnt/etc/config.scm /mnt --no-substitutes
737 (define (enter-luks-passphrase marionette)
738 "Return a gexp to be inserted in the basic system test running on MARIONETTE
739 to enter the LUKS passphrase."
740 (let ((ocrad (file-append ocrad "/bin/ocrad")))
742 (define (passphrase-prompt? text)
743 (string-contains (pk 'screen-text text) "Enter pass"))
745 (define (bios-boot-screen? text)
746 ;; Return true if TEXT corresponds to the boot screen, before GRUB's
748 (string-prefix? "SeaBIOS" text))
750 (test-assert "enter LUKS passphrase for GRUB"
752 ;; At this point we have no choice but to use OCR to determine
753 ;; when the passphrase should be entered.
754 (wait-for-screen-text #$marionette passphrase-prompt?
756 (marionette-type #$(string-append %luks-passphrase "\n")
759 ;; Now wait until we leave the boot screen. This is necessary so
760 ;; we can then be sure we match the "Enter passphrase" prompt from
761 ;; 'cryptsetup', in the initrd.
762 (wait-for-screen-text #$marionette (negate bios-boot-screen?)
766 (test-assert "enter LUKS passphrase for the initrd"
768 ;; XXX: Here we use OCR as well but we could instead use QEMU
769 ;; '-serial stdio' and run it in an input pipe,
770 (wait-for-screen-text #$marionette passphrase-prompt?
773 (marionette-type #$(string-append %luks-passphrase "\n")
776 ;; Take a screenshot for debugging purposes.
777 (marionette-control (string-append "screendump " #$output
778 "/post-initrd-passphrase.ppm")
781 (define %test-encrypted-root-os
783 (name "encrypted-root-os")
785 "Test basic functionality of an OS installed like one would do by hand.
786 This test is expensive in terms of CPU and storage usage since we need to
787 build (current-guix) and then store a couple of full system images.")
789 (mlet* %store-monad ((image (run-install %encrypted-root-os
790 %encrypted-root-os-source
792 %encrypted-root-installation-script))
793 (command (qemu-command/writable-image image)))
794 (run-basic-test %encrypted-root-os command "encrypted-root-os"
795 #:initialization enter-luks-passphrase)))))
799 ;;; Btrfs root file system.
802 (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
803 ;; The OS we want to install.
804 (use-modules (gnu) (gnu tests) (srfi srfi-1))
807 (host-name "liberigilo")
808 (timezone "Europe/Paris")
809 (locale "en_US.UTF-8")
811 (bootloader (bootloader-configuration
812 (bootloader grub-bootloader)
813 (target "/dev/vdb")))
814 (kernel-arguments '("console=ttyS0"))
815 (file-systems (cons (file-system
816 (device (file-system-label "my-root"))
820 (users (cons (user-account
823 (supplementary-groups '("wheel" "audio" "video")))
824 %base-user-accounts))
825 (services (cons (service marionette-service-type
826 (marionette-configuration
827 (imported-modules '((gnu services herd)
828 (guix combinators)))))
831 (define %btrfs-root-installation-script
832 ;; Shell script of a simple installation.
838 export GUIX_BUILD_OPTIONS=--no-grafts
839 ls -l /run/current-system/gc-roots
840 parted --script /dev/vdb mklabel gpt \\
841 mkpart primary ext2 1M 3M \\
842 mkpart primary ext2 3M 2G \\
845 mkfs.btrfs -L my-root /dev/vdb2
847 btrfs subvolume create /mnt/home
848 herd start cow-store /mnt
850 cp /etc/target-config.scm /mnt/etc/config.scm
851 guix system build /mnt/etc/config.scm
852 guix system init /mnt/etc/config.scm /mnt --no-substitutes
856 (define %test-btrfs-root-os
858 (name "btrfs-root-os")
860 "Test basic functionality of an OS installed like one would do by hand.
861 This test is expensive in terms of CPU and storage usage since we need to
862 build (current-guix) and then store a couple of full system images.")
864 (mlet* %store-monad ((image (run-install %btrfs-root-os
865 %btrfs-root-os-source
867 %btrfs-root-installation-script))
868 (command (qemu-command/writable-image image)))
869 (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
873 ;;; Btrfs root file system on a subvolume.
876 (define-os-with-source (%btrfs-root-on-subvolume-os
877 %btrfs-root-on-subvolume-os-source)
878 ;; The OS we want to install.
879 (use-modules (gnu) (gnu tests) (srfi srfi-1))
883 (timezone "America/Montreal")
884 (locale "en_US.UTF-8")
885 (bootloader (bootloader-configuration
886 (bootloader grub-bootloader)
887 (target "/dev/vdb")))
888 (kernel-arguments '("console=ttyS0"))
889 (file-systems (cons* (file-system
890 (device (file-system-label "btrfs-pool"))
892 (options "subvol=rootfs,compress=zstd")
895 (device (file-system-label "btrfs-pool"))
896 (mount-point "/home")
897 (options "subvol=homefs,compress=lzo")
900 (users (cons (user-account
903 (supplementary-groups '("wheel" "audio" "video")))
904 %base-user-accounts))
905 (services (cons (service marionette-service-type
906 (marionette-configuration
907 (imported-modules '((gnu services herd)
908 (guix combinators)))))
911 (define %btrfs-root-on-subvolume-installation-script
912 ;; Shell script of a simple installation.
918 export GUIX_BUILD_OPTIONS=--no-grafts
919 ls -l /run/current-system/gc-roots
920 parted --script /dev/vdb mklabel gpt \\
921 mkpart primary ext2 1M 3M \\
922 mkpart primary ext2 3M 2G \\
926 # Setup the top level Btrfs file system with its subvolume.
927 mkfs.btrfs -L btrfs-pool /dev/vdb2
929 btrfs subvolume create /mnt/rootfs
930 btrfs subvolume create /mnt/homefs
933 # Mount the subvolumes, ready for installation.
934 mount LABEL=btrfs-pool -o 'subvol=rootfs,compress=zstd' /mnt
936 mount LABEL=btrfs-pool -o 'subvol=homefs,compress=zstd' /mnt/home
938 herd start cow-store /mnt
940 cp /etc/target-config.scm /mnt/etc/config.scm
941 guix system build /mnt/etc/config.scm
942 guix system init /mnt/etc/config.scm /mnt --no-substitutes
946 (define %test-btrfs-root-on-subvolume-os
948 (name "btrfs-root-on-subvolume-os")
950 "Test basic functionality of an OS installed like one would do by hand.
951 This test is expensive in terms of CPU and storage usage since we need to
952 build (current-guix) and then store a couple of full system images.")
956 (run-install %btrfs-root-on-subvolume-os
957 %btrfs-root-on-subvolume-os-source
959 %btrfs-root-on-subvolume-installation-script))
960 (command (qemu-command/writable-image image)))
961 (run-basic-test %btrfs-root-on-subvolume-os command
962 "btrfs-root-on-subvolume-os")))))
966 ;;; JFS root file system.
969 (define-os-with-source (%jfs-root-os %jfs-root-os-source)
970 ;; The OS we want to install.
971 (use-modules (gnu) (gnu tests) (srfi srfi-1))
974 (host-name "liberigilo")
975 (timezone "Europe/Paris")
976 (locale "en_US.UTF-8")
978 (bootloader (bootloader-configuration
979 (bootloader grub-bootloader)
980 (target "/dev/vdb")))
981 (kernel-arguments '("console=ttyS0"))
982 (file-systems (cons (file-system
983 (device (file-system-label "my-root"))
987 (users (cons (user-account
990 (supplementary-groups '("wheel" "audio" "video")))
991 %base-user-accounts))
992 (services (cons (service marionette-service-type
993 (marionette-configuration
994 (imported-modules '((gnu services herd)
995 (guix combinators)))))
998 (define %jfs-root-installation-script
999 ;; Shell script of a simple installation.
1005 export GUIX_BUILD_OPTIONS=--no-grafts
1006 ls -l /run/current-system/gc-roots
1007 parted --script /dev/vdb mklabel gpt \\
1008 mkpart primary ext2 1M 3M \\
1009 mkpart primary ext2 3M 2G \\
1012 jfs_mkfs -L my-root -q /dev/vdb2
1013 mount /dev/vdb2 /mnt
1014 herd start cow-store /mnt
1016 cp /etc/target-config.scm /mnt/etc/config.scm
1017 guix system build /mnt/etc/config.scm
1018 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1022 (define %test-jfs-root-os
1024 (name "jfs-root-os")
1026 "Test basic functionality of an OS installed like one would do by hand.
1027 This test is expensive in terms of CPU and storage usage since we need to
1028 build (current-guix) and then store a couple of full system images.")
1030 (mlet* %store-monad ((image (run-install %jfs-root-os
1033 %jfs-root-installation-script))
1034 (command (qemu-command/writable-image image)))
1035 (run-basic-test %jfs-root-os command "jfs-root-os")))))
1039 ;;; F2FS root file system.
1042 (define-os-with-source (%f2fs-root-os %f2fs-root-os-source)
1043 ;; The OS we want to install.
1044 (use-modules (gnu) (gnu tests) (srfi srfi-1))
1047 (host-name "liberigilo")
1048 (timezone "Europe/Paris")
1049 (locale "en_US.UTF-8")
1051 (bootloader (bootloader-configuration
1052 (bootloader grub-bootloader)
1053 (target "/dev/vdb")))
1054 (kernel-arguments '("console=ttyS0"))
1055 (file-systems (cons (file-system
1056 (device (file-system-label "my-root"))
1059 %base-file-systems))
1060 (users (cons (user-account
1063 (supplementary-groups '("wheel" "audio" "video")))
1064 %base-user-accounts))
1065 (services (cons (service marionette-service-type
1066 (marionette-configuration
1067 (imported-modules '((gnu services herd)
1068 (guix combinators)))))
1071 (define %f2fs-root-installation-script
1072 ;; Shell script of a simple installation.
1078 export GUIX_BUILD_OPTIONS=--no-grafts
1079 ls -l /run/current-system/gc-roots
1080 parted --script /dev/vdb mklabel gpt \\
1081 mkpart primary ext2 1M 3M \\
1082 mkpart primary ext2 3M 2G \\
1085 mkfs.f2fs -l my-root -q /dev/vdb2
1086 mount /dev/vdb2 /mnt
1087 herd start cow-store /mnt
1089 cp /etc/target-config.scm /mnt/etc/config.scm
1090 guix system build /mnt/etc/config.scm
1091 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1095 (define %test-f2fs-root-os
1097 (name "f2fs-root-os")
1099 "Test basic functionality of an OS installed like one would do by hand.
1100 This test is expensive in terms of CPU and storage usage since we need to
1101 build (current-guix) and then store a couple of full system images.")
1103 (mlet* %store-monad ((image (run-install %f2fs-root-os
1104 %f2fs-root-os-source
1106 %f2fs-root-installation-script))
1107 (command (qemu-command/writable-image image)))
1108 (run-basic-test %f2fs-root-os command "f2fs-root-os")))))
1112 ;;; Installation through the graphical interface.
1115 (define %syslog-conf
1116 ;; Syslog configuration that dumps to /dev/console, so we can see the
1117 ;; installer's messages during the test.
1118 (computed-file "syslog.conf"
1120 (copy-file #$%default-syslog.conf #$output)
1121 (chmod #$output #o644)
1122 (let ((port (open-file #$output "a")))
1123 (display "\n*.info /dev/console\n" port)
1126 (define (operating-system-with-console-syslog os)
1127 "Return OS with a syslog service that writes to /dev/console."
1130 (services (modify-services (operating-system-user-services os)
1131 (syslog-service-type config
1133 (syslog-configuration
1135 (config-file %syslog-conf)))))))
1137 (define %root-password "foo")
1139 (define* (gui-test-program marionette
1144 (define (screenshot file)
1145 (marionette-control (string-append "screendump " file)
1148 (define-syntax-rule (marionette-eval* exp marionette)
1149 (or (marionette-eval exp marionette)
1150 (throw 'marionette-eval-failure 'exp)))
1152 (setvbuf (current-output-port) 'none)
1153 (setvbuf (current-error-port) 'none)
1155 (marionette-eval* '(use-modules (gnu installer tests))
1158 ;; Arrange so that 'converse' prints debugging output to the console.
1159 (marionette-eval* '(let ((console (open-output-file "/dev/console")))
1160 (setvbuf console 'none)
1161 (conversation-log-port console))
1164 ;; Tell the installer to not wait for the Connman "online" status.
1165 (marionette-eval* '(call-with-output-file "/tmp/installer-assume-online"
1169 ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
1171 (marionette-eval* '(call-with-output-file
1172 "/tmp/installer-system-init-options"
1174 (write '("--no-grafts" "--no-substitutes")
1178 (marionette-eval* '(define installer-socket
1179 (open-installer-socket))
1181 (screenshot "installer-start.ppm")
1183 (marionette-eval* '(choose-locale+keyboard installer-socket)
1185 (screenshot "installer-locale.ppm")
1187 ;; Choose the host name that the "basic" test expects.
1188 (marionette-eval* '(enter-host-name+passwords installer-socket
1189 #:host-name "liberigilo"
1196 (screenshot "installer-services.ppm")
1198 (marionette-eval* '(choose-services installer-socket
1199 #:choose-desktop-environment?
1201 #:choose-network-service?
1204 (screenshot "installer-partitioning.ppm")
1206 (marionette-eval* '(choose-partitioning installer-socket
1207 #:encrypted? #$encrypted?
1208 #:passphrase #$%luks-passphrase)
1210 (screenshot "installer-run.ppm")
1212 (marionette-eval* '(conclude-installation installer-socket)
1218 (define %extra-packages
1219 ;; Packages needed when installing with an encrypted root.
1221 lvm2-static cryptsetup-static e2fsck/static
1224 (define installation-os-for-gui-tests
1225 ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
1226 ;; target OS, as well as syslog output redirected to the console so we can
1227 ;; see what the installer is up to.
1228 (marionette-operating-system
1230 (inherit (operating-system-with-console-syslog
1231 (operating-system-add-packages
1232 (operating-system-with-current-guix
1235 (kernel-arguments '("console=ttyS0")))
1236 #:imported-modules '((gnu services herd)
1237 (gnu installer tests)
1238 (guix combinators))))
1240 (define* (installation-target-os-for-gui-tests
1241 #:key (encrypted? #f))
1243 (inherit %minimal-os-on-vda)
1244 (users (append (list (user-account
1246 (comment "Bob's sister")
1248 (supplementary-groups
1249 '("wheel" "audio" "video")))
1252 (comment "Alice's brother")
1254 (supplementary-groups
1255 '("wheel" "audio" "video"))))
1256 %base-user-accounts))
1257 ;; The installer does not create a swap device in guided mode with
1258 ;; encryption support.
1259 (swap-devices (if encrypted? '() '("/dev/vda2")))
1260 (services (cons (service dhcp-client-service-type)
1261 (operating-system-user-services %minimal-os-on-vda)))))
1263 (define* (installation-target-desktop-os-for-gui-tests
1264 #:key (encrypted? #f))
1266 (inherit (installation-target-os-for-gui-tests
1267 #:encrypted? encrypted?))
1268 (keyboard-layout (keyboard-layout "us" "altgr-intl"))
1270 ;; Make sure that all the packages and services that may be used by the
1271 ;; graphical installer are available.
1273 (list openbox awesome i3-wm i3status
1274 dmenu st ratpoison xterm)
1278 (list (service gnome-desktop-service-type)
1279 (service xfce-desktop-service-type)
1280 (service mate-desktop-service-type)
1281 (service enlightenment-desktop-service-type)
1282 (set-xorg-configuration
1284 (keyboard-layout keyboard-layout)))
1285 (service marionette-service-type
1286 (marionette-configuration
1287 (imported-modules '((gnu services herd)
1289 (guix combinators))))))
1290 %desktop-services))))
1292 (define* (guided-installation-test name
1297 (install-size 'guess)
1298 (target-size (* 2200 MiB)))
1302 "Install an OS using the graphical installer and test it.")
1305 ((image (run-install target-os '(this is unused)
1307 #:os installation-os-for-gui-tests
1308 #:install-size install-size
1309 #:target-size target-size
1310 #:installation-image-type
1311 'uncompressed-iso9660
1313 (lambda (marionette)
1317 #:encrypted? encrypted?))))
1318 (command (qemu-command/writable-image image #:memory-size 512)))
1319 (run-basic-test target-os command name
1320 #:initialization (and encrypted? enter-luks-passphrase)
1321 #:root-password %root-password
1322 #:desktop? desktop?)))))
1324 (define %test-gui-installed-os
1325 (guided-installation-test
1327 #:target-os (installation-target-os-for-gui-tests)))
1329 (define %test-gui-installed-os-encrypted
1330 (guided-installation-test
1331 "gui-installed-os-encrypted"
1333 #:target-os (installation-target-os-for-gui-tests
1336 ;; Building a desktop image is very time and space consuming. Install all
1337 ;; desktop environments in a single test to reduce the overhead.
1338 (define %test-gui-installed-desktop-os-encrypted
1339 (guided-installation-test "gui-installed-desktop-os-encrypted"
1343 (installation-target-desktop-os-for-gui-tests
1345 ;; XXX: The disk-image size guess is too low. Use
1346 ;; a constant value until this is fixed.
1347 #:install-size (* 8000 MiB)
1348 #:target-size (* 9000 MiB)))
1350 ;;; install.scm ends here