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>
7 ;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
9 ;;; This file is part of GNU Guix.
11 ;;; GNU Guix is free software; you can redistribute it and/or modify it
12 ;;; under the terms of the GNU General Public License as published by
13 ;;; the Free Software Foundation; either version 3 of the License, or (at
14 ;;; your option) any later version.
16 ;;; GNU Guix is distributed in the hope that it will be useful, but
17 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;;; GNU General Public License for more details.
21 ;;; You should have received a copy of the GNU General Public License
22 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
24 (define-module (gnu tests install)
26 #:use-module (gnu bootloader extlinux)
27 #:use-module (gnu image)
28 #:use-module (gnu tests)
29 #:use-module (gnu tests base)
30 #:use-module (gnu system)
31 #:use-module (gnu system image)
32 #:use-module (gnu system install)
33 #:use-module (gnu system vm)
34 #:use-module ((gnu build vm) #:select (qemu-command))
35 #:use-module (gnu packages admin)
36 #:use-module (gnu packages bootloaders)
37 #:use-module (gnu packages commencement) ;for 'guile-final'
38 #:use-module (gnu packages cryptsetup)
39 #:use-module (gnu packages emacs)
40 #:use-module (gnu packages emacs-xyz)
41 #:use-module (gnu packages linux)
42 #:use-module (gnu packages ocr)
43 #:use-module (gnu packages openbox)
44 #:use-module (gnu packages package-management)
45 #:use-module (gnu packages ratpoison)
46 #:use-module (gnu packages suckless)
47 #:use-module (gnu packages virtualization)
48 #:use-module (gnu packages wm)
49 #:use-module (gnu packages xorg)
50 #:use-module (gnu services desktop)
51 #:use-module (gnu services networking)
52 #:use-module (gnu services xorg)
53 #:use-module (guix store)
54 #:use-module (guix monads)
55 #:use-module (guix packages)
56 #:use-module (guix grafts)
57 #:use-module (guix gexp)
58 #:use-module (guix utils)
59 #:use-module (srfi srfi-1)
60 #:export (%test-installed-os
61 %test-installed-extlinux-os
62 %test-iso-image-installer
63 %test-separate-store-os
64 %test-separate-home-os
66 %test-encrypted-root-os
67 %test-encrypted-root-not-boot-os
69 %test-btrfs-root-on-subvolume-os
70 %test-btrfs-raid-root-os
73 %test-lvm-separate-home-os
75 %test-gui-installed-os
76 %test-gui-installed-os-encrypted
77 %test-gui-installed-desktop-os-encrypted))
81 ;;; Test the installation of Guix using the documented approach at the
86 (define-os-with-source (%minimal-os %minimal-os-source)
87 ;; The OS we want to install.
88 (use-modules (gnu) (gnu tests) (srfi srfi-1))
91 (host-name "liberigilo")
92 (timezone "Europe/Paris")
93 (locale "en_US.UTF-8")
95 (bootloader (bootloader-configuration
96 (bootloader grub-bootloader)
98 (kernel-arguments '("console=ttyS0"))
99 (file-systems (cons (file-system
100 (device (file-system-label "my-root"))
104 (users (cons (user-account
106 (comment "Bob's sister")
108 (supplementary-groups '("wheel" "audio" "video")))
109 %base-user-accounts))
110 (services (cons (service marionette-service-type
111 (marionette-configuration
112 (imported-modules '((gnu services herd)
114 (guix combinators)))))
117 (define (operating-system-add-packages os packages)
118 "Append PACKAGES to OS packages list."
121 (packages (append packages (operating-system-packages os)))))
123 (define-os-with-source (%minimal-extlinux-os
124 %minimal-extlinux-os-source)
125 (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
129 (host-name "liberigilo")
130 (timezone "Europe/Paris")
131 (locale "en_US.UTF-8")
133 (bootloader (bootloader-configuration
134 (bootloader extlinux-bootloader-gpt)
135 (target "/dev/vdb")))
136 (kernel-arguments '("console=ttyS0"))
137 (file-systems (cons (file-system
138 (device (file-system-label "my-root"))
142 (services (cons (service marionette-service-type
143 (marionette-configuration
144 (imported-modules '((gnu services herd)
145 (guix combinators)))))
148 (define (operating-system-with-current-guix os)
149 "Return a variant of OS that uses the current Guix."
152 (services (modify-services (operating-system-user-services os)
153 (guix-service-type config =>
156 (guix (current-guix))))))))
159 (define MiB (expt 2 20))
161 (define %simple-installation-script
162 ;; Shell script of a simple installation.
168 export GUIX_BUILD_OPTIONS=--no-grafts
170 parted --script /dev/vdb mklabel gpt \\
171 mkpart primary ext2 1M 3M \\
172 mkpart primary ext2 3M 1.6G \\
175 mkfs.ext4 -L my-root /dev/vdb2
178 herd start cow-store /mnt
180 cp /etc/target-config.scm /mnt/etc/config.scm
181 guix system init /mnt/etc/config.scm /mnt --no-substitutes
185 (define %extlinux-gpt-installation-script
186 ;; Shell script of a simple installation.
187 ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
188 ;; we make sure to pass -O '^64bit' to mkfs.
194 export GUIX_BUILD_OPTIONS=--no-grafts
196 parted --script /dev/vdb mklabel gpt \\
197 mkpart ext2 1M 1.6G \\
199 mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
202 herd start cow-store /mnt
204 cp /etc/target-config.scm /mnt/etc/config.scm
205 guix system init /mnt/etc/config.scm /mnt --no-substitutes
209 (define* (run-install target-os target-os-source
211 (script %simple-installation-script)
214 (os (marionette-operating-system
216 ;; Since the image has no network access, use the
217 ;; current Guix so the store items we need are in
218 ;; the image and add packages provided.
219 (inherit (operating-system-add-packages
220 (operating-system-with-current-guix
223 (kernel-arguments '("console=ttyS0")))
224 #:imported-modules '((gnu services herd)
225 (gnu installer tests)
226 (guix combinators))))
227 (installation-image-type 'efi-raw)
228 (install-size 'guess)
229 (target-size (* 2200 MiB)))
230 "Run SCRIPT (a shell script following the system installation procedure) in
231 OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
232 the installed system. The packages specified in PACKAGES will be appended to
233 packages defined in installation-os."
235 (mlet* %store-monad ((_ (set-grafting #f))
236 (system (current-system))
238 ;; Since the installation system has no network access,
239 ;; we cheat a little bit by adding TARGET to its GC
240 ;; roots. This way, we know 'guix system init' will
241 ;; succeed. Also add guile-final, which is pulled in
242 ;; through provenance.drv and may not always be present.
243 (target (operating-system-derivation target-os))
246 (operating-system-with-gc-roots
247 os (list target guile-final))
248 #:type (lookup-image-type-by-name
249 installation-image-type)))
256 ;; Don't provide substitutes; too big.
257 (substitutable? #f)))))
259 (with-imported-modules '((guix build utils)
260 (gnu build marionette))
262 (use-modules (guix build utils)
263 (gnu build marionette))
265 (set-path-environment-variable "PATH" '("bin")
266 (list #$qemu-minimal))
268 (system* "qemu-img" "create" "-f" "qcow2"
269 #$output #$(number->string target-size))
273 `(,(which #$(qemu-command system))
277 ((eq? 'efi-raw installation-image-type)
279 ,(string-append "file=" #$image
280 ",if=virtio,readonly")))
281 ((eq? 'uncompressed-iso9660 installation-image-type)
282 #~("-cdrom" #$image))
285 "unsupported installation-image-type:"
286 installation-image-type)))
288 ,(string-append "file=" #$output ",if=virtio")
289 ,@(if (file-exists? "/dev/kvm")
293 (pk 'uname (marionette-eval '(uname) marionette))
296 (marionette-eval '(begin
297 (use-modules (gnu services herd))
301 (when #$(->bool script)
302 (marionette-eval '(call-with-output-file "/etc/target-config.scm"
304 (write '#$target-os-source port)))
307 ;; Run SCRIPT. It typically invokes 'reboot' as a last step and
308 ;; thus normally gets killed with SIGTERM by PID 1.
309 (let ((status (marionette-eval '(system #$script) marionette)))
310 (exit (or (eof-object? status)
311 (equal? (status:term-sig status) SIGTERM)
312 (equal? (status:exit-val status) 0)))))
314 (when #$(->bool gui-test)
315 (wait-for-unix-socket "/var/guix/installer-socket"
317 (format #t "installer socket ready~%")
319 (exit #$(and gui-test
320 (gui-test #~marionette)))))))
322 (gexp->derivation "installation" install
323 #:substitutable? #f))) ;too big
325 (define* (qemu-command/writable-image image #:key (memory-size 256))
326 "Return as a monadic value the command to run QEMU on a writable copy of
327 IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
328 (mlet %store-monad ((system (current-system)))
329 (return #~(let ((image #$image))
330 ;; First we need a writable copy of the image.
331 (format #t "creating writable image from '~a'...~%" image)
332 (unless (zero? (system* #+(file-append qemu-minimal
334 "create" "-f" "qcow2"
336 (string-append "backing_file=" image)
338 (error "failed to create writable QEMU image" image))
340 (chmod "disk.img" #o644)
341 `(,(string-append #$qemu-minimal "/bin/"
342 #$(qemu-command system))
343 ,@(if (file-exists? "/dev/kvm")
346 "-no-reboot" "-m" #$(number->string memory-size)
347 "-drive" "file=disk.img,if=virtio")))))
349 (define %test-installed-os
351 (name "installed-os")
353 "Test basic functionality of an OS installed like one would do by hand.
354 This test is expensive in terms of CPU and storage usage since we need to
355 build (current-guix) and then store a couple of full system images.")
357 (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
358 (command (qemu-command/writable-image image)))
359 (run-basic-test %minimal-os command
362 (define %test-installed-extlinux-os
364 (name "installed-extlinux-os")
366 "Test basic functionality of an OS booted with an extlinux bootloader. As
367 per %test-installed-os, this test is expensive in terms of CPU and storage.")
369 (mlet* %store-monad ((image (run-install %minimal-extlinux-os
370 %minimal-extlinux-os-source
374 %extlinux-gpt-installation-script))
375 (command (qemu-command/writable-image image)))
376 (run-basic-test %minimal-extlinux-os command
377 "installed-extlinux-os")))))
381 ;;; Installation through an ISO image.
384 (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
385 ;; The OS we want to install.
386 (use-modules (gnu) (gnu tests) (srfi srfi-1))
389 (host-name "liberigilo")
390 (timezone "Europe/Paris")
391 (locale "en_US.UTF-8")
393 (bootloader (bootloader-configuration
394 (bootloader grub-bootloader)
395 (target "/dev/vda")))
396 (kernel-arguments '("console=ttyS0"))
397 (file-systems (cons (file-system
398 (device (file-system-label "my-root"))
402 (users (cons (user-account
404 (comment "Bob's sister")
406 (supplementary-groups '("wheel" "audio" "video")))
407 %base-user-accounts))
408 (services (cons (service marionette-service-type
409 (marionette-configuration
410 (imported-modules '((gnu services herd)
412 (guix combinators)))))
415 (define %simple-installation-script-for-/dev/vda
416 ;; Shell script of a simple installation.
422 export GUIX_BUILD_OPTIONS=--no-grafts
424 parted --script /dev/vda mklabel gpt \\
425 mkpart primary ext2 1M 3M \\
426 mkpart primary ext2 3M 1.6G \\
429 mkfs.ext4 -L my-root /dev/vda2
432 herd start cow-store /mnt
434 cp /etc/target-config.scm /mnt/etc/config.scm
435 guix system init /mnt/etc/config.scm /mnt --no-substitutes
439 (define %test-iso-image-installer
441 (name "iso-image-installer")
445 (mlet* %store-monad ((image (run-install
447 %minimal-os-on-vda-source
449 %simple-installation-script-for-/dev/vda
450 #:installation-image-type
451 'uncompressed-iso9660))
452 (command (qemu-command/writable-image image)))
453 (run-basic-test %minimal-os-on-vda command name)))))
460 (define-os-with-source (%separate-home-os %separate-home-os-source)
461 ;; The OS we want to install.
462 (use-modules (gnu) (gnu tests) (srfi srfi-1))
465 (host-name "liberigilo")
466 (timezone "Europe/Paris")
467 (locale "en_US.utf8")
469 (bootloader (bootloader-configuration
470 (bootloader grub-bootloader)
471 (target "/dev/vdb")))
472 (kernel-arguments '("console=ttyS0"))
473 (file-systems (cons* (file-system
474 (device (file-system-label "my-root"))
479 (mount-point "/home")
482 (users (cons* (user-account
488 %base-user-accounts))
489 (services (cons (service marionette-service-type
490 (marionette-configuration
491 (imported-modules '((gnu services herd)
492 (guix combinators)))))
495 (define %test-separate-home-os
497 (name "separate-home-os")
499 "Test basic functionality of an installed OS with a separate /home
500 partition. In particular, home directories must be correctly created (see
501 <https://bugs.gnu.org/21108>).")
503 (mlet* %store-monad ((image (run-install %separate-home-os
504 %separate-home-os-source
506 %simple-installation-script))
507 (command (qemu-command/writable-image image)))
508 (run-basic-test %separate-home-os command "separate-home-os")))))
512 ;;; Separate /gnu/store partition.
515 (define-os-with-source (%separate-store-os %separate-store-os-source)
516 ;; The OS we want to install.
517 (use-modules (gnu) (gnu tests) (srfi srfi-1))
520 (host-name "liberigilo")
521 (timezone "Europe/Paris")
522 (locale "en_US.UTF-8")
524 (bootloader (bootloader-configuration
525 (bootloader grub-bootloader)
526 (target "/dev/vdb")))
527 (kernel-arguments '("console=ttyS0"))
528 (file-systems (cons* (file-system
529 (device (file-system-label "root-fs"))
533 (device (file-system-label "store-fs"))
537 (users %base-user-accounts)
538 (services (cons (service marionette-service-type
539 (marionette-configuration
540 (imported-modules '((gnu services herd)
541 (guix combinators)))))
544 (define %separate-store-installation-script
545 ;; Installation with a separate /gnu partition.
551 export GUIX_BUILD_OPTIONS=--no-grafts
553 parted --script /dev/vdb mklabel gpt \\
554 mkpart primary ext2 1M 3M \\
555 mkpart primary ext2 3M 400M \\
556 mkpart primary ext2 400M 2.1G \\
559 mkfs.ext4 -L root-fs /dev/vdb2
560 mkfs.ext4 -L store-fs /dev/vdb3
563 mount /dev/vdb3 /mnt/gnu
566 herd start cow-store /mnt
568 cp /etc/target-config.scm /mnt/etc/config.scm
569 guix system init /mnt/etc/config.scm /mnt --no-substitutes
573 (define %test-separate-store-os
575 (name "separate-store-os")
577 "Test basic functionality of an OS installed like one would do by hand,
578 where /gnu lives on a separate partition.")
580 (mlet* %store-monad ((image (run-install %separate-store-os
581 %separate-store-os-source
583 %separate-store-installation-script))
584 (command (qemu-command/writable-image image)))
585 (run-basic-test %separate-store-os command "separate-store-os")))))
589 ;;; RAID root device.
592 (define-os-with-source (%raid-root-os %raid-root-os-source)
593 ;; An OS whose root partition is a RAID partition.
594 (use-modules (gnu) (gnu tests))
597 (host-name "raidified")
598 (timezone "Europe/Paris")
599 (locale "en_US.utf8")
601 (bootloader (bootloader-configuration
602 (bootloader grub-bootloader)
603 (target "/dev/vdb")))
604 (kernel-arguments '("console=ttyS0"))
606 ;; Add a kernel module for RAID-1 (aka. "mirror").
607 (initrd-modules (cons "raid1" %base-initrd-modules))
609 (mapped-devices (list (mapped-device
610 (source (list "/dev/vda2" "/dev/vda3"))
612 (type raid-device-mapping))))
613 (file-systems (cons (file-system
614 (device (file-system-label "root-fs"))
617 (dependencies mapped-devices))
619 (users %base-user-accounts)
620 (services (cons (service marionette-service-type
621 (marionette-configuration
622 (imported-modules '((gnu services herd)
623 (guix combinators)))))
626 (define %raid-root-installation-script
627 ;; Installation with a separate /gnu partition. See
628 ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
635 export GUIX_BUILD_OPTIONS=--no-grafts
636 parted --script /dev/vdb mklabel gpt \\
637 mkpart primary ext2 1M 3M \\
638 mkpart primary ext2 3M 1.6G \\
639 mkpart primary ext2 1.6G 3.2G \\
642 yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
644 mkfs.ext4 -L root-fs /dev/md0
647 herd start cow-store /mnt
649 cp /etc/target-config.scm /mnt/etc/config.scm
650 guix system init /mnt/etc/config.scm /mnt --no-substitutes
654 (define %test-raid-root-os
656 (name "raid-root-os")
658 "Test functionality of an OS installed with a RAID root partition managed
661 (mlet* %store-monad ((image (run-install %raid-root-os
664 %raid-root-installation-script
665 #:target-size (* 3200 MiB)))
666 (command (qemu-command/writable-image image)))
667 (run-basic-test %raid-root-os
668 `(,@command) "raid-root-os")))))
672 ;;; LUKS-encrypted root file system.
675 (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
676 ;; The OS we want to install.
677 (use-modules (gnu) (gnu tests) (srfi srfi-1))
680 (host-name "liberigilo")
681 (timezone "Europe/Paris")
682 (locale "en_US.UTF-8")
684 (bootloader (bootloader-configuration
685 (bootloader grub-bootloader)
686 (target "/dev/vdb")))
688 ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
689 ;; detection logic in 'enter-luks-passphrase'.
691 (mapped-devices (list (mapped-device
692 (source (uuid "12345678-1234-1234-1234-123456789abc"))
693 (target "the-root-device")
694 (type luks-device-mapping))))
695 (file-systems (cons (file-system
696 (device "/dev/mapper/the-root-device")
700 (users (cons (user-account
703 (supplementary-groups '("wheel" "audio" "video")))
704 %base-user-accounts))
705 (services (cons (service marionette-service-type
706 (marionette-configuration
707 (imported-modules '((gnu services herd)
708 (guix combinators)))))
711 (define %luks-passphrase
712 ;; LUKS encryption passphrase used in tests.
715 (define %encrypted-root-installation-script
716 ;; Shell script of a simple installation.
722 export GUIX_BUILD_OPTIONS=--no-grafts
723 ls -l /run/current-system/gc-roots
724 parted --script /dev/vdb mklabel gpt \\
725 mkpart primary ext2 1M 3M \\
726 mkpart primary ext2 3M 1.6G \\
729 echo -n " %luks-passphrase " | \\
730 cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
731 echo -n " %luks-passphrase " | \\
732 cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
733 mkfs.ext4 -L my-root /dev/mapper/the-root-device
734 mount LABEL=my-root /mnt
735 herd start cow-store /mnt
737 cp /etc/target-config.scm /mnt/etc/config.scm
738 guix system build /mnt/etc/config.scm
739 guix system init /mnt/etc/config.scm /mnt --no-substitutes
743 (define (enter-luks-passphrase marionette)
744 "Return a gexp to be inserted in the basic system test running on MARIONETTE
745 to enter the LUKS passphrase."
746 (let ((ocrad (file-append ocrad "/bin/ocrad")))
748 (define (passphrase-prompt? text)
749 (string-contains (pk 'screen-text text) "Enter pass"))
751 (define (bios-boot-screen? text)
752 ;; Return true if TEXT corresponds to the boot screen, before GRUB's
754 (string-prefix? "SeaBIOS" text))
756 (test-assert "enter LUKS passphrase for GRUB"
758 ;; At this point we have no choice but to use OCR to determine
759 ;; when the passphrase should be entered.
760 (wait-for-screen-text #$marionette passphrase-prompt?
762 (marionette-type #$(string-append %luks-passphrase "\n")
765 ;; Now wait until we leave the boot screen. This is necessary so
766 ;; we can then be sure we match the "Enter passphrase" prompt from
767 ;; 'cryptsetup', in the initrd.
768 (wait-for-screen-text #$marionette (negate bios-boot-screen?)
772 (test-assert "enter LUKS passphrase for the initrd"
774 ;; XXX: Here we use OCR as well but we could instead use QEMU
775 ;; '-serial stdio' and run it in an input pipe,
776 (wait-for-screen-text #$marionette passphrase-prompt?
779 (marionette-type #$(string-append %luks-passphrase "\n")
782 ;; Take a screenshot for debugging purposes.
783 (marionette-control (string-append "screendump " #$output
784 "/post-initrd-passphrase.ppm")
787 (define %test-encrypted-root-os
789 (name "encrypted-root-os")
791 "Test basic functionality of an OS installed like one would do by hand.
792 This test is expensive in terms of CPU and storage usage since we need to
793 build (current-guix) and then store a couple of full system images.")
795 (mlet* %store-monad ((image (run-install %encrypted-root-os
796 %encrypted-root-os-source
798 %encrypted-root-installation-script))
799 (command (qemu-command/writable-image image)))
800 (run-basic-test %encrypted-root-os command "encrypted-root-os"
801 #:initialization enter-luks-passphrase)))))
805 ;;; Separate /home on LVM
808 ;; Since LVM support in guix currently doesn't allow root-on-LVM we use /home on LVM
809 (define-os-with-source (%lvm-separate-home-os %lvm-separate-home-os-source)
810 (use-modules (gnu) (gnu tests))
813 (host-name "separate-home-on-lvm")
814 (timezone "Europe/Paris")
815 (locale "en_US.utf8")
817 (bootloader (bootloader-configuration
818 (bootloader grub-bootloader)
819 (target "/dev/vdb")))
820 (kernel-arguments '("console=ttyS0"))
822 (mapped-devices (list (mapped-device
825 (type lvm-device-mapping))))
826 (file-systems (cons* (file-system
827 (device (file-system-label "root-fs"))
831 (device "/dev/mapper/vg0-home")
832 (mount-point "/home")
834 (dependencies mapped-devices))
836 (users %base-user-accounts)
837 (services (cons (service marionette-service-type
838 (marionette-configuration
839 (imported-modules '((gnu services herd)
840 (guix combinators)))))
843 (define %lvm-separate-home-installation-script
849 export GUIX_BUILD_OPTIONS=--no-grafts
850 parted --script /dev/vdb mklabel gpt \\
851 mkpart primary ext2 1M 3M \\
852 mkpart primary ext2 3M 1.6G \\
853 mkpart primary 1.6G 3.2G \\
857 vgcreate vg0 /dev/vdb3
858 lvcreate -L 1.6G -n home vg0
860 mkfs.ext4 -L root-fs /dev/vdb2
861 mkfs.ext4 /dev/mapper/vg0-home
864 mount /dev/mapper/vg0-home /mnt/home
866 herd start cow-store /mnt
868 cp /etc/target-config.scm /mnt/etc/config.scm
869 guix system init /mnt/etc/config.scm /mnt --no-substitutes
873 (define %test-lvm-separate-home-os
875 (name "lvm-separate-home-os")
877 "Test functionality of an OS installed with a LVM /home partition")
879 (mlet* %store-monad ((image (run-install %lvm-separate-home-os
880 %lvm-separate-home-os-source
882 %lvm-separate-home-installation-script
883 #:packages (list lvm2-static)
884 #:target-size (* 3200 MiB)))
885 (command (qemu-command/writable-image image)))
886 (run-basic-test %lvm-separate-home-os
887 `(,@command) "lvm-separate-home-os")))))
891 ;;; LUKS-encrypted root file system and /boot in a non-encrypted partition.
894 (define-os-with-source (%encrypted-root-not-boot-os
895 %encrypted-root-not-boot-os-source)
896 ;; The OS we want to install.
897 (use-modules (gnu) (gnu tests) (srfi srfi-1))
900 (host-name "bootroot")
901 (timezone "Europe/Madrid")
902 (locale "en_US.UTF-8")
904 (bootloader (bootloader-configuration
905 (bootloader grub-bootloader)
906 (target "/dev/vdb")))
908 (mapped-devices (list (mapped-device
910 (uuid "12345678-1234-1234-1234-123456789abc"))
912 (type luks-device-mapping))))
913 (file-systems (cons* (file-system
914 (device (file-system-label "my-boot"))
915 (mount-point "/boot")
918 (device "/dev/mapper/root")
922 (users (cons (user-account
925 (supplementary-groups '("wheel" "audio" "video")))
926 %base-user-accounts))
927 (services (cons (service marionette-service-type
928 (marionette-configuration
929 (imported-modules '((gnu services herd)
930 (guix combinators)))))
933 (define %encrypted-root-not-boot-installation-script
934 ;; Shell script for an installation with boot not encrypted but root
941 export GUIX_BUILD_OPTIONS=--no-grafts
942 ls -l /run/current-system/gc-roots
943 parted --script /dev/vdb mklabel gpt \\
944 mkpart primary ext2 1M 3M \\
945 mkpart primary ext2 3M 50M \\
946 mkpart primary ext2 50M 1.6G \\
949 echo -n \"~a\" | cryptsetup luksFormat --uuid=\"~a\" -q /dev/vdb3 -
950 echo -n \"~a\" | cryptsetup open --type luks --key-file - /dev/vdb3 root
951 mkfs.ext4 -L my-root /dev/mapper/root
952 mkfs.ext4 -L my-boot /dev/vdb2
953 mount LABEL=my-root /mnt
955 mount LABEL=my-boot /mnt/boot
956 echo \"Checking mounts\"
958 herd start cow-store /mnt
960 cp /etc/target-config.scm /mnt/etc/config.scm
961 guix system build /mnt/etc/config.scm
962 guix system init /mnt/etc/config.scm /mnt --no-substitutes
964 echo \"Debugging info\"
966 cat /mnt/boot/grub/grub.cfg
968 %luks-passphrase "12345678-1234-1234-1234-123456789abc"
971 (define %test-encrypted-root-not-boot-os
973 (name "encrypted-root-not-boot-os")
975 "Test the manual installation on an OS with / in an encrypted partition
976 but /boot on a different, non-encrypted partition. This test is expensive in
977 terms of CPU and storage usage since we need to build (current-guix) and then
978 store a couple of full system images.")
981 ((image (run-install %encrypted-root-not-boot-os
982 %encrypted-root-not-boot-os-source
984 %encrypted-root-not-boot-installation-script))
985 (command (qemu-command/writable-image image)))
986 (run-basic-test %encrypted-root-not-boot-os command
987 "encrypted-root-not-boot-os"
988 #:initialization enter-luks-passphrase)))))
992 ;;; Btrfs root file system.
995 (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
996 ;; The OS we want to install.
997 (use-modules (gnu) (gnu tests) (srfi srfi-1))
1000 (host-name "liberigilo")
1001 (timezone "Europe/Paris")
1002 (locale "en_US.UTF-8")
1004 (bootloader (bootloader-configuration
1005 (bootloader grub-bootloader)
1006 (target "/dev/vdb")))
1007 (kernel-arguments '("console=ttyS0"))
1008 (file-systems (cons (file-system
1009 (device (file-system-label "my-root"))
1012 %base-file-systems))
1013 (users (cons (user-account
1016 (supplementary-groups '("wheel" "audio" "video")))
1017 %base-user-accounts))
1018 (services (cons (service marionette-service-type
1019 (marionette-configuration
1020 (imported-modules '((gnu services herd)
1021 (guix combinators)))))
1024 (define %btrfs-root-installation-script
1025 ;; Shell script of a simple installation.
1031 export GUIX_BUILD_OPTIONS=--no-grafts
1032 ls -l /run/current-system/gc-roots
1033 parted --script /dev/vdb mklabel gpt \\
1034 mkpart primary ext2 1M 3M \\
1035 mkpart primary ext2 3M 2G \\
1038 mkfs.btrfs -L my-root /dev/vdb2
1039 mount /dev/vdb2 /mnt
1040 btrfs subvolume create /mnt/home
1041 herd start cow-store /mnt
1043 cp /etc/target-config.scm /mnt/etc/config.scm
1044 guix system build /mnt/etc/config.scm
1045 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1049 (define %test-btrfs-root-os
1051 (name "btrfs-root-os")
1053 "Test basic functionality of an OS installed like one would do by hand.
1054 This test is expensive in terms of CPU and storage usage since we need to
1055 build (current-guix) and then store a couple of full system images.")
1057 (mlet* %store-monad ((image (run-install %btrfs-root-os
1058 %btrfs-root-os-source
1060 %btrfs-root-installation-script))
1061 (command (qemu-command/writable-image image)))
1062 (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
1067 ;;; Btrfs RAID-0 root file system.
1069 (define-os-with-source (%btrfs-raid-root-os %btrfs-raid-root-os-source)
1070 ;; An OS whose root partition is a RAID partition.
1071 (use-modules (gnu) (gnu tests))
1074 (host-name "liberigilo")
1075 (timezone "Europe/Paris")
1076 (locale "en_US.utf8")
1078 (bootloader (bootloader-configuration
1079 (bootloader grub-bootloader)
1080 (target "/dev/vdb")))
1081 (kernel-arguments '("console=ttyS0"))
1083 (file-systems (cons (file-system
1084 (device (file-system-label "root-fs"))
1087 %base-file-systems))
1088 (users %base-user-accounts)
1089 (services (cons (service marionette-service-type
1090 (marionette-configuration
1091 (imported-modules '((gnu services herd)
1092 (guix combinators)))))
1095 (define %btrfs-raid-root-installation-script
1101 export GUIX_BUILD_OPTIONS=--no-grafts
1102 parted --script /dev/vdb mklabel gpt \\
1103 mkpart primary ext2 1M 3M \\
1104 mkpart primary ext2 3M 1.4G \\
1105 mkpart primary ext2 1.4G 2.8G \\
1108 mkfs.btrfs -L root-fs -d raid0 -m raid0 /dev/vdb2 /dev/vdb3
1109 mount /dev/vdb2 /mnt
1111 herd start cow-store /mnt
1113 cp /etc/target-config.scm /mnt/etc/config.scm
1114 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1118 (define %test-btrfs-raid-root-os
1120 (name "btrfs-raid-root-os")
1121 (description "Test functionality of an OS installed with a Btrfs
1122 RAID-0 (stripe) root partition.")
1125 ((image (run-install %btrfs-raid-root-os
1126 %btrfs-raid-root-os-source
1127 #:script %btrfs-raid-root-installation-script
1128 #:target-size (* 2800 MiB)))
1129 (command (qemu-command/writable-image image)))
1130 (run-basic-test %btrfs-raid-root-os `(,@command) "btrfs-raid-root-os")))))
1134 ;;; Btrfs root file system on a subvolume.
1137 (define-os-with-source (%btrfs-root-on-subvolume-os
1138 %btrfs-root-on-subvolume-os-source)
1139 ;; The OS we want to install.
1140 (use-modules (gnu) (gnu tests) (srfi srfi-1))
1144 (timezone "America/Montreal")
1145 (locale "en_US.UTF-8")
1146 (bootloader (bootloader-configuration
1147 (bootloader grub-bootloader)
1148 (target "/dev/vdb")))
1149 (kernel-arguments '("console=ttyS0"))
1150 (file-systems (cons* (file-system
1151 (device (file-system-label "btrfs-pool"))
1153 (options "subvol=rootfs,compress=zstd")
1156 (device (file-system-label "btrfs-pool"))
1157 (mount-point "/home")
1158 (options "subvol=homefs,compress=lzo")
1160 %base-file-systems))
1161 (users (cons (user-account
1164 (supplementary-groups '("wheel" "audio" "video")))
1165 %base-user-accounts))
1166 (services (cons (service marionette-service-type
1167 (marionette-configuration
1168 (imported-modules '((gnu services herd)
1169 (guix combinators)))))
1172 (define %btrfs-root-on-subvolume-installation-script
1173 ;; Shell script of a simple installation.
1179 export GUIX_BUILD_OPTIONS=--no-grafts
1180 ls -l /run/current-system/gc-roots
1181 parted --script /dev/vdb mklabel gpt \\
1182 mkpart primary ext2 1M 3M \\
1183 mkpart primary ext2 3M 2G \\
1187 # Setup the top level Btrfs file system with its subvolume.
1188 mkfs.btrfs -L btrfs-pool /dev/vdb2
1189 mount /dev/vdb2 /mnt
1190 btrfs subvolume create /mnt/rootfs
1191 btrfs subvolume create /mnt/homefs
1194 # Mount the subvolumes, ready for installation.
1195 mount LABEL=btrfs-pool -o 'subvol=rootfs,compress=zstd' /mnt
1197 mount LABEL=btrfs-pool -o 'subvol=homefs,compress=zstd' /mnt/home
1199 herd start cow-store /mnt
1201 cp /etc/target-config.scm /mnt/etc/config.scm
1202 guix system build /mnt/etc/config.scm
1203 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1207 (define %test-btrfs-root-on-subvolume-os
1209 (name "btrfs-root-on-subvolume-os")
1211 "Test basic functionality of an OS installed like one would do by hand.
1212 This test is expensive in terms of CPU and storage usage since we need to
1213 build (current-guix) and then store a couple of full system images.")
1217 (run-install %btrfs-root-on-subvolume-os
1218 %btrfs-root-on-subvolume-os-source
1220 %btrfs-root-on-subvolume-installation-script))
1221 (command (qemu-command/writable-image image)))
1222 (run-basic-test %btrfs-root-on-subvolume-os command
1223 "btrfs-root-on-subvolume-os")))))
1227 ;;; JFS root file system.
1230 (define-os-with-source (%jfs-root-os %jfs-root-os-source)
1231 ;; The OS we want to install.
1232 (use-modules (gnu) (gnu tests) (srfi srfi-1))
1235 (host-name "liberigilo")
1236 (timezone "Europe/Paris")
1237 (locale "en_US.UTF-8")
1239 (bootloader (bootloader-configuration
1240 (bootloader grub-bootloader)
1241 (target "/dev/vdb")))
1242 (kernel-arguments '("console=ttyS0"))
1243 (file-systems (cons (file-system
1244 (device (file-system-label "my-root"))
1247 %base-file-systems))
1248 (users (cons (user-account
1251 (supplementary-groups '("wheel" "audio" "video")))
1252 %base-user-accounts))
1253 (services (cons (service marionette-service-type
1254 (marionette-configuration
1255 (imported-modules '((gnu services herd)
1256 (guix combinators)))))
1259 (define %jfs-root-installation-script
1260 ;; Shell script of a simple installation.
1266 export GUIX_BUILD_OPTIONS=--no-grafts
1267 ls -l /run/current-system/gc-roots
1268 parted --script /dev/vdb mklabel gpt \\
1269 mkpart primary ext2 1M 3M \\
1270 mkpart primary ext2 3M 2G \\
1273 jfs_mkfs -L my-root -q /dev/vdb2
1274 mount /dev/vdb2 /mnt
1275 herd start cow-store /mnt
1277 cp /etc/target-config.scm /mnt/etc/config.scm
1278 guix system build /mnt/etc/config.scm
1279 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1283 (define %test-jfs-root-os
1285 (name "jfs-root-os")
1287 "Test basic functionality of an OS installed like one would do by hand.
1288 This test is expensive in terms of CPU and storage usage since we need to
1289 build (current-guix) and then store a couple of full system images.")
1291 (mlet* %store-monad ((image (run-install %jfs-root-os
1294 %jfs-root-installation-script))
1295 (command (qemu-command/writable-image image)))
1296 (run-basic-test %jfs-root-os command "jfs-root-os")))))
1300 ;;; F2FS root file system.
1303 (define-os-with-source (%f2fs-root-os %f2fs-root-os-source)
1304 ;; The OS we want to install.
1305 (use-modules (gnu) (gnu tests) (srfi srfi-1))
1308 (host-name "liberigilo")
1309 (timezone "Europe/Paris")
1310 (locale "en_US.UTF-8")
1312 (bootloader (bootloader-configuration
1313 (bootloader grub-bootloader)
1314 (target "/dev/vdb")))
1315 (kernel-arguments '("console=ttyS0"))
1316 (file-systems (cons (file-system
1317 (device (file-system-label "my-root"))
1320 %base-file-systems))
1321 (users (cons (user-account
1324 (supplementary-groups '("wheel" "audio" "video")))
1325 %base-user-accounts))
1326 (services (cons (service marionette-service-type
1327 (marionette-configuration
1328 (imported-modules '((gnu services herd)
1329 (guix combinators)))))
1332 (define %f2fs-root-installation-script
1333 ;; Shell script of a simple installation.
1339 export GUIX_BUILD_OPTIONS=--no-grafts
1340 ls -l /run/current-system/gc-roots
1341 parted --script /dev/vdb mklabel gpt \\
1342 mkpart primary ext2 1M 3M \\
1343 mkpart primary ext2 3M 2G \\
1346 mkfs.f2fs -l my-root -q /dev/vdb2
1347 mount /dev/vdb2 /mnt
1348 herd start cow-store /mnt
1350 cp /etc/target-config.scm /mnt/etc/config.scm
1351 guix system build /mnt/etc/config.scm
1352 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1356 (define %test-f2fs-root-os
1358 (name "f2fs-root-os")
1360 "Test basic functionality of an OS installed like one would do by hand.
1361 This test is expensive in terms of CPU and storage usage since we need to
1362 build (current-guix) and then store a couple of full system images.")
1364 (mlet* %store-monad ((image (run-install %f2fs-root-os
1365 %f2fs-root-os-source
1367 %f2fs-root-installation-script))
1368 (command (qemu-command/writable-image image)))
1369 (run-basic-test %f2fs-root-os command "f2fs-root-os")))))
1373 ;;; Installation through the graphical interface.
1376 (define %syslog-conf
1377 ;; Syslog configuration that dumps to /dev/console, so we can see the
1378 ;; installer's messages during the test.
1379 (computed-file "syslog.conf"
1381 (copy-file #$%default-syslog.conf #$output)
1382 (chmod #$output #o644)
1383 (let ((port (open-file #$output "a")))
1384 (display "\n*.info /dev/console\n" port)
1387 (define (operating-system-with-console-syslog os)
1388 "Return OS with a syslog service that writes to /dev/console."
1391 (services (modify-services (operating-system-user-services os)
1392 (syslog-service-type config
1394 (syslog-configuration
1396 (config-file %syslog-conf)))))))
1398 (define %root-password "foo")
1400 (define* (gui-test-program marionette
1405 (define (screenshot file)
1406 (marionette-control (string-append "screendump " file)
1409 (define-syntax-rule (marionette-eval* exp marionette)
1410 (or (marionette-eval exp marionette)
1411 (throw 'marionette-eval-failure 'exp)))
1413 (setvbuf (current-output-port) 'none)
1414 (setvbuf (current-error-port) 'none)
1416 (marionette-eval* '(use-modules (gnu installer tests))
1419 ;; Arrange so that 'converse' prints debugging output to the console.
1420 (marionette-eval* '(let ((console (open-output-file "/dev/console")))
1421 (setvbuf console 'none)
1422 (conversation-log-port console))
1425 ;; Tell the installer to not wait for the Connman "online" status.
1426 (marionette-eval* '(call-with-output-file "/tmp/installer-assume-online"
1430 ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
1432 (marionette-eval* '(call-with-output-file
1433 "/tmp/installer-system-init-options"
1435 (write '("--no-grafts" "--no-substitutes")
1439 (marionette-eval* '(define installer-socket
1440 (open-installer-socket))
1442 (screenshot "installer-start.ppm")
1444 (marionette-eval* '(choose-locale+keyboard installer-socket)
1446 (screenshot "installer-locale.ppm")
1448 ;; Choose the host name that the "basic" test expects.
1449 (marionette-eval* '(enter-host-name+passwords installer-socket
1450 #:host-name "liberigilo"
1457 (screenshot "installer-services.ppm")
1459 (marionette-eval* '(choose-services installer-socket
1460 #:choose-desktop-environment?
1462 #:choose-network-service?
1465 (screenshot "installer-partitioning.ppm")
1467 (marionette-eval* '(choose-partitioning installer-socket
1468 #:encrypted? #$encrypted?
1469 #:passphrase #$%luks-passphrase)
1471 (screenshot "installer-run.ppm")
1473 (unless #$encrypted?
1474 ;; At this point, user partitions are formatted and the installer is
1475 ;; waiting for us to start the final step: generating the
1476 ;; configuration file, etc. Set a fixed UUID on the swap partition
1477 ;; that matches what 'installation-target-os-for-gui-tests' expects.
1478 (marionette-eval* '(invoke #$(file-append util-linux "/sbin/swaplabel")
1479 "-U" "11111111-2222-3333-4444-123456789abc"
1483 (marionette-eval* '(conclude-installation installer-socket)
1489 (define %extra-packages
1490 ;; Packages needed when installing with an encrypted root.
1492 lvm2-static cryptsetup-static e2fsck/static
1495 (define installation-os-for-gui-tests
1496 ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
1497 ;; target OS, as well as syslog output redirected to the console so we can
1498 ;; see what the installer is up to.
1499 (marionette-operating-system
1501 (inherit (operating-system-with-console-syslog
1502 (operating-system-add-packages
1503 (operating-system-with-current-guix
1506 (kernel-arguments '("console=ttyS0")))
1507 #:imported-modules '((gnu services herd)
1508 (gnu installer tests)
1509 (guix combinators))))
1511 (define* (installation-target-os-for-gui-tests
1512 #:key (encrypted? #f))
1514 (inherit %minimal-os-on-vda)
1515 (users (append (list (user-account
1517 (comment "Bob's sister")
1519 (supplementary-groups
1520 '("wheel" "audio" "video")))
1523 (comment "Alice's brother")
1525 (supplementary-groups
1526 '("wheel" "audio" "video"))))
1527 %base-user-accounts))
1528 ;; The installer does not create a swap device in guided mode with
1529 ;; encryption support. The installer produces a UUID for the partition;
1530 ;; this "UUID" is explicitly set in 'gui-test-program' to the value shown
1532 (swap-devices (if encrypted?
1534 (list (uuid "11111111-2222-3333-4444-123456789abc"))))
1535 (services (cons (service dhcp-client-service-type)
1536 (operating-system-user-services %minimal-os-on-vda)))))
1538 (define* (installation-target-desktop-os-for-gui-tests
1539 #:key (encrypted? #f))
1541 (inherit (installation-target-os-for-gui-tests
1542 #:encrypted? encrypted?))
1543 (keyboard-layout (keyboard-layout "us" "altgr-intl"))
1545 ;; Make sure that all the packages and services that may be used by the
1546 ;; graphical installer are available.
1548 (list openbox awesome i3-wm i3status
1549 dmenu st ratpoison xterm
1550 emacs emacs-exwm emacs-desktop-environment)
1554 (list (service gnome-desktop-service-type)
1555 (service xfce-desktop-service-type)
1556 (service mate-desktop-service-type)
1557 (service enlightenment-desktop-service-type)
1558 (set-xorg-configuration
1560 (keyboard-layout keyboard-layout)))
1561 (service marionette-service-type
1562 (marionette-configuration
1563 (imported-modules '((gnu services herd)
1565 (guix combinators))))))
1566 %desktop-services))))
1568 (define* (guided-installation-test name
1573 (install-size 'guess)
1574 (target-size (* 2200 MiB)))
1578 "Install an OS using the graphical installer and test it.")
1581 ((image (run-install target-os '(this is unused)
1583 #:os installation-os-for-gui-tests
1584 #:install-size install-size
1585 #:target-size target-size
1586 #:installation-image-type
1587 'uncompressed-iso9660
1589 (lambda (marionette)
1593 #:encrypted? encrypted?))))
1594 (command (qemu-command/writable-image image #:memory-size 512)))
1595 (run-basic-test target-os command name
1596 #:initialization (and encrypted? enter-luks-passphrase)
1597 #:root-password %root-password
1598 #:desktop? desktop?)))))
1600 (define %test-gui-installed-os
1601 (guided-installation-test
1603 #:target-os (installation-target-os-for-gui-tests)))
1605 (define %test-gui-installed-os-encrypted
1606 (guided-installation-test
1607 "gui-installed-os-encrypted"
1609 #:target-os (installation-target-os-for-gui-tests
1612 ;; Building a desktop image is very time and space consuming. Install all
1613 ;; desktop environments in a single test to reduce the overhead.
1614 (define %test-gui-installed-desktop-os-encrypted
1615 (guided-installation-test "gui-installed-desktop-os-encrypted"
1619 (installation-target-desktop-os-for-gui-tests
1621 ;; XXX: The disk-image size guess is too low. Use
1622 ;; a constant value until this is fixed.
1623 #:install-size (* 8000 MiB)
1624 #:target-size (* 9000 MiB)))
1626 ;;; install.scm ends here