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>
5 ;;; This file is part of GNU Guix.
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;;; GNU General Public License for more details.
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20 (define-module (gnu tests install)
22 #:use-module (gnu bootloader extlinux)
23 #:use-module (gnu tests)
24 #:use-module (gnu tests base)
25 #:use-module (gnu system)
26 #:use-module (gnu system install)
27 #:use-module (gnu system vm)
28 #:use-module ((gnu build vm) #:select (qemu-command))
29 #:use-module (gnu packages admin)
30 #:use-module (gnu packages bootloaders)
31 #:use-module (gnu packages cryptsetup)
32 #:use-module (gnu packages linux)
33 #:use-module (gnu packages ocr)
34 #:use-module (gnu packages package-management)
35 #:use-module (gnu packages virtualization)
36 #:use-module (gnu services networking)
37 #:use-module (guix store)
38 #:use-module (guix monads)
39 #:use-module (guix packages)
40 #:use-module (guix grafts)
41 #:use-module (guix gexp)
42 #:use-module (guix utils)
43 #:export (%test-installed-os
44 %test-installed-extlinux-os
45 %test-iso-image-installer
46 %test-separate-store-os
47 %test-separate-home-os
49 %test-encrypted-root-os
53 %test-gui-installed-os
54 %test-gui-installed-os-encrypted))
58 ;;; Test the installation of Guix using the documented approach at the
63 (define-os-with-source (%minimal-os %minimal-os-source)
64 ;; The OS we want to install.
65 (use-modules (gnu) (gnu tests) (srfi srfi-1))
68 (host-name "liberigilo")
69 (timezone "Europe/Paris")
70 (locale "en_US.UTF-8")
72 (bootloader (bootloader-configuration
73 (bootloader grub-bootloader)
75 (kernel-arguments '("console=ttyS0"))
76 (file-systems (cons (file-system
77 (device (file-system-label "my-root"))
81 (users (cons (user-account
83 (comment "Bob's sister")
85 (supplementary-groups '("wheel" "audio" "video")))
87 (services (cons (service marionette-service-type
88 (marionette-configuration
89 (imported-modules '((gnu services herd)
91 (guix combinators)))))
94 (define (operating-system-add-packages os packages)
95 "Append PACKAGES to OS packages list."
98 (packages (append packages (operating-system-packages os)))))
100 (define-os-with-source (%minimal-extlinux-os
101 %minimal-extlinux-os-source)
102 (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
106 (host-name "liberigilo")
107 (timezone "Europe/Paris")
108 (locale "en_US.UTF-8")
110 (bootloader (bootloader-configuration
111 (bootloader extlinux-bootloader-gpt)
112 (target "/dev/vdb")))
113 (kernel-arguments '("console=ttyS0"))
114 (file-systems (cons (file-system
115 (device (file-system-label "my-root"))
119 (services (cons (service marionette-service-type
120 (marionette-configuration
121 (imported-modules '((gnu services herd)
122 (guix combinators)))))
125 (define (operating-system-with-current-guix os)
126 "Return a variant of OS that uses the current Guix."
129 (services (modify-services (operating-system-user-services os)
130 (guix-service-type config =>
133 (guix (current-guix))))))))
136 (define MiB (expt 2 20))
138 (define %simple-installation-script
139 ;; Shell script of a simple installation.
145 export GUIX_BUILD_OPTIONS=--no-grafts
147 parted --script /dev/vdb mklabel gpt \\
148 mkpart primary ext2 1M 3M \\
149 mkpart primary ext2 3M 1.4G \\
152 mkfs.ext4 -L my-root /dev/vdb2
155 herd start cow-store /mnt
157 cp /etc/target-config.scm /mnt/etc/config.scm
158 guix system init /mnt/etc/config.scm /mnt --no-substitutes
162 (define %extlinux-gpt-installation-script
163 ;; Shell script of a simple installation.
164 ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
165 ;; we make sure to pass -O '^64bit' to mkfs.
171 export GUIX_BUILD_OPTIONS=--no-grafts
173 parted --script /dev/vdb mklabel gpt \\
174 mkpart ext2 1M 1.4G \\
176 mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
179 herd start cow-store /mnt
181 cp /etc/target-config.scm /mnt/etc/config.scm
182 guix system init /mnt/etc/config.scm /mnt --no-substitutes
186 (define* (run-install target-os target-os-source
188 (script %simple-installation-script)
191 (os (marionette-operating-system
193 ;; Since the image has no network access, use the
194 ;; current Guix so the store items we need are in
195 ;; the image and add packages provided.
196 (inherit (operating-system-add-packages
197 (operating-system-with-current-guix
200 (kernel-arguments '("console=ttyS0")))
201 #:imported-modules '((gnu services herd)
202 (gnu installer tests)
203 (guix combinators))))
204 (installation-disk-image-file-system-type "ext4")
205 (target-size (* 2200 MiB)))
206 "Run SCRIPT (a shell script following the system installation procedure) in
207 OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
208 the installed system. The packages specified in PACKAGES will be appended to
209 packages defined in installation-os."
211 (mlet* %store-monad ((_ (set-grafting #f))
212 (system (current-system))
213 (target (operating-system-derivation target-os))
215 ;; Since the installation system has no network access,
216 ;; we cheat a little bit by adding TARGET to its GC
217 ;; roots. This way, we know 'guix system init' will
219 (image (system-disk-image
220 (operating-system-with-gc-roots
222 #:disk-image-size 'guess
224 installation-disk-image-file-system-type)))
226 (with-imported-modules '((guix build utils)
227 (gnu build marionette))
229 (use-modules (guix build utils)
230 (gnu build marionette))
232 (set-path-environment-variable "PATH" '("bin")
233 (list #$qemu-minimal))
235 (system* "qemu-img" "create" "-f" "qcow2"
236 #$output #$(number->string target-size))
240 `(,(which #$(qemu-command system))
244 ((string=? "ext4" installation-disk-image-file-system-type)
246 ,(string-append "file=" #$image
247 ",if=virtio,readonly")))
248 ((string=? "iso9660" installation-disk-image-file-system-type)
249 #~("-cdrom" #$image))
252 "unsupported installation-disk-image-file-system-type:"
253 installation-disk-image-file-system-type)))
255 ,(string-append "file=" #$output ",if=virtio")
256 ,@(if (file-exists? "/dev/kvm")
260 (pk 'uname (marionette-eval '(uname) marionette))
263 (marionette-eval '(begin
264 (use-modules (gnu services herd))
268 (when #$(->bool script)
269 (marionette-eval '(call-with-output-file "/etc/target-config.scm"
271 (write '#$target-os-source port)))
273 (exit (marionette-eval '(zero? (system #$script))
276 (when #$(->bool gui-test)
277 (wait-for-unix-socket "/var/guix/installer-socket"
279 (format #t "installer socket ready~%")
281 (exit #$(and gui-test
282 (gui-test #~marionette)))))))
284 (gexp->derivation "installation" install)))
286 (define* (qemu-command/writable-image image #:key (memory-size 256))
287 "Return as a monadic value the command to run QEMU on a writable copy of
288 IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
289 (mlet %store-monad ((system (current-system)))
290 (return #~(let ((image #$image))
291 ;; First we need a writable copy of the image.
292 (format #t "creating writable image from '~a'...~%" image)
293 (unless (zero? (system* #+(file-append qemu-minimal
295 "create" "-f" "qcow2"
297 (string-append "backing_file=" image)
299 (error "failed to create writable QEMU image" image))
301 (chmod "disk.img" #o644)
302 `(,(string-append #$qemu-minimal "/bin/"
303 #$(qemu-command system))
304 ,@(if (file-exists? "/dev/kvm")
307 "-no-reboot" "-m" #$(number->string memory-size)
308 "-drive" "file=disk.img,if=virtio")))))
310 (define %test-installed-os
312 (name "installed-os")
314 "Test basic functionality of an OS installed like one would do by hand.
315 This test is expensive in terms of CPU and storage usage since we need to
316 build (current-guix) and then store a couple of full system images.")
318 (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
319 (command (qemu-command/writable-image image)))
320 (run-basic-test %minimal-os command
323 (define %test-installed-extlinux-os
325 (name "installed-extlinux-os")
327 "Test basic functionality of an OS booted with an extlinux bootloader. As
328 per %test-installed-os, this test is expensive in terms of CPU and storage.")
330 (mlet* %store-monad ((image (run-install %minimal-extlinux-os
331 %minimal-extlinux-os-source
335 %extlinux-gpt-installation-script))
336 (command (qemu-command/writable-image image)))
337 (run-basic-test %minimal-extlinux-os command
338 "installed-extlinux-os")))))
342 ;;; Installation through an ISO image.
345 (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
346 ;; The OS we want to install.
347 (use-modules (gnu) (gnu tests) (srfi srfi-1))
350 (host-name "liberigilo")
351 (timezone "Europe/Paris")
352 (locale "en_US.UTF-8")
354 (bootloader (bootloader-configuration
355 (bootloader grub-bootloader)
356 (target "/dev/vda")))
357 (kernel-arguments '("console=ttyS0"))
358 (file-systems (cons (file-system
359 (device (file-system-label "my-root"))
363 (users (cons (user-account
365 (comment "Bob's sister")
367 (supplementary-groups '("wheel" "audio" "video")))
368 %base-user-accounts))
369 (services (cons (service marionette-service-type
370 (marionette-configuration
371 (imported-modules '((gnu services herd)
372 (guix combinators)))))
375 (define %simple-installation-script-for-/dev/vda
376 ;; Shell script of a simple installation.
382 export GUIX_BUILD_OPTIONS=--no-grafts
384 parted --script /dev/vda mklabel gpt \\
385 mkpart primary ext2 1M 3M \\
386 mkpart primary ext2 3M 1.4G \\
389 mkfs.ext4 -L my-root /dev/vda2
392 herd start cow-store /mnt
394 cp /etc/target-config.scm /mnt/etc/config.scm
395 guix system init /mnt/etc/config.scm /mnt --no-substitutes
399 (define %test-iso-image-installer
401 (name "iso-image-installer")
405 (mlet* %store-monad ((image (run-install
407 %minimal-os-on-vda-source
409 %simple-installation-script-for-/dev/vda
410 #:installation-disk-image-file-system-type
412 (command (qemu-command/writable-image image)))
413 (run-basic-test %minimal-os-on-vda command name)))))
420 (define-os-with-source (%separate-home-os %separate-home-os-source)
421 ;; The OS we want to install.
422 (use-modules (gnu) (gnu tests) (srfi srfi-1))
425 (host-name "liberigilo")
426 (timezone "Europe/Paris")
427 (locale "en_US.utf8")
429 (bootloader (bootloader-configuration
430 (bootloader grub-bootloader)
431 (target "/dev/vdb")))
432 (kernel-arguments '("console=ttyS0"))
433 (file-systems (cons* (file-system
434 (device (file-system-label "my-root"))
439 (mount-point "/home")
442 (users (cons* (user-account
448 %base-user-accounts))
449 (services (cons (service marionette-service-type
450 (marionette-configuration
451 (imported-modules '((gnu services herd)
452 (guix combinators)))))
455 (define %test-separate-home-os
457 (name "separate-home-os")
459 "Test basic functionality of an installed OS with a separate /home
460 partition. In particular, home directories must be correctly created (see
461 <https://bugs.gnu.org/21108>).")
463 (mlet* %store-monad ((image (run-install %separate-home-os
464 %separate-home-os-source
466 %simple-installation-script))
467 (command (qemu-command/writable-image image)))
468 (run-basic-test %separate-home-os command "separate-home-os")))))
472 ;;; Separate /gnu/store partition.
475 (define-os-with-source (%separate-store-os %separate-store-os-source)
476 ;; The OS we want to install.
477 (use-modules (gnu) (gnu tests) (srfi srfi-1))
480 (host-name "liberigilo")
481 (timezone "Europe/Paris")
482 (locale "en_US.UTF-8")
484 (bootloader (bootloader-configuration
485 (bootloader grub-bootloader)
486 (target "/dev/vdb")))
487 (kernel-arguments '("console=ttyS0"))
488 (file-systems (cons* (file-system
489 (device (file-system-label "root-fs"))
493 (device (file-system-label "store-fs"))
497 (users %base-user-accounts)
498 (services (cons (service marionette-service-type
499 (marionette-configuration
500 (imported-modules '((gnu services herd)
501 (guix combinators)))))
504 (define %separate-store-installation-script
505 ;; Installation with a separate /gnu partition.
511 export GUIX_BUILD_OPTIONS=--no-grafts
513 parted --script /dev/vdb mklabel gpt \\
514 mkpart primary ext2 1M 3M \\
515 mkpart primary ext2 3M 400M \\
516 mkpart primary ext2 400M 2.1G \\
519 mkfs.ext4 -L root-fs /dev/vdb2
520 mkfs.ext4 -L store-fs /dev/vdb3
523 mount /dev/vdb3 /mnt/gnu
526 herd start cow-store /mnt
528 cp /etc/target-config.scm /mnt/etc/config.scm
529 guix system init /mnt/etc/config.scm /mnt --no-substitutes
533 (define %test-separate-store-os
535 (name "separate-store-os")
537 "Test basic functionality of an OS installed like one would do by hand,
538 where /gnu lives on a separate partition.")
540 (mlet* %store-monad ((image (run-install %separate-store-os
541 %separate-store-os-source
543 %separate-store-installation-script))
544 (command (qemu-command/writable-image image)))
545 (run-basic-test %separate-store-os command "separate-store-os")))))
549 ;;; RAID root device.
552 (define-os-with-source (%raid-root-os %raid-root-os-source)
553 ;; An OS whose root partition is a RAID partition.
554 (use-modules (gnu) (gnu tests))
557 (host-name "raidified")
558 (timezone "Europe/Paris")
559 (locale "en_US.utf8")
561 (bootloader (bootloader-configuration
562 (bootloader grub-bootloader)
563 (target "/dev/vdb")))
564 (kernel-arguments '("console=ttyS0"))
566 ;; Add a kernel module for RAID-1 (aka. "mirror").
567 (initrd-modules (cons "raid1" %base-initrd-modules))
569 (mapped-devices (list (mapped-device
570 (source (list "/dev/vda2" "/dev/vda3"))
572 (type raid-device-mapping))))
573 (file-systems (cons (file-system
574 (device (file-system-label "root-fs"))
577 (dependencies mapped-devices))
579 (users %base-user-accounts)
580 (services (cons (service marionette-service-type
581 (marionette-configuration
582 (imported-modules '((gnu services herd)
583 (guix combinators)))))
586 (define %raid-root-installation-script
587 ;; Installation with a separate /gnu partition. See
588 ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
595 export GUIX_BUILD_OPTIONS=--no-grafts
596 parted --script /dev/vdb mklabel gpt \\
597 mkpart primary ext2 1M 3M \\
598 mkpart primary ext2 3M 1.4G \\
599 mkpart primary ext2 1.4G 2.8G \\
602 yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
604 mkfs.ext4 -L root-fs /dev/md0
607 herd start cow-store /mnt
609 cp /etc/target-config.scm /mnt/etc/config.scm
610 guix system init /mnt/etc/config.scm /mnt --no-substitutes
614 (define %test-raid-root-os
616 (name "raid-root-os")
618 "Test functionality of an OS installed with a RAID root partition managed
621 (mlet* %store-monad ((image (run-install %raid-root-os
624 %raid-root-installation-script
625 #:target-size (* 2800 MiB)))
626 (command (qemu-command/writable-image image)))
627 (run-basic-test %raid-root-os
628 `(,@command) "raid-root-os")))))
632 ;;; LUKS-encrypted root file system.
635 (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
636 ;; The OS we want to install.
637 (use-modules (gnu) (gnu tests) (srfi srfi-1))
640 (host-name "liberigilo")
641 (timezone "Europe/Paris")
642 (locale "en_US.UTF-8")
644 (bootloader (bootloader-configuration
645 (bootloader grub-bootloader)
646 (target "/dev/vdb")))
648 ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
649 ;; detection logic in 'enter-luks-passphrase'.
651 (mapped-devices (list (mapped-device
652 (source (uuid "12345678-1234-1234-1234-123456789abc"))
653 (target "the-root-device")
654 (type luks-device-mapping))))
655 (file-systems (cons (file-system
656 (device "/dev/mapper/the-root-device")
660 (users (cons (user-account
663 (supplementary-groups '("wheel" "audio" "video")))
664 %base-user-accounts))
665 (services (cons (service marionette-service-type
666 (marionette-configuration
667 (imported-modules '((gnu services herd)
668 (guix combinators)))))
671 (define %luks-passphrase
672 ;; LUKS encryption passphrase used in tests.
675 (define %encrypted-root-installation-script
676 ;; Shell script of a simple installation.
682 export GUIX_BUILD_OPTIONS=--no-grafts
683 ls -l /run/current-system/gc-roots
684 parted --script /dev/vdb mklabel gpt \\
685 mkpart primary ext2 1M 3M \\
686 mkpart primary ext2 3M 1.4G \\
689 echo -n " %luks-passphrase " | \\
690 cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
691 echo -n " %luks-passphrase " | \\
692 cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
693 mkfs.ext4 -L my-root /dev/mapper/the-root-device
694 mount LABEL=my-root /mnt
695 herd start cow-store /mnt
697 cp /etc/target-config.scm /mnt/etc/config.scm
698 guix system build /mnt/etc/config.scm
699 guix system init /mnt/etc/config.scm /mnt --no-substitutes
703 (define (enter-luks-passphrase marionette)
704 "Return a gexp to be inserted in the basic system test running on MARIONETTE
705 to enter the LUKS passphrase."
706 (let ((ocrad (file-append ocrad "/bin/ocrad")))
708 (define (passphrase-prompt? text)
709 (string-contains (pk 'screen-text text) "Enter pass"))
711 (define (bios-boot-screen? text)
712 ;; Return true if TEXT corresponds to the boot screen, before GRUB's
714 (string-prefix? "SeaBIOS" text))
716 (test-assert "enter LUKS passphrase for GRUB"
718 ;; At this point we have no choice but to use OCR to determine
719 ;; when the passphrase should be entered.
720 (wait-for-screen-text #$marionette passphrase-prompt?
722 (marionette-type #$(string-append %luks-passphrase "\n")
725 ;; Now wait until we leave the boot screen. This is necessary so
726 ;; we can then be sure we match the "Enter passphrase" prompt from
727 ;; 'cryptsetup', in the initrd.
728 (wait-for-screen-text #$marionette (negate bios-boot-screen?)
732 (test-assert "enter LUKS passphrase for the initrd"
734 ;; XXX: Here we use OCR as well but we could instead use QEMU
735 ;; '-serial stdio' and run it in an input pipe,
736 (wait-for-screen-text #$marionette passphrase-prompt?
739 (marionette-type #$(string-append %luks-passphrase "\n")
742 ;; Take a screenshot for debugging purposes.
743 (marionette-control (string-append "screendump " #$output
744 "/post-initrd-passphrase.ppm")
747 (define %test-encrypted-root-os
749 (name "encrypted-root-os")
751 "Test basic functionality of an OS installed like one would do by hand.
752 This test is expensive in terms of CPU and storage usage since we need to
753 build (current-guix) and then store a couple of full system images.")
755 (mlet* %store-monad ((image (run-install %encrypted-root-os
756 %encrypted-root-os-source
758 %encrypted-root-installation-script))
759 (command (qemu-command/writable-image image)))
760 (run-basic-test %encrypted-root-os command "encrypted-root-os"
761 #:initialization enter-luks-passphrase)))))
765 ;;; Btrfs root file system.
768 (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
769 ;; The OS we want to install.
770 (use-modules (gnu) (gnu tests) (srfi srfi-1))
773 (host-name "liberigilo")
774 (timezone "Europe/Paris")
775 (locale "en_US.UTF-8")
777 (bootloader (bootloader-configuration
778 (bootloader grub-bootloader)
779 (target "/dev/vdb")))
780 (kernel-arguments '("console=ttyS0"))
781 (file-systems (cons (file-system
782 (device (file-system-label "my-root"))
786 (users (cons (user-account
789 (supplementary-groups '("wheel" "audio" "video")))
790 %base-user-accounts))
791 (services (cons (service marionette-service-type
792 (marionette-configuration
793 (imported-modules '((gnu services herd)
794 (guix combinators)))))
797 (define %btrfs-root-installation-script
798 ;; Shell script of a simple installation.
804 export GUIX_BUILD_OPTIONS=--no-grafts
805 ls -l /run/current-system/gc-roots
806 parted --script /dev/vdb mklabel gpt \\
807 mkpart primary ext2 1M 3M \\
808 mkpart primary ext2 3M 2G \\
811 mkfs.btrfs -L my-root /dev/vdb2
813 btrfs subvolume create /mnt/home
814 herd start cow-store /mnt
816 cp /etc/target-config.scm /mnt/etc/config.scm
817 guix system build /mnt/etc/config.scm
818 guix system init /mnt/etc/config.scm /mnt --no-substitutes
822 (define %test-btrfs-root-os
824 (name "btrfs-root-os")
826 "Test basic functionality of an OS installed like one would do by hand.
827 This test is expensive in terms of CPU and storage usage since we need to
828 build (current-guix) and then store a couple of full system images.")
830 (mlet* %store-monad ((image (run-install %btrfs-root-os
831 %btrfs-root-os-source
833 %btrfs-root-installation-script))
834 (command (qemu-command/writable-image image)))
835 (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
839 ;;; JFS root file system.
842 (define-os-with-source (%jfs-root-os %jfs-root-os-source)
843 ;; The OS we want to install.
844 (use-modules (gnu) (gnu tests) (srfi srfi-1))
847 (host-name "liberigilo")
848 (timezone "Europe/Paris")
849 (locale "en_US.UTF-8")
851 (bootloader (bootloader-configuration
852 (bootloader grub-bootloader)
853 (target "/dev/vdb")))
854 (kernel-arguments '("console=ttyS0"))
855 (file-systems (cons (file-system
856 (device (file-system-label "my-root"))
860 (users (cons (user-account
863 (supplementary-groups '("wheel" "audio" "video")))
864 %base-user-accounts))
865 (services (cons (service marionette-service-type
866 (marionette-configuration
867 (imported-modules '((gnu services herd)
868 (guix combinators)))))
871 (define %jfs-root-installation-script
872 ;; Shell script of a simple installation.
878 export GUIX_BUILD_OPTIONS=--no-grafts
879 ls -l /run/current-system/gc-roots
880 parted --script /dev/vdb mklabel gpt \\
881 mkpart primary ext2 1M 3M \\
882 mkpart primary ext2 3M 2G \\
885 jfs_mkfs -L my-root -q /dev/vdb2
887 herd start cow-store /mnt
889 cp /etc/target-config.scm /mnt/etc/config.scm
890 guix system build /mnt/etc/config.scm
891 guix system init /mnt/etc/config.scm /mnt --no-substitutes
895 (define %test-jfs-root-os
899 "Test basic functionality of an OS installed like one would do by hand.
900 This test is expensive in terms of CPU and storage usage since we need to
901 build (current-guix) and then store a couple of full system images.")
903 (mlet* %store-monad ((image (run-install %jfs-root-os
906 %jfs-root-installation-script))
907 (command (qemu-command/writable-image image)))
908 (run-basic-test %jfs-root-os command "jfs-root-os")))))
912 ;;; Installation through the graphical interface.
916 ;; Syslog configuration that dumps to /dev/console, so we can see the
917 ;; installer's messages during the test.
918 (computed-file "syslog.conf"
920 (copy-file #$%default-syslog.conf #$output)
921 (chmod #$output #o644)
922 (let ((port (open-file #$output "a")))
923 (display "\n*.info /dev/console\n" port)
926 (define (operating-system-with-console-syslog os)
927 "Return OS with a syslog service that writes to /dev/console."
930 (services (modify-services (operating-system-user-services os)
931 (syslog-service-type config
933 (syslog-configuration
935 (config-file %syslog-conf)))))))
937 (define %root-password "foo")
939 (define* (gui-test-program marionette #:key (encrypted? #f))
941 (define (screenshot file)
942 (marionette-control (string-append "screendump " file)
945 (setvbuf (current-output-port) 'none)
946 (setvbuf (current-error-port) 'none)
948 (marionette-eval '(use-modules (gnu installer tests))
951 ;; Arrange so that 'converse' prints debugging output to the console.
952 (marionette-eval '(let ((console (open-output-file "/dev/console")))
953 (setvbuf console 'none)
954 (conversation-log-port console))
957 ;; Tell the installer to not wait for the Connman "online" status.
958 (marionette-eval '(call-with-output-file "/tmp/installer-assume-online"
962 ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
964 (marionette-eval '(call-with-output-file
965 "/tmp/installer-system-init-options"
967 (write '("--no-grafts" "--no-substitutes")
971 (marionette-eval '(define installer-socket
972 (open-installer-socket))
974 (screenshot "installer-start.ppm")
976 (marionette-eval '(choose-locale+keyboard installer-socket)
978 (screenshot "installer-locale.ppm")
980 ;; Choose the host name that the "basic" test expects.
981 (marionette-eval '(enter-host-name+passwords installer-socket
982 #:host-name "liberigilo"
989 (screenshot "installer-services.ppm")
991 (marionette-eval '(choose-services installer-socket
992 #:desktop-environments '()
993 #:choose-network-service?
996 (screenshot "installer-partitioning.ppm")
998 (marionette-eval '(choose-partitioning installer-socket
999 #:encrypted? #$encrypted?
1000 #:passphrase #$%luks-passphrase)
1002 (screenshot "installer-run.ppm")
1004 (marionette-eval '(conclude-installation installer-socket)
1010 (define %extra-packages
1011 ;; Packages needed when installing with an encrypted root.
1013 lvm2-static cryptsetup-static e2fsck/static
1016 (define installation-os-for-gui-tests
1017 ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
1018 ;; target OS, as well as syslog output redirected to the console so we can
1019 ;; see what the installer is up to.
1020 (marionette-operating-system
1022 (inherit (operating-system-with-console-syslog
1023 (operating-system-add-packages
1024 (operating-system-with-current-guix
1027 (kernel-arguments '("console=ttyS0")))
1028 #:imported-modules '((gnu services herd)
1029 (gnu installer tests)
1030 (guix combinators))))
1032 (define* (guided-installation-test name #:key encrypted?)
1035 (inherit %minimal-os)
1036 (users (append (list (user-account
1038 (comment "Bob's sister")
1040 (supplementary-groups
1041 '("wheel" "audio" "video")))
1044 (comment "Alice's brother")
1046 (supplementary-groups
1047 '("wheel" "audio" "video"))))
1048 %base-user-accounts))
1049 ;; The installer does not create a swap device in guided mode with
1050 ;; encryption support.
1051 (swap-devices (if encrypted? '() '("/dev/vdb2")))
1052 (services (cons (service dhcp-client-service-type)
1053 (operating-system-user-services %minimal-os)))))
1058 "Install an OS using the graphical installer and test it.")
1060 (mlet* %store-monad ((image (run-install os '(this is unused)
1062 #:os installation-os-for-gui-tests
1064 (lambda (marionette)
1067 #:encrypted? encrypted?))))
1068 (command (qemu-command/writable-image image)))
1069 (run-basic-test os command name
1070 #:initialization (and encrypted? enter-luks-passphrase)
1071 #:root-password %root-password)))))
1073 (define %test-gui-installed-os
1074 (guided-installation-test "gui-installed-os"
1077 (define %test-gui-installed-os-encrypted
1078 (guided-installation-test "gui-installed-os-encrypted"
1081 ;;; install.scm ends here