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>
6 ;;; This file is part of GNU Guix.
8 ;;; GNU Guix is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
13 ;;; GNU Guix is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;;; GNU General Public License for more details.
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21 (define-module (gnu tests install)
23 #:use-module (gnu bootloader extlinux)
24 #:use-module (gnu tests)
25 #:use-module (gnu tests base)
26 #:use-module (gnu system)
27 #:use-module (gnu system install)
28 #:use-module (gnu system vm)
29 #:use-module ((gnu build vm) #:select (qemu-command))
30 #:use-module (gnu packages admin)
31 #:use-module (gnu packages bootloaders)
32 #:use-module (gnu packages cryptsetup)
33 #:use-module (gnu packages linux)
34 #:use-module (gnu packages ocr)
35 #:use-module (gnu packages openbox)
36 #:use-module (gnu packages package-management)
37 #:use-module (gnu packages ratpoison)
38 #:use-module (gnu packages suckless)
39 #:use-module (gnu packages virtualization)
40 #:use-module (gnu packages wm)
41 #:use-module (gnu packages xorg)
42 #:use-module (gnu services desktop)
43 #:use-module (gnu services networking)
44 #:use-module (gnu services xorg)
45 #:use-module (guix store)
46 #:use-module (guix monads)
47 #:use-module (guix packages)
48 #:use-module (guix grafts)
49 #:use-module (guix gexp)
50 #:use-module (guix utils)
51 #:use-module (srfi srfi-1)
52 #:export (%test-installed-os
53 %test-installed-extlinux-os
54 %test-iso-image-installer
55 %test-separate-store-os
56 %test-separate-home-os
58 %test-encrypted-root-os
62 %test-gui-installed-os
63 %test-gui-installed-os-encrypted
64 %test-gui-installed-desktop-os-encrypted))
68 ;;; Test the installation of Guix using the documented approach at the
73 (define-os-with-source (%minimal-os %minimal-os-source)
74 ;; The OS we want to install.
75 (use-modules (gnu) (gnu tests) (srfi srfi-1))
78 (host-name "liberigilo")
79 (timezone "Europe/Paris")
80 (locale "en_US.UTF-8")
82 (bootloader (bootloader-configuration
83 (bootloader grub-bootloader)
85 (kernel-arguments '("console=ttyS0"))
86 (file-systems (cons (file-system
87 (device (file-system-label "my-root"))
91 (users (cons (user-account
93 (comment "Bob's sister")
95 (supplementary-groups '("wheel" "audio" "video")))
97 (services (cons (service marionette-service-type
98 (marionette-configuration
99 (imported-modules '((gnu services herd)
101 (guix combinators)))))
104 (define (operating-system-add-packages os packages)
105 "Append PACKAGES to OS packages list."
108 (packages (append packages (operating-system-packages os)))))
110 (define-os-with-source (%minimal-extlinux-os
111 %minimal-extlinux-os-source)
112 (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
116 (host-name "liberigilo")
117 (timezone "Europe/Paris")
118 (locale "en_US.UTF-8")
120 (bootloader (bootloader-configuration
121 (bootloader extlinux-bootloader-gpt)
122 (target "/dev/vdb")))
123 (kernel-arguments '("console=ttyS0"))
124 (file-systems (cons (file-system
125 (device (file-system-label "my-root"))
129 (services (cons (service marionette-service-type
130 (marionette-configuration
131 (imported-modules '((gnu services herd)
132 (guix combinators)))))
135 (define (operating-system-with-current-guix os)
136 "Return a variant of OS that uses the current Guix."
139 (services (modify-services (operating-system-user-services os)
140 (guix-service-type config =>
143 (guix (current-guix))))))))
146 (define MiB (expt 2 20))
148 (define %simple-installation-script
149 ;; Shell script of a simple installation.
155 export GUIX_BUILD_OPTIONS=--no-grafts
157 parted --script /dev/vdb mklabel gpt \\
158 mkpart primary ext2 1M 3M \\
159 mkpart primary ext2 3M 1.4G \\
162 mkfs.ext4 -L my-root /dev/vdb2
165 herd start cow-store /mnt
167 cp /etc/target-config.scm /mnt/etc/config.scm
168 guix system init /mnt/etc/config.scm /mnt --no-substitutes
172 (define %extlinux-gpt-installation-script
173 ;; Shell script of a simple installation.
174 ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
175 ;; we make sure to pass -O '^64bit' to mkfs.
181 export GUIX_BUILD_OPTIONS=--no-grafts
183 parted --script /dev/vdb mklabel gpt \\
184 mkpart ext2 1M 1.4G \\
186 mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
189 herd start cow-store /mnt
191 cp /etc/target-config.scm /mnt/etc/config.scm
192 guix system init /mnt/etc/config.scm /mnt --no-substitutes
196 (define* (run-install target-os target-os-source
198 (script %simple-installation-script)
201 (os (marionette-operating-system
203 ;; Since the image has no network access, use the
204 ;; current Guix so the store items we need are in
205 ;; the image and add packages provided.
206 (inherit (operating-system-add-packages
207 (operating-system-with-current-guix
210 (kernel-arguments '("console=ttyS0")))
211 #:imported-modules '((gnu services herd)
212 (gnu installer tests)
213 (guix combinators))))
214 (installation-disk-image-file-system-type "ext4")
215 (install-size 'guess)
216 (target-size (* 2200 MiB)))
217 "Run SCRIPT (a shell script following the system installation procedure) in
218 OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
219 the installed system. The packages specified in PACKAGES will be appended to
220 packages defined in installation-os."
222 (mlet* %store-monad ((_ (set-grafting #f))
223 (system (current-system))
224 (target (operating-system-derivation target-os))
226 ;; Since the installation system has no network access,
227 ;; we cheat a little bit by adding TARGET to its GC
228 ;; roots. This way, we know 'guix system init' will
230 (image (system-disk-image
231 (operating-system-with-gc-roots
233 #:disk-image-size install-size
235 installation-disk-image-file-system-type)))
237 (with-imported-modules '((guix build utils)
238 (gnu build marionette))
240 (use-modules (guix build utils)
241 (gnu build marionette))
243 (set-path-environment-variable "PATH" '("bin")
244 (list #$qemu-minimal))
246 (system* "qemu-img" "create" "-f" "qcow2"
247 #$output #$(number->string target-size))
251 `(,(which #$(qemu-command system))
255 ((string=? "ext4" installation-disk-image-file-system-type)
257 ,(string-append "file=" #$image
258 ",if=virtio,readonly")))
259 ((string=? "iso9660" installation-disk-image-file-system-type)
260 #~("-cdrom" #$image))
263 "unsupported installation-disk-image-file-system-type:"
264 installation-disk-image-file-system-type)))
266 ,(string-append "file=" #$output ",if=virtio")
267 ,@(if (file-exists? "/dev/kvm")
271 (pk 'uname (marionette-eval '(uname) marionette))
274 (marionette-eval '(begin
275 (use-modules (gnu services herd))
279 (when #$(->bool script)
280 (marionette-eval '(call-with-output-file "/etc/target-config.scm"
282 (write '#$target-os-source port)))
285 ;; Run SCRIPT. It typically invokes 'reboot' as a last step and
286 ;; thus normally gets killed with SIGTERM by PID 1.
287 (let ((status (marionette-eval '(system #$script) marionette)))
288 (exit (or (equal? (status:term-sig status) SIGTERM)
289 (equal? (status:exit-val status) 0)))))
291 (when #$(->bool gui-test)
292 (wait-for-unix-socket "/var/guix/installer-socket"
294 (format #t "installer socket ready~%")
296 (exit #$(and gui-test
297 (gui-test #~marionette)))))))
299 (gexp->derivation "installation" install)))
301 (define* (qemu-command/writable-image image #:key (memory-size 256))
302 "Return as a monadic value the command to run QEMU on a writable copy of
303 IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
304 (mlet %store-monad ((system (current-system)))
305 (return #~(let ((image #$image))
306 ;; First we need a writable copy of the image.
307 (format #t "creating writable image from '~a'...~%" image)
308 (unless (zero? (system* #+(file-append qemu-minimal
310 "create" "-f" "qcow2"
312 (string-append "backing_file=" image)
314 (error "failed to create writable QEMU image" image))
316 (chmod "disk.img" #o644)
317 `(,(string-append #$qemu-minimal "/bin/"
318 #$(qemu-command system))
319 ,@(if (file-exists? "/dev/kvm")
322 "-no-reboot" "-m" #$(number->string memory-size)
323 "-drive" "file=disk.img,if=virtio")))))
325 (define %test-installed-os
327 (name "installed-os")
329 "Test basic functionality of an OS installed like one would do by hand.
330 This test is expensive in terms of CPU and storage usage since we need to
331 build (current-guix) and then store a couple of full system images.")
333 (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
334 (command (qemu-command/writable-image image)))
335 (run-basic-test %minimal-os command
338 (define %test-installed-extlinux-os
340 (name "installed-extlinux-os")
342 "Test basic functionality of an OS booted with an extlinux bootloader. As
343 per %test-installed-os, this test is expensive in terms of CPU and storage.")
345 (mlet* %store-monad ((image (run-install %minimal-extlinux-os
346 %minimal-extlinux-os-source
350 %extlinux-gpt-installation-script))
351 (command (qemu-command/writable-image image)))
352 (run-basic-test %minimal-extlinux-os command
353 "installed-extlinux-os")))))
357 ;;; Installation through an ISO image.
360 (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
361 ;; The OS we want to install.
362 (use-modules (gnu) (gnu tests) (srfi srfi-1))
365 (host-name "liberigilo")
366 (timezone "Europe/Paris")
367 (locale "en_US.UTF-8")
369 (bootloader (bootloader-configuration
370 (bootloader grub-bootloader)
371 (target "/dev/vda")))
372 (kernel-arguments '("console=ttyS0"))
373 (file-systems (cons (file-system
374 (device (file-system-label "my-root"))
378 (users (cons (user-account
380 (comment "Bob's sister")
382 (supplementary-groups '("wheel" "audio" "video")))
383 %base-user-accounts))
384 (services (cons (service marionette-service-type
385 (marionette-configuration
386 (imported-modules '((gnu services herd)
387 (guix combinators)))))
390 (define %simple-installation-script-for-/dev/vda
391 ;; Shell script of a simple installation.
397 export GUIX_BUILD_OPTIONS=--no-grafts
399 parted --script /dev/vda mklabel gpt \\
400 mkpart primary ext2 1M 3M \\
401 mkpart primary ext2 3M 1.4G \\
404 mkfs.ext4 -L my-root /dev/vda2
407 herd start cow-store /mnt
409 cp /etc/target-config.scm /mnt/etc/config.scm
410 guix system init /mnt/etc/config.scm /mnt --no-substitutes
414 (define %test-iso-image-installer
416 (name "iso-image-installer")
420 (mlet* %store-monad ((image (run-install
422 %minimal-os-on-vda-source
424 %simple-installation-script-for-/dev/vda
425 #:installation-disk-image-file-system-type
427 (command (qemu-command/writable-image image)))
428 (run-basic-test %minimal-os-on-vda command name)))))
435 (define-os-with-source (%separate-home-os %separate-home-os-source)
436 ;; The OS we want to install.
437 (use-modules (gnu) (gnu tests) (srfi srfi-1))
440 (host-name "liberigilo")
441 (timezone "Europe/Paris")
442 (locale "en_US.utf8")
444 (bootloader (bootloader-configuration
445 (bootloader grub-bootloader)
446 (target "/dev/vdb")))
447 (kernel-arguments '("console=ttyS0"))
448 (file-systems (cons* (file-system
449 (device (file-system-label "my-root"))
454 (mount-point "/home")
457 (users (cons* (user-account
463 %base-user-accounts))
464 (services (cons (service marionette-service-type
465 (marionette-configuration
466 (imported-modules '((gnu services herd)
467 (guix combinators)))))
470 (define %test-separate-home-os
472 (name "separate-home-os")
474 "Test basic functionality of an installed OS with a separate /home
475 partition. In particular, home directories must be correctly created (see
476 <https://bugs.gnu.org/21108>).")
478 (mlet* %store-monad ((image (run-install %separate-home-os
479 %separate-home-os-source
481 %simple-installation-script))
482 (command (qemu-command/writable-image image)))
483 (run-basic-test %separate-home-os command "separate-home-os")))))
487 ;;; Separate /gnu/store partition.
490 (define-os-with-source (%separate-store-os %separate-store-os-source)
491 ;; The OS we want to install.
492 (use-modules (gnu) (gnu tests) (srfi srfi-1))
495 (host-name "liberigilo")
496 (timezone "Europe/Paris")
497 (locale "en_US.UTF-8")
499 (bootloader (bootloader-configuration
500 (bootloader grub-bootloader)
501 (target "/dev/vdb")))
502 (kernel-arguments '("console=ttyS0"))
503 (file-systems (cons* (file-system
504 (device (file-system-label "root-fs"))
508 (device (file-system-label "store-fs"))
512 (users %base-user-accounts)
513 (services (cons (service marionette-service-type
514 (marionette-configuration
515 (imported-modules '((gnu services herd)
516 (guix combinators)))))
519 (define %separate-store-installation-script
520 ;; Installation with a separate /gnu partition.
526 export GUIX_BUILD_OPTIONS=--no-grafts
528 parted --script /dev/vdb mklabel gpt \\
529 mkpart primary ext2 1M 3M \\
530 mkpart primary ext2 3M 400M \\
531 mkpart primary ext2 400M 2.1G \\
534 mkfs.ext4 -L root-fs /dev/vdb2
535 mkfs.ext4 -L store-fs /dev/vdb3
538 mount /dev/vdb3 /mnt/gnu
541 herd start cow-store /mnt
543 cp /etc/target-config.scm /mnt/etc/config.scm
544 guix system init /mnt/etc/config.scm /mnt --no-substitutes
548 (define %test-separate-store-os
550 (name "separate-store-os")
552 "Test basic functionality of an OS installed like one would do by hand,
553 where /gnu lives on a separate partition.")
555 (mlet* %store-monad ((image (run-install %separate-store-os
556 %separate-store-os-source
558 %separate-store-installation-script))
559 (command (qemu-command/writable-image image)))
560 (run-basic-test %separate-store-os command "separate-store-os")))))
564 ;;; RAID root device.
567 (define-os-with-source (%raid-root-os %raid-root-os-source)
568 ;; An OS whose root partition is a RAID partition.
569 (use-modules (gnu) (gnu tests))
572 (host-name "raidified")
573 (timezone "Europe/Paris")
574 (locale "en_US.utf8")
576 (bootloader (bootloader-configuration
577 (bootloader grub-bootloader)
578 (target "/dev/vdb")))
579 (kernel-arguments '("console=ttyS0"))
581 ;; Add a kernel module for RAID-1 (aka. "mirror").
582 (initrd-modules (cons "raid1" %base-initrd-modules))
584 (mapped-devices (list (mapped-device
585 (source (list "/dev/vda2" "/dev/vda3"))
587 (type raid-device-mapping))))
588 (file-systems (cons (file-system
589 (device (file-system-label "root-fs"))
592 (dependencies mapped-devices))
594 (users %base-user-accounts)
595 (services (cons (service marionette-service-type
596 (marionette-configuration
597 (imported-modules '((gnu services herd)
598 (guix combinators)))))
601 (define %raid-root-installation-script
602 ;; Installation with a separate /gnu partition. See
603 ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
610 export GUIX_BUILD_OPTIONS=--no-grafts
611 parted --script /dev/vdb mklabel gpt \\
612 mkpart primary ext2 1M 3M \\
613 mkpart primary ext2 3M 1.4G \\
614 mkpart primary ext2 1.4G 2.8G \\
617 yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
619 mkfs.ext4 -L root-fs /dev/md0
622 herd start cow-store /mnt
624 cp /etc/target-config.scm /mnt/etc/config.scm
625 guix system init /mnt/etc/config.scm /mnt --no-substitutes
629 (define %test-raid-root-os
631 (name "raid-root-os")
633 "Test functionality of an OS installed with a RAID root partition managed
636 (mlet* %store-monad ((image (run-install %raid-root-os
639 %raid-root-installation-script
640 #:target-size (* 2800 MiB)))
641 (command (qemu-command/writable-image image)))
642 (run-basic-test %raid-root-os
643 `(,@command) "raid-root-os")))))
647 ;;; LUKS-encrypted root file system.
650 (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
651 ;; The OS we want to install.
652 (use-modules (gnu) (gnu tests) (srfi srfi-1))
655 (host-name "liberigilo")
656 (timezone "Europe/Paris")
657 (locale "en_US.UTF-8")
659 (bootloader (bootloader-configuration
660 (bootloader grub-bootloader)
661 (target "/dev/vdb")))
663 ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
664 ;; detection logic in 'enter-luks-passphrase'.
666 (mapped-devices (list (mapped-device
667 (source (uuid "12345678-1234-1234-1234-123456789abc"))
668 (target "the-root-device")
669 (type luks-device-mapping))))
670 (file-systems (cons (file-system
671 (device "/dev/mapper/the-root-device")
675 (users (cons (user-account
678 (supplementary-groups '("wheel" "audio" "video")))
679 %base-user-accounts))
680 (services (cons (service marionette-service-type
681 (marionette-configuration
682 (imported-modules '((gnu services herd)
683 (guix combinators)))))
686 (define %luks-passphrase
687 ;; LUKS encryption passphrase used in tests.
690 (define %encrypted-root-installation-script
691 ;; Shell script of a simple installation.
697 export GUIX_BUILD_OPTIONS=--no-grafts
698 ls -l /run/current-system/gc-roots
699 parted --script /dev/vdb mklabel gpt \\
700 mkpart primary ext2 1M 3M \\
701 mkpart primary ext2 3M 1.4G \\
704 echo -n " %luks-passphrase " | \\
705 cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
706 echo -n " %luks-passphrase " | \\
707 cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
708 mkfs.ext4 -L my-root /dev/mapper/the-root-device
709 mount LABEL=my-root /mnt
710 herd start cow-store /mnt
712 cp /etc/target-config.scm /mnt/etc/config.scm
713 guix system build /mnt/etc/config.scm
714 guix system init /mnt/etc/config.scm /mnt --no-substitutes
718 (define (enter-luks-passphrase marionette)
719 "Return a gexp to be inserted in the basic system test running on MARIONETTE
720 to enter the LUKS passphrase."
721 (let ((ocrad (file-append ocrad "/bin/ocrad")))
723 (define (passphrase-prompt? text)
724 (string-contains (pk 'screen-text text) "Enter pass"))
726 (define (bios-boot-screen? text)
727 ;; Return true if TEXT corresponds to the boot screen, before GRUB's
729 (string-prefix? "SeaBIOS" text))
731 (test-assert "enter LUKS passphrase for GRUB"
733 ;; At this point we have no choice but to use OCR to determine
734 ;; when the passphrase should be entered.
735 (wait-for-screen-text #$marionette passphrase-prompt?
737 (marionette-type #$(string-append %luks-passphrase "\n")
740 ;; Now wait until we leave the boot screen. This is necessary so
741 ;; we can then be sure we match the "Enter passphrase" prompt from
742 ;; 'cryptsetup', in the initrd.
743 (wait-for-screen-text #$marionette (negate bios-boot-screen?)
747 (test-assert "enter LUKS passphrase for the initrd"
749 ;; XXX: Here we use OCR as well but we could instead use QEMU
750 ;; '-serial stdio' and run it in an input pipe,
751 (wait-for-screen-text #$marionette passphrase-prompt?
754 (marionette-type #$(string-append %luks-passphrase "\n")
757 ;; Take a screenshot for debugging purposes.
758 (marionette-control (string-append "screendump " #$output
759 "/post-initrd-passphrase.ppm")
762 (define %test-encrypted-root-os
764 (name "encrypted-root-os")
766 "Test basic functionality of an OS installed like one would do by hand.
767 This test is expensive in terms of CPU and storage usage since we need to
768 build (current-guix) and then store a couple of full system images.")
770 (mlet* %store-monad ((image (run-install %encrypted-root-os
771 %encrypted-root-os-source
773 %encrypted-root-installation-script))
774 (command (qemu-command/writable-image image)))
775 (run-basic-test %encrypted-root-os command "encrypted-root-os"
776 #:initialization enter-luks-passphrase)))))
780 ;;; Btrfs root file system.
783 (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
784 ;; The OS we want to install.
785 (use-modules (gnu) (gnu tests) (srfi srfi-1))
788 (host-name "liberigilo")
789 (timezone "Europe/Paris")
790 (locale "en_US.UTF-8")
792 (bootloader (bootloader-configuration
793 (bootloader grub-bootloader)
794 (target "/dev/vdb")))
795 (kernel-arguments '("console=ttyS0"))
796 (file-systems (cons (file-system
797 (device (file-system-label "my-root"))
801 (users (cons (user-account
804 (supplementary-groups '("wheel" "audio" "video")))
805 %base-user-accounts))
806 (services (cons (service marionette-service-type
807 (marionette-configuration
808 (imported-modules '((gnu services herd)
809 (guix combinators)))))
812 (define %btrfs-root-installation-script
813 ;; Shell script of a simple installation.
819 export GUIX_BUILD_OPTIONS=--no-grafts
820 ls -l /run/current-system/gc-roots
821 parted --script /dev/vdb mklabel gpt \\
822 mkpart primary ext2 1M 3M \\
823 mkpart primary ext2 3M 2G \\
826 mkfs.btrfs -L my-root /dev/vdb2
828 btrfs subvolume create /mnt/home
829 herd start cow-store /mnt
831 cp /etc/target-config.scm /mnt/etc/config.scm
832 guix system build /mnt/etc/config.scm
833 guix system init /mnt/etc/config.scm /mnt --no-substitutes
837 (define %test-btrfs-root-os
839 (name "btrfs-root-os")
841 "Test basic functionality of an OS installed like one would do by hand.
842 This test is expensive in terms of CPU and storage usage since we need to
843 build (current-guix) and then store a couple of full system images.")
845 (mlet* %store-monad ((image (run-install %btrfs-root-os
846 %btrfs-root-os-source
848 %btrfs-root-installation-script))
849 (command (qemu-command/writable-image image)))
850 (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
854 ;;; JFS root file system.
857 (define-os-with-source (%jfs-root-os %jfs-root-os-source)
858 ;; The OS we want to install.
859 (use-modules (gnu) (gnu tests) (srfi srfi-1))
862 (host-name "liberigilo")
863 (timezone "Europe/Paris")
864 (locale "en_US.UTF-8")
866 (bootloader (bootloader-configuration
867 (bootloader grub-bootloader)
868 (target "/dev/vdb")))
869 (kernel-arguments '("console=ttyS0"))
870 (file-systems (cons (file-system
871 (device (file-system-label "my-root"))
875 (users (cons (user-account
878 (supplementary-groups '("wheel" "audio" "video")))
879 %base-user-accounts))
880 (services (cons (service marionette-service-type
881 (marionette-configuration
882 (imported-modules '((gnu services herd)
883 (guix combinators)))))
886 (define %jfs-root-installation-script
887 ;; Shell script of a simple installation.
893 export GUIX_BUILD_OPTIONS=--no-grafts
894 ls -l /run/current-system/gc-roots
895 parted --script /dev/vdb mklabel gpt \\
896 mkpart primary ext2 1M 3M \\
897 mkpart primary ext2 3M 2G \\
900 jfs_mkfs -L my-root -q /dev/vdb2
902 herd start cow-store /mnt
904 cp /etc/target-config.scm /mnt/etc/config.scm
905 guix system build /mnt/etc/config.scm
906 guix system init /mnt/etc/config.scm /mnt --no-substitutes
910 (define %test-jfs-root-os
914 "Test basic functionality of an OS installed like one would do by hand.
915 This test is expensive in terms of CPU and storage usage since we need to
916 build (current-guix) and then store a couple of full system images.")
918 (mlet* %store-monad ((image (run-install %jfs-root-os
921 %jfs-root-installation-script))
922 (command (qemu-command/writable-image image)))
923 (run-basic-test %jfs-root-os command "jfs-root-os")))))
927 ;;; Installation through the graphical interface.
931 ;; Syslog configuration that dumps to /dev/console, so we can see the
932 ;; installer's messages during the test.
933 (computed-file "syslog.conf"
935 (copy-file #$%default-syslog.conf #$output)
936 (chmod #$output #o644)
937 (let ((port (open-file #$output "a")))
938 (display "\n*.info /dev/console\n" port)
941 (define (operating-system-with-console-syslog os)
942 "Return OS with a syslog service that writes to /dev/console."
945 (services (modify-services (operating-system-user-services os)
946 (syslog-service-type config
948 (syslog-configuration
950 (config-file %syslog-conf)))))))
952 (define %root-password "foo")
954 (define* (gui-test-program marionette
959 (define (screenshot file)
960 (marionette-control (string-append "screendump " file)
963 (define-syntax-rule (marionette-eval* exp marionette)
964 (or (marionette-eval exp marionette)
965 (throw 'marionette-eval-failure 'exp)))
967 (setvbuf (current-output-port) 'none)
968 (setvbuf (current-error-port) 'none)
970 (marionette-eval* '(use-modules (gnu installer tests))
973 ;; Arrange so that 'converse' prints debugging output to the console.
974 (marionette-eval* '(let ((console (open-output-file "/dev/console")))
975 (setvbuf console 'none)
976 (conversation-log-port console))
979 ;; Tell the installer to not wait for the Connman "online" status.
980 (marionette-eval* '(call-with-output-file "/tmp/installer-assume-online"
984 ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
986 (marionette-eval* '(call-with-output-file
987 "/tmp/installer-system-init-options"
989 (write '("--no-grafts" "--no-substitutes")
993 (marionette-eval* '(define installer-socket
994 (open-installer-socket))
996 (screenshot "installer-start.ppm")
998 (marionette-eval* '(choose-locale+keyboard installer-socket)
1000 (screenshot "installer-locale.ppm")
1002 ;; Choose the host name that the "basic" test expects.
1003 (marionette-eval* '(enter-host-name+passwords installer-socket
1004 #:host-name "liberigilo"
1011 (screenshot "installer-services.ppm")
1013 (marionette-eval* '(choose-services installer-socket
1014 #:choose-desktop-environment?
1016 #:choose-network-service?
1019 (screenshot "installer-partitioning.ppm")
1021 (marionette-eval* '(choose-partitioning installer-socket
1022 #:encrypted? #$encrypted?
1023 #:passphrase #$%luks-passphrase)
1025 (screenshot "installer-run.ppm")
1027 (marionette-eval* '(conclude-installation installer-socket)
1033 (define %extra-packages
1034 ;; Packages needed when installing with an encrypted root.
1036 lvm2-static cryptsetup-static e2fsck/static
1039 (define installation-os-for-gui-tests
1040 ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
1041 ;; target OS, as well as syslog output redirected to the console so we can
1042 ;; see what the installer is up to.
1043 (marionette-operating-system
1045 (inherit (operating-system-with-console-syslog
1046 (operating-system-add-packages
1047 (operating-system-with-current-guix
1050 (kernel-arguments '("console=ttyS0")))
1051 #:imported-modules '((gnu services herd)
1052 (gnu installer tests)
1053 (guix combinators))))
1055 (define* (installation-target-os-for-gui-tests
1056 #:key (encrypted? #f))
1058 (inherit %minimal-os)
1059 (users (append (list (user-account
1061 (comment "Bob's sister")
1063 (supplementary-groups
1064 '("wheel" "audio" "video")))
1067 (comment "Alice's brother")
1069 (supplementary-groups
1070 '("wheel" "audio" "video"))))
1071 %base-user-accounts))
1072 ;; The installer does not create a swap device in guided mode with
1073 ;; encryption support.
1074 (swap-devices (if encrypted? '() '("/dev/vdb2")))
1075 (services (cons (service dhcp-client-service-type)
1076 (operating-system-user-services %minimal-os)))))
1078 (define* (installation-target-desktop-os-for-gui-tests
1079 #:key (encrypted? #f))
1081 (inherit (installation-target-os-for-gui-tests
1082 #:encrypted? encrypted?))
1083 (keyboard-layout (keyboard-layout "us" "altgr-intl"))
1085 ;; Make sure that all the packages and services that may be used by the
1086 ;; graphical installer are available.
1088 (list openbox awesome i3-wm i3status
1089 dmenu st ratpoison xterm)
1093 (list (service gnome-desktop-service-type)
1094 (service xfce-desktop-service-type)
1095 (service mate-desktop-service-type)
1096 (service enlightenment-desktop-service-type)
1097 (set-xorg-configuration
1099 (keyboard-layout keyboard-layout)))
1100 (service marionette-service-type
1101 (marionette-configuration
1102 (imported-modules '((gnu services herd)
1104 (guix combinators))))))
1105 %desktop-services))))
1107 (define* (guided-installation-test name
1112 (install-size 'guess)
1113 (target-size (* 2200 MiB)))
1117 "Install an OS using the graphical installer and test it.")
1120 ((image (run-install target-os '(this is unused)
1122 #:os installation-os-for-gui-tests
1123 #:install-size install-size
1124 #:target-size target-size
1126 (lambda (marionette)
1130 #:encrypted? encrypted?))))
1131 (command (qemu-command/writable-image image)))
1132 (run-basic-test target-os command name
1133 #:initialization (and encrypted? enter-luks-passphrase)
1134 #:root-password %root-password)))))
1136 (define %test-gui-installed-os
1137 (guided-installation-test
1139 #:target-os (installation-target-os-for-gui-tests)))
1141 (define %test-gui-installed-os-encrypted
1142 (guided-installation-test
1143 "gui-installed-os-encrypted"
1145 #:target-os (installation-target-os-for-gui-tests
1148 ;; Building a desktop image is very time and space consuming. Install all
1149 ;; desktop environments in a single test to reduce the overhead.
1150 (define %test-gui-installed-desktop-os-encrypted
1151 (guided-installation-test "gui-installed-desktop-os-encrypted"
1155 (installation-target-desktop-os-for-gui-tests
1157 ;; XXX: The disk-image size guess is too low. Use
1158 ;; a constant value until this is fixed.
1159 #:install-size (* 8000 MiB)
1160 #:target-size (* 9000 MiB)))
1162 ;;; install.scm ends here