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>
7 ;;; This file is part of GNU Guix.
9 ;;; GNU Guix is free software; you can redistribute it and/or modify it
10 ;;; under the terms of the GNU General Public License as published by
11 ;;; the Free Software Foundation; either version 3 of the License, or (at
12 ;;; your option) any later version.
14 ;;; GNU Guix is distributed in the hope that it will be useful, but
15 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;;; GNU General Public License for more details.
19 ;;; You should have received a copy of the GNU General Public License
20 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
22 (define-module (gnu tests install)
24 #:use-module (gnu bootloader extlinux)
25 #:use-module (gnu image)
26 #:use-module (gnu tests)
27 #:use-module (gnu tests base)
28 #:use-module (gnu system)
29 #:use-module (gnu system image)
30 #:use-module (gnu system install)
31 #:use-module (gnu system vm)
32 #:use-module ((gnu build vm) #:select (qemu-command))
33 #:use-module (gnu packages admin)
34 #:use-module (gnu packages bootloaders)
35 #:use-module (gnu packages commencement) ;for 'guile-final'
36 #:use-module (gnu packages cryptsetup)
37 #:use-module (gnu packages linux)
38 #:use-module (gnu packages ocr)
39 #:use-module (gnu packages openbox)
40 #:use-module (gnu packages package-management)
41 #:use-module (gnu packages ratpoison)
42 #:use-module (gnu packages suckless)
43 #:use-module (gnu packages virtualization)
44 #:use-module (gnu packages wm)
45 #:use-module (gnu packages xorg)
46 #:use-module (gnu services desktop)
47 #:use-module (gnu services networking)
48 #:use-module (gnu services xorg)
49 #:use-module (guix store)
50 #:use-module (guix monads)
51 #:use-module (guix packages)
52 #:use-module (guix grafts)
53 #:use-module (guix gexp)
54 #:use-module (guix utils)
55 #:use-module (srfi srfi-1)
56 #:export (%test-installed-os
57 %test-installed-extlinux-os
58 %test-iso-image-installer
59 %test-separate-store-os
60 %test-separate-home-os
62 %test-encrypted-root-os
64 %test-btrfs-root-on-subvolume-os
68 %test-gui-installed-os
69 %test-gui-installed-os-encrypted
70 %test-gui-installed-desktop-os-encrypted))
74 ;;; Test the installation of Guix using the documented approach at the
79 (define-os-with-source (%minimal-os %minimal-os-source)
80 ;; The OS we want to install.
81 (use-modules (gnu) (gnu tests) (srfi srfi-1))
84 (host-name "liberigilo")
85 (timezone "Europe/Paris")
86 (locale "en_US.UTF-8")
88 (bootloader (bootloader-configuration
89 (bootloader grub-bootloader)
91 (kernel-arguments '("console=ttyS0"))
92 (file-systems (cons (file-system
93 (device (file-system-label "my-root"))
97 (users (cons (user-account
99 (comment "Bob's sister")
101 (supplementary-groups '("wheel" "audio" "video")))
102 %base-user-accounts))
103 (services (cons (service marionette-service-type
104 (marionette-configuration
105 (imported-modules '((gnu services herd)
107 (guix combinators)))))
110 (define (operating-system-add-packages os packages)
111 "Append PACKAGES to OS packages list."
114 (packages (append packages (operating-system-packages os)))))
116 (define-os-with-source (%minimal-extlinux-os
117 %minimal-extlinux-os-source)
118 (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
122 (host-name "liberigilo")
123 (timezone "Europe/Paris")
124 (locale "en_US.UTF-8")
126 (bootloader (bootloader-configuration
127 (bootloader extlinux-bootloader-gpt)
128 (target "/dev/vdb")))
129 (kernel-arguments '("console=ttyS0"))
130 (file-systems (cons (file-system
131 (device (file-system-label "my-root"))
135 (services (cons (service marionette-service-type
136 (marionette-configuration
137 (imported-modules '((gnu services herd)
138 (guix combinators)))))
141 (define (operating-system-with-current-guix os)
142 "Return a variant of OS that uses the current Guix."
145 (services (modify-services (operating-system-user-services os)
146 (guix-service-type config =>
149 (guix (current-guix))))))))
152 (define MiB (expt 2 20))
154 (define %simple-installation-script
155 ;; Shell script of a simple installation.
161 export GUIX_BUILD_OPTIONS=--no-grafts
163 parted --script /dev/vdb mklabel gpt \\
164 mkpart primary ext2 1M 3M \\
165 mkpart primary ext2 3M 1.4G \\
168 mkfs.ext4 -L my-root /dev/vdb2
171 herd start cow-store /mnt
173 cp /etc/target-config.scm /mnt/etc/config.scm
174 guix system init /mnt/etc/config.scm /mnt --no-substitutes
178 (define %extlinux-gpt-installation-script
179 ;; Shell script of a simple installation.
180 ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
181 ;; we make sure to pass -O '^64bit' to mkfs.
187 export GUIX_BUILD_OPTIONS=--no-grafts
189 parted --script /dev/vdb mklabel gpt \\
190 mkpart ext2 1M 1.4G \\
192 mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
195 herd start cow-store /mnt
197 cp /etc/target-config.scm /mnt/etc/config.scm
198 guix system init /mnt/etc/config.scm /mnt --no-substitutes
202 (define* (run-install target-os target-os-source
204 (script %simple-installation-script)
207 (os (marionette-operating-system
209 ;; Since the image has no network access, use the
210 ;; current Guix so the store items we need are in
211 ;; the image and add packages provided.
212 (inherit (operating-system-add-packages
213 (operating-system-with-current-guix
216 (kernel-arguments '("console=ttyS0")))
217 #:imported-modules '((gnu services herd)
218 (gnu installer tests)
219 (guix combinators))))
220 (installation-disk-image-file-system-type "ext4")
221 (install-size 'guess)
222 (target-size (* 2200 MiB)))
223 "Run SCRIPT (a shell script following the system installation procedure) in
224 OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
225 the installed system. The packages specified in PACKAGES will be appended to
226 packages defined in installation-os."
228 (mlet* %store-monad ((_ (set-grafting #f))
229 (system (current-system))
230 (target (operating-system-derivation target-os))
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.
242 installation-disk-image-file-system-type))
245 (operating-system-with-gc-roots
246 os (list target guile-final)))
247 ;; Don't provide substitutes; too big.
248 (substitutable? #f)))))
250 (with-imported-modules '((guix build utils)
251 (gnu build marionette))
253 (use-modules (guix build utils)
254 (gnu build marionette))
256 (set-path-environment-variable "PATH" '("bin")
257 (list #$qemu-minimal))
259 (system* "qemu-img" "create" "-f" "qcow2"
260 #$output #$(number->string target-size))
264 `(,(which #$(qemu-command system))
268 ((string=? "ext4" installation-disk-image-file-system-type)
270 ,(string-append "file=" #$image
271 ",if=virtio,readonly")))
272 ((string=? "iso9660" installation-disk-image-file-system-type)
273 #~("-cdrom" #$image))
276 "unsupported installation-disk-image-file-system-type:"
277 installation-disk-image-file-system-type)))
279 ,(string-append "file=" #$output ",if=virtio")
280 ,@(if (file-exists? "/dev/kvm")
284 (pk 'uname (marionette-eval '(uname) marionette))
287 (marionette-eval '(begin
288 (use-modules (gnu services herd))
292 (when #$(->bool script)
293 (marionette-eval '(call-with-output-file "/etc/target-config.scm"
295 (write '#$target-os-source port)))
298 ;; Run SCRIPT. It typically invokes 'reboot' as a last step and
299 ;; thus normally gets killed with SIGTERM by PID 1.
300 (let ((status (marionette-eval '(system #$script) marionette)))
301 (exit (or (equal? (status:term-sig status) SIGTERM)
302 (equal? (status:exit-val status) 0)))))
304 (when #$(->bool gui-test)
305 (wait-for-unix-socket "/var/guix/installer-socket"
307 (format #t "installer socket ready~%")
309 (exit #$(and gui-test
310 (gui-test #~marionette)))))))
312 (gexp->derivation "installation" install
313 #:substitutable? #f))) ;too big
315 (define* (qemu-command/writable-image image #:key (memory-size 256))
316 "Return as a monadic value the command to run QEMU on a writable copy of
317 IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
318 (mlet %store-monad ((system (current-system)))
319 (return #~(let ((image #$image))
320 ;; First we need a writable copy of the image.
321 (format #t "creating writable image from '~a'...~%" image)
322 (unless (zero? (system* #+(file-append qemu-minimal
324 "create" "-f" "qcow2"
326 (string-append "backing_file=" image)
328 (error "failed to create writable QEMU image" image))
330 (chmod "disk.img" #o644)
331 `(,(string-append #$qemu-minimal "/bin/"
332 #$(qemu-command system))
333 ,@(if (file-exists? "/dev/kvm")
336 "-no-reboot" "-m" #$(number->string memory-size)
337 "-drive" "file=disk.img,if=virtio")))))
339 (define %test-installed-os
341 (name "installed-os")
343 "Test basic functionality of an OS installed like one would do by hand.
344 This test is expensive in terms of CPU and storage usage since we need to
345 build (current-guix) and then store a couple of full system images.")
347 (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
348 (command (qemu-command/writable-image image)))
349 (run-basic-test %minimal-os command
352 (define %test-installed-extlinux-os
354 (name "installed-extlinux-os")
356 "Test basic functionality of an OS booted with an extlinux bootloader. As
357 per %test-installed-os, this test is expensive in terms of CPU and storage.")
359 (mlet* %store-monad ((image (run-install %minimal-extlinux-os
360 %minimal-extlinux-os-source
364 %extlinux-gpt-installation-script))
365 (command (qemu-command/writable-image image)))
366 (run-basic-test %minimal-extlinux-os command
367 "installed-extlinux-os")))))
371 ;;; Installation through an ISO image.
374 (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
375 ;; The OS we want to install.
376 (use-modules (gnu) (gnu tests) (srfi srfi-1))
379 (host-name "liberigilo")
380 (timezone "Europe/Paris")
381 (locale "en_US.UTF-8")
383 (bootloader (bootloader-configuration
384 (bootloader grub-bootloader)
385 (target "/dev/vda")))
386 (kernel-arguments '("console=ttyS0"))
387 (file-systems (cons (file-system
388 (device (file-system-label "my-root"))
392 (users (cons (user-account
394 (comment "Bob's sister")
396 (supplementary-groups '("wheel" "audio" "video")))
397 %base-user-accounts))
398 (services (cons (service marionette-service-type
399 (marionette-configuration
400 (imported-modules '((gnu services herd)
402 (guix combinators)))))
405 (define %simple-installation-script-for-/dev/vda
406 ;; Shell script of a simple installation.
412 export GUIX_BUILD_OPTIONS=--no-grafts
414 parted --script /dev/vda mklabel gpt \\
415 mkpart primary ext2 1M 3M \\
416 mkpart primary ext2 3M 1.4G \\
419 mkfs.ext4 -L my-root /dev/vda2
422 herd start cow-store /mnt
424 cp /etc/target-config.scm /mnt/etc/config.scm
425 guix system init /mnt/etc/config.scm /mnt --no-substitutes
429 (define %test-iso-image-installer
431 (name "iso-image-installer")
435 (mlet* %store-monad ((image (run-install
437 %minimal-os-on-vda-source
439 %simple-installation-script-for-/dev/vda
440 #:installation-disk-image-file-system-type
442 (command (qemu-command/writable-image image)))
443 (run-basic-test %minimal-os-on-vda command name)))))
450 (define-os-with-source (%separate-home-os %separate-home-os-source)
451 ;; The OS we want to install.
452 (use-modules (gnu) (gnu tests) (srfi srfi-1))
455 (host-name "liberigilo")
456 (timezone "Europe/Paris")
457 (locale "en_US.utf8")
459 (bootloader (bootloader-configuration
460 (bootloader grub-bootloader)
461 (target "/dev/vdb")))
462 (kernel-arguments '("console=ttyS0"))
463 (file-systems (cons* (file-system
464 (device (file-system-label "my-root"))
469 (mount-point "/home")
472 (users (cons* (user-account
478 %base-user-accounts))
479 (services (cons (service marionette-service-type
480 (marionette-configuration
481 (imported-modules '((gnu services herd)
482 (guix combinators)))))
485 (define %test-separate-home-os
487 (name "separate-home-os")
489 "Test basic functionality of an installed OS with a separate /home
490 partition. In particular, home directories must be correctly created (see
491 <https://bugs.gnu.org/21108>).")
493 (mlet* %store-monad ((image (run-install %separate-home-os
494 %separate-home-os-source
496 %simple-installation-script))
497 (command (qemu-command/writable-image image)))
498 (run-basic-test %separate-home-os command "separate-home-os")))))
502 ;;; Separate /gnu/store partition.
505 (define-os-with-source (%separate-store-os %separate-store-os-source)
506 ;; The OS we want to install.
507 (use-modules (gnu) (gnu tests) (srfi srfi-1))
510 (host-name "liberigilo")
511 (timezone "Europe/Paris")
512 (locale "en_US.UTF-8")
514 (bootloader (bootloader-configuration
515 (bootloader grub-bootloader)
516 (target "/dev/vdb")))
517 (kernel-arguments '("console=ttyS0"))
518 (file-systems (cons* (file-system
519 (device (file-system-label "root-fs"))
523 (device (file-system-label "store-fs"))
527 (users %base-user-accounts)
528 (services (cons (service marionette-service-type
529 (marionette-configuration
530 (imported-modules '((gnu services herd)
531 (guix combinators)))))
534 (define %separate-store-installation-script
535 ;; Installation with a separate /gnu partition.
541 export GUIX_BUILD_OPTIONS=--no-grafts
543 parted --script /dev/vdb mklabel gpt \\
544 mkpart primary ext2 1M 3M \\
545 mkpart primary ext2 3M 400M \\
546 mkpart primary ext2 400M 2.1G \\
549 mkfs.ext4 -L root-fs /dev/vdb2
550 mkfs.ext4 -L store-fs /dev/vdb3
553 mount /dev/vdb3 /mnt/gnu
556 herd start cow-store /mnt
558 cp /etc/target-config.scm /mnt/etc/config.scm
559 guix system init /mnt/etc/config.scm /mnt --no-substitutes
563 (define %test-separate-store-os
565 (name "separate-store-os")
567 "Test basic functionality of an OS installed like one would do by hand,
568 where /gnu lives on a separate partition.")
570 (mlet* %store-monad ((image (run-install %separate-store-os
571 %separate-store-os-source
573 %separate-store-installation-script))
574 (command (qemu-command/writable-image image)))
575 (run-basic-test %separate-store-os command "separate-store-os")))))
579 ;;; RAID root device.
582 (define-os-with-source (%raid-root-os %raid-root-os-source)
583 ;; An OS whose root partition is a RAID partition.
584 (use-modules (gnu) (gnu tests))
587 (host-name "raidified")
588 (timezone "Europe/Paris")
589 (locale "en_US.utf8")
591 (bootloader (bootloader-configuration
592 (bootloader grub-bootloader)
593 (target "/dev/vdb")))
594 (kernel-arguments '("console=ttyS0"))
596 ;; Add a kernel module for RAID-1 (aka. "mirror").
597 (initrd-modules (cons "raid1" %base-initrd-modules))
599 (mapped-devices (list (mapped-device
600 (source (list "/dev/vda2" "/dev/vda3"))
602 (type raid-device-mapping))))
603 (file-systems (cons (file-system
604 (device (file-system-label "root-fs"))
607 (dependencies mapped-devices))
609 (users %base-user-accounts)
610 (services (cons (service marionette-service-type
611 (marionette-configuration
612 (imported-modules '((gnu services herd)
613 (guix combinators)))))
616 (define %raid-root-installation-script
617 ;; Installation with a separate /gnu partition. See
618 ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
625 export GUIX_BUILD_OPTIONS=--no-grafts
626 parted --script /dev/vdb mklabel gpt \\
627 mkpart primary ext2 1M 3M \\
628 mkpart primary ext2 3M 1.4G \\
629 mkpart primary ext2 1.4G 2.8G \\
632 yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
634 mkfs.ext4 -L root-fs /dev/md0
637 herd start cow-store /mnt
639 cp /etc/target-config.scm /mnt/etc/config.scm
640 guix system init /mnt/etc/config.scm /mnt --no-substitutes
644 (define %test-raid-root-os
646 (name "raid-root-os")
648 "Test functionality of an OS installed with a RAID root partition managed
651 (mlet* %store-monad ((image (run-install %raid-root-os
654 %raid-root-installation-script
655 #:target-size (* 2800 MiB)))
656 (command (qemu-command/writable-image image)))
657 (run-basic-test %raid-root-os
658 `(,@command) "raid-root-os")))))
662 ;;; LUKS-encrypted root file system.
665 (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
666 ;; The OS we want to install.
667 (use-modules (gnu) (gnu tests) (srfi srfi-1))
670 (host-name "liberigilo")
671 (timezone "Europe/Paris")
672 (locale "en_US.UTF-8")
674 (bootloader (bootloader-configuration
675 (bootloader grub-bootloader)
676 (target "/dev/vdb")))
678 ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
679 ;; detection logic in 'enter-luks-passphrase'.
681 (mapped-devices (list (mapped-device
682 (source (uuid "12345678-1234-1234-1234-123456789abc"))
683 (target "the-root-device")
684 (type luks-device-mapping))))
685 (file-systems (cons (file-system
686 (device "/dev/mapper/the-root-device")
690 (users (cons (user-account
693 (supplementary-groups '("wheel" "audio" "video")))
694 %base-user-accounts))
695 (services (cons (service marionette-service-type
696 (marionette-configuration
697 (imported-modules '((gnu services herd)
698 (guix combinators)))))
701 (define %luks-passphrase
702 ;; LUKS encryption passphrase used in tests.
705 (define %encrypted-root-installation-script
706 ;; Shell script of a simple installation.
712 export GUIX_BUILD_OPTIONS=--no-grafts
713 ls -l /run/current-system/gc-roots
714 parted --script /dev/vdb mklabel gpt \\
715 mkpart primary ext2 1M 3M \\
716 mkpart primary ext2 3M 1.4G \\
719 echo -n " %luks-passphrase " | \\
720 cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
721 echo -n " %luks-passphrase " | \\
722 cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
723 mkfs.ext4 -L my-root /dev/mapper/the-root-device
724 mount LABEL=my-root /mnt
725 herd start cow-store /mnt
727 cp /etc/target-config.scm /mnt/etc/config.scm
728 guix system build /mnt/etc/config.scm
729 guix system init /mnt/etc/config.scm /mnt --no-substitutes
733 (define (enter-luks-passphrase marionette)
734 "Return a gexp to be inserted in the basic system test running on MARIONETTE
735 to enter the LUKS passphrase."
736 (let ((ocrad (file-append ocrad "/bin/ocrad")))
738 (define (passphrase-prompt? text)
739 (string-contains (pk 'screen-text text) "Enter pass"))
741 (define (bios-boot-screen? text)
742 ;; Return true if TEXT corresponds to the boot screen, before GRUB's
744 (string-prefix? "SeaBIOS" text))
746 (test-assert "enter LUKS passphrase for GRUB"
748 ;; At this point we have no choice but to use OCR to determine
749 ;; when the passphrase should be entered.
750 (wait-for-screen-text #$marionette passphrase-prompt?
752 (marionette-type #$(string-append %luks-passphrase "\n")
755 ;; Now wait until we leave the boot screen. This is necessary so
756 ;; we can then be sure we match the "Enter passphrase" prompt from
757 ;; 'cryptsetup', in the initrd.
758 (wait-for-screen-text #$marionette (negate bios-boot-screen?)
762 (test-assert "enter LUKS passphrase for the initrd"
764 ;; XXX: Here we use OCR as well but we could instead use QEMU
765 ;; '-serial stdio' and run it in an input pipe,
766 (wait-for-screen-text #$marionette passphrase-prompt?
769 (marionette-type #$(string-append %luks-passphrase "\n")
772 ;; Take a screenshot for debugging purposes.
773 (marionette-control (string-append "screendump " #$output
774 "/post-initrd-passphrase.ppm")
777 (define %test-encrypted-root-os
779 (name "encrypted-root-os")
781 "Test basic functionality of an OS installed like one would do by hand.
782 This test is expensive in terms of CPU and storage usage since we need to
783 build (current-guix) and then store a couple of full system images.")
785 (mlet* %store-monad ((image (run-install %encrypted-root-os
786 %encrypted-root-os-source
788 %encrypted-root-installation-script))
789 (command (qemu-command/writable-image image)))
790 (run-basic-test %encrypted-root-os command "encrypted-root-os"
791 #:initialization enter-luks-passphrase)))))
795 ;;; Btrfs root file system.
798 (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
799 ;; The OS we want to install.
800 (use-modules (gnu) (gnu tests) (srfi srfi-1))
803 (host-name "liberigilo")
804 (timezone "Europe/Paris")
805 (locale "en_US.UTF-8")
807 (bootloader (bootloader-configuration
808 (bootloader grub-bootloader)
809 (target "/dev/vdb")))
810 (kernel-arguments '("console=ttyS0"))
811 (file-systems (cons (file-system
812 (device (file-system-label "my-root"))
816 (users (cons (user-account
819 (supplementary-groups '("wheel" "audio" "video")))
820 %base-user-accounts))
821 (services (cons (service marionette-service-type
822 (marionette-configuration
823 (imported-modules '((gnu services herd)
824 (guix combinators)))))
827 (define %btrfs-root-installation-script
828 ;; Shell script of a simple installation.
834 export GUIX_BUILD_OPTIONS=--no-grafts
835 ls -l /run/current-system/gc-roots
836 parted --script /dev/vdb mklabel gpt \\
837 mkpart primary ext2 1M 3M \\
838 mkpart primary ext2 3M 2G \\
841 mkfs.btrfs -L my-root /dev/vdb2
843 btrfs subvolume create /mnt/home
844 herd start cow-store /mnt
846 cp /etc/target-config.scm /mnt/etc/config.scm
847 guix system build /mnt/etc/config.scm
848 guix system init /mnt/etc/config.scm /mnt --no-substitutes
852 (define %test-btrfs-root-os
854 (name "btrfs-root-os")
856 "Test basic functionality of an OS installed like one would do by hand.
857 This test is expensive in terms of CPU and storage usage since we need to
858 build (current-guix) and then store a couple of full system images.")
860 (mlet* %store-monad ((image (run-install %btrfs-root-os
861 %btrfs-root-os-source
863 %btrfs-root-installation-script))
864 (command (qemu-command/writable-image image)))
865 (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
869 ;;; Btrfs root file system on a subvolume.
872 (define-os-with-source (%btrfs-root-on-subvolume-os
873 %btrfs-root-on-subvolume-os-source)
874 ;; The OS we want to install.
875 (use-modules (gnu) (gnu tests) (srfi srfi-1))
879 (timezone "America/Montreal")
880 (locale "en_US.UTF-8")
881 (bootloader (bootloader-configuration
882 (bootloader grub-bootloader)
883 (target "/dev/vdb")))
884 (kernel-arguments '("console=ttyS0"))
885 (file-systems (cons* (file-system
886 (device (file-system-label "btrfs-pool"))
888 (options "subvol=rootfs,compress=zstd")
891 (device (file-system-label "btrfs-pool"))
892 (mount-point "/home")
893 (options "subvol=homefs,compress=lzo")
896 (users (cons (user-account
899 (supplementary-groups '("wheel" "audio" "video")))
900 %base-user-accounts))
901 (services (cons (service marionette-service-type
902 (marionette-configuration
903 (imported-modules '((gnu services herd)
904 (guix combinators)))))
907 (define %btrfs-root-on-subvolume-installation-script
908 ;; Shell script of a simple installation.
914 export GUIX_BUILD_OPTIONS=--no-grafts
915 ls -l /run/current-system/gc-roots
916 parted --script /dev/vdb mklabel gpt \\
917 mkpart primary ext2 1M 3M \\
918 mkpart primary ext2 3M 2G \\
922 # Setup the top level Btrfs file system with its subvolume.
923 mkfs.btrfs -L btrfs-pool /dev/vdb2
925 btrfs subvolume create /mnt/rootfs
926 btrfs subvolume create /mnt/homefs
929 # Mount the subvolumes, ready for installation.
930 mount LABEL=btrfs-pool -o 'subvol=rootfs,compress=zstd' /mnt
932 mount LABEL=btrfs-pool -o 'subvol=homefs,compress=zstd' /mnt/home
934 herd start cow-store /mnt
936 cp /etc/target-config.scm /mnt/etc/config.scm
937 guix system build /mnt/etc/config.scm
938 guix system init /mnt/etc/config.scm /mnt --no-substitutes
942 (define %test-btrfs-root-on-subvolume-os
944 (name "btrfs-root-on-subvolume-os")
946 "Test basic functionality of an OS installed like one would do by hand.
947 This test is expensive in terms of CPU and storage usage since we need to
948 build (current-guix) and then store a couple of full system images.")
952 (run-install %btrfs-root-on-subvolume-os
953 %btrfs-root-on-subvolume-os-source
955 %btrfs-root-on-subvolume-installation-script))
956 (command (qemu-command/writable-image image)))
957 (run-basic-test %btrfs-root-on-subvolume-os command
958 "btrfs-root-on-subvolume-os")))))
962 ;;; JFS root file system.
965 (define-os-with-source (%jfs-root-os %jfs-root-os-source)
966 ;; The OS we want to install.
967 (use-modules (gnu) (gnu tests) (srfi srfi-1))
970 (host-name "liberigilo")
971 (timezone "Europe/Paris")
972 (locale "en_US.UTF-8")
974 (bootloader (bootloader-configuration
975 (bootloader grub-bootloader)
976 (target "/dev/vdb")))
977 (kernel-arguments '("console=ttyS0"))
978 (file-systems (cons (file-system
979 (device (file-system-label "my-root"))
983 (users (cons (user-account
986 (supplementary-groups '("wheel" "audio" "video")))
987 %base-user-accounts))
988 (services (cons (service marionette-service-type
989 (marionette-configuration
990 (imported-modules '((gnu services herd)
991 (guix combinators)))))
994 (define %jfs-root-installation-script
995 ;; Shell script of a simple installation.
1001 export GUIX_BUILD_OPTIONS=--no-grafts
1002 ls -l /run/current-system/gc-roots
1003 parted --script /dev/vdb mklabel gpt \\
1004 mkpart primary ext2 1M 3M \\
1005 mkpart primary ext2 3M 2G \\
1008 jfs_mkfs -L my-root -q /dev/vdb2
1009 mount /dev/vdb2 /mnt
1010 herd start cow-store /mnt
1012 cp /etc/target-config.scm /mnt/etc/config.scm
1013 guix system build /mnt/etc/config.scm
1014 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1018 (define %test-jfs-root-os
1020 (name "jfs-root-os")
1022 "Test basic functionality of an OS installed like one would do by hand.
1023 This test is expensive in terms of CPU and storage usage since we need to
1024 build (current-guix) and then store a couple of full system images.")
1026 (mlet* %store-monad ((image (run-install %jfs-root-os
1029 %jfs-root-installation-script))
1030 (command (qemu-command/writable-image image)))
1031 (run-basic-test %jfs-root-os command "jfs-root-os")))))
1035 ;;; F2FS root file system.
1038 (define-os-with-source (%f2fs-root-os %f2fs-root-os-source)
1039 ;; The OS we want to install.
1040 (use-modules (gnu) (gnu tests) (srfi srfi-1))
1043 (host-name "liberigilo")
1044 (timezone "Europe/Paris")
1045 (locale "en_US.UTF-8")
1047 (bootloader (bootloader-configuration
1048 (bootloader grub-bootloader)
1049 (target "/dev/vdb")))
1050 (kernel-arguments '("console=ttyS0"))
1051 (file-systems (cons (file-system
1052 (device (file-system-label "my-root"))
1055 %base-file-systems))
1056 (users (cons (user-account
1059 (supplementary-groups '("wheel" "audio" "video")))
1060 %base-user-accounts))
1061 (services (cons (service marionette-service-type
1062 (marionette-configuration
1063 (imported-modules '((gnu services herd)
1064 (guix combinators)))))
1067 (define %f2fs-root-installation-script
1068 ;; Shell script of a simple installation.
1074 export GUIX_BUILD_OPTIONS=--no-grafts
1075 ls -l /run/current-system/gc-roots
1076 parted --script /dev/vdb mklabel gpt \\
1077 mkpart primary ext2 1M 3M \\
1078 mkpart primary ext2 3M 2G \\
1081 mkfs.f2fs -l my-root -q /dev/vdb2
1082 mount /dev/vdb2 /mnt
1083 herd start cow-store /mnt
1085 cp /etc/target-config.scm /mnt/etc/config.scm
1086 guix system build /mnt/etc/config.scm
1087 guix system init /mnt/etc/config.scm /mnt --no-substitutes
1091 (define %test-f2fs-root-os
1093 (name "f2fs-root-os")
1095 "Test basic functionality of an OS installed like one would do by hand.
1096 This test is expensive in terms of CPU and storage usage since we need to
1097 build (current-guix) and then store a couple of full system images.")
1099 (mlet* %store-monad ((image (run-install %f2fs-root-os
1100 %f2fs-root-os-source
1102 %f2fs-root-installation-script))
1103 (command (qemu-command/writable-image image)))
1104 (run-basic-test %f2fs-root-os command "f2fs-root-os")))))
1108 ;;; Installation through the graphical interface.
1111 (define %syslog-conf
1112 ;; Syslog configuration that dumps to /dev/console, so we can see the
1113 ;; installer's messages during the test.
1114 (computed-file "syslog.conf"
1116 (copy-file #$%default-syslog.conf #$output)
1117 (chmod #$output #o644)
1118 (let ((port (open-file #$output "a")))
1119 (display "\n*.info /dev/console\n" port)
1122 (define (operating-system-with-console-syslog os)
1123 "Return OS with a syslog service that writes to /dev/console."
1126 (services (modify-services (operating-system-user-services os)
1127 (syslog-service-type config
1129 (syslog-configuration
1131 (config-file %syslog-conf)))))))
1133 (define %root-password "foo")
1135 (define* (gui-test-program marionette
1140 (define (screenshot file)
1141 (marionette-control (string-append "screendump " file)
1144 (define-syntax-rule (marionette-eval* exp marionette)
1145 (or (marionette-eval exp marionette)
1146 (throw 'marionette-eval-failure 'exp)))
1148 (setvbuf (current-output-port) 'none)
1149 (setvbuf (current-error-port) 'none)
1151 (marionette-eval* '(use-modules (gnu installer tests))
1154 ;; Arrange so that 'converse' prints debugging output to the console.
1155 (marionette-eval* '(let ((console (open-output-file "/dev/console")))
1156 (setvbuf console 'none)
1157 (conversation-log-port console))
1160 ;; Tell the installer to not wait for the Connman "online" status.
1161 (marionette-eval* '(call-with-output-file "/tmp/installer-assume-online"
1165 ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
1167 (marionette-eval* '(call-with-output-file
1168 "/tmp/installer-system-init-options"
1170 (write '("--no-grafts" "--no-substitutes")
1174 (marionette-eval* '(define installer-socket
1175 (open-installer-socket))
1177 (screenshot "installer-start.ppm")
1179 (marionette-eval* '(choose-locale+keyboard installer-socket)
1181 (screenshot "installer-locale.ppm")
1183 ;; Choose the host name that the "basic" test expects.
1184 (marionette-eval* '(enter-host-name+passwords installer-socket
1185 #:host-name "liberigilo"
1192 (screenshot "installer-services.ppm")
1194 (marionette-eval* '(choose-services installer-socket
1195 #:choose-desktop-environment?
1197 #:choose-network-service?
1200 (screenshot "installer-partitioning.ppm")
1202 (marionette-eval* '(choose-partitioning installer-socket
1203 #:encrypted? #$encrypted?
1204 #:passphrase #$%luks-passphrase)
1206 (screenshot "installer-run.ppm")
1208 (marionette-eval* '(conclude-installation installer-socket)
1214 (define %extra-packages
1215 ;; Packages needed when installing with an encrypted root.
1217 lvm2-static cryptsetup-static e2fsck/static
1220 (define installation-os-for-gui-tests
1221 ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
1222 ;; target OS, as well as syslog output redirected to the console so we can
1223 ;; see what the installer is up to.
1224 (marionette-operating-system
1226 (inherit (operating-system-with-console-syslog
1227 (operating-system-add-packages
1228 (operating-system-with-current-guix
1231 (kernel-arguments '("console=ttyS0")))
1232 #:imported-modules '((gnu services herd)
1233 (gnu installer tests)
1234 (guix combinators))))
1236 (define* (installation-target-os-for-gui-tests
1237 #:key (encrypted? #f))
1239 (inherit %minimal-os-on-vda)
1240 (users (append (list (user-account
1242 (comment "Bob's sister")
1244 (supplementary-groups
1245 '("wheel" "audio" "video")))
1248 (comment "Alice's brother")
1250 (supplementary-groups
1251 '("wheel" "audio" "video"))))
1252 %base-user-accounts))
1253 ;; The installer does not create a swap device in guided mode with
1254 ;; encryption support.
1255 (swap-devices (if encrypted? '() '("/dev/vda2")))
1256 (services (cons (service dhcp-client-service-type)
1257 (operating-system-user-services %minimal-os-on-vda)))))
1259 (define* (installation-target-desktop-os-for-gui-tests
1260 #:key (encrypted? #f))
1262 (inherit (installation-target-os-for-gui-tests
1263 #:encrypted? encrypted?))
1264 (keyboard-layout (keyboard-layout "us" "altgr-intl"))
1266 ;; Make sure that all the packages and services that may be used by the
1267 ;; graphical installer are available.
1269 (list openbox awesome i3-wm i3status
1270 dmenu st ratpoison xterm)
1274 (list (service gnome-desktop-service-type)
1275 (service xfce-desktop-service-type)
1276 (service mate-desktop-service-type)
1277 (service enlightenment-desktop-service-type)
1278 (set-xorg-configuration
1280 (keyboard-layout keyboard-layout)))
1281 (service marionette-service-type
1282 (marionette-configuration
1283 (imported-modules '((gnu services herd)
1285 (guix combinators))))))
1286 %desktop-services))))
1288 (define* (guided-installation-test name
1293 (install-size 'guess)
1294 (target-size (* 2200 MiB)))
1298 "Install an OS using the graphical installer and test it.")
1301 ((image (run-install target-os '(this is unused)
1303 #:os installation-os-for-gui-tests
1304 #:install-size install-size
1305 #:target-size target-size
1306 #:installation-disk-image-file-system-type
1309 (lambda (marionette)
1313 #:encrypted? encrypted?))))
1314 (command (qemu-command/writable-image image)))
1315 (run-basic-test target-os command name
1316 #:initialization (and encrypted? enter-luks-passphrase)
1317 #:root-password %root-password)))))
1319 (define %test-gui-installed-os
1320 (guided-installation-test
1322 #:target-os (installation-target-os-for-gui-tests)))
1324 (define %test-gui-installed-os-encrypted
1325 (guided-installation-test
1326 "gui-installed-os-encrypted"
1328 #:target-os (installation-target-os-for-gui-tests
1331 ;; Building a desktop image is very time and space consuming. Install all
1332 ;; desktop environments in a single test to reduce the overhead.
1333 (define %test-gui-installed-desktop-os-encrypted
1334 (guided-installation-test "gui-installed-desktop-os-encrypted"
1338 (installation-target-desktop-os-for-gui-tests
1340 ;; XXX: The disk-image size guess is too low. Use
1341 ;; a constant value until this is fixed.
1342 #:install-size (* 8000 MiB)
1343 #:target-size (* 9000 MiB)))
1345 ;;; install.scm ends here