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
236 ;; Don't provide substitutes; too big.
237 #:substitutable? #f)))
239 (with-imported-modules '((guix build utils)
240 (gnu build marionette))
242 (use-modules (guix build utils)
243 (gnu build marionette))
245 (set-path-environment-variable "PATH" '("bin")
246 (list #$qemu-minimal))
248 (system* "qemu-img" "create" "-f" "qcow2"
249 #$output #$(number->string target-size))
253 `(,(which #$(qemu-command system))
257 ((string=? "ext4" installation-disk-image-file-system-type)
259 ,(string-append "file=" #$image
260 ",if=virtio,readonly")))
261 ((string=? "iso9660" installation-disk-image-file-system-type)
262 #~("-cdrom" #$image))
265 "unsupported installation-disk-image-file-system-type:"
266 installation-disk-image-file-system-type)))
268 ,(string-append "file=" #$output ",if=virtio")
269 ,@(if (file-exists? "/dev/kvm")
273 (pk 'uname (marionette-eval '(uname) marionette))
276 (marionette-eval '(begin
277 (use-modules (gnu services herd))
281 (when #$(->bool script)
282 (marionette-eval '(call-with-output-file "/etc/target-config.scm"
284 (write '#$target-os-source port)))
287 ;; Run SCRIPT. It typically invokes 'reboot' as a last step and
288 ;; thus normally gets killed with SIGTERM by PID 1.
289 (let ((status (marionette-eval '(system #$script) marionette)))
290 (exit (or (equal? (status:term-sig status) SIGTERM)
291 (equal? (status:exit-val status) 0)))))
293 (when #$(->bool gui-test)
294 (wait-for-unix-socket "/var/guix/installer-socket"
296 (format #t "installer socket ready~%")
298 (exit #$(and gui-test
299 (gui-test #~marionette)))))))
301 (gexp->derivation "installation" install
302 #:substitutable? #f))) ;too big
304 (define* (qemu-command/writable-image image #:key (memory-size 256))
305 "Return as a monadic value the command to run QEMU on a writable copy of
306 IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
307 (mlet %store-monad ((system (current-system)))
308 (return #~(let ((image #$image))
309 ;; First we need a writable copy of the image.
310 (format #t "creating writable image from '~a'...~%" image)
311 (unless (zero? (system* #+(file-append qemu-minimal
313 "create" "-f" "qcow2"
315 (string-append "backing_file=" image)
317 (error "failed to create writable QEMU image" image))
319 (chmod "disk.img" #o644)
320 `(,(string-append #$qemu-minimal "/bin/"
321 #$(qemu-command system))
322 ,@(if (file-exists? "/dev/kvm")
325 "-no-reboot" "-m" #$(number->string memory-size)
326 "-drive" "file=disk.img,if=virtio")))))
328 (define %test-installed-os
330 (name "installed-os")
332 "Test basic functionality of an OS installed like one would do by hand.
333 This test is expensive in terms of CPU and storage usage since we need to
334 build (current-guix) and then store a couple of full system images.")
336 (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
337 (command (qemu-command/writable-image image)))
338 (run-basic-test %minimal-os command
341 (define %test-installed-extlinux-os
343 (name "installed-extlinux-os")
345 "Test basic functionality of an OS booted with an extlinux bootloader. As
346 per %test-installed-os, this test is expensive in terms of CPU and storage.")
348 (mlet* %store-monad ((image (run-install %minimal-extlinux-os
349 %minimal-extlinux-os-source
353 %extlinux-gpt-installation-script))
354 (command (qemu-command/writable-image image)))
355 (run-basic-test %minimal-extlinux-os command
356 "installed-extlinux-os")))))
360 ;;; Installation through an ISO image.
363 (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
364 ;; The OS we want to install.
365 (use-modules (gnu) (gnu tests) (srfi srfi-1))
368 (host-name "liberigilo")
369 (timezone "Europe/Paris")
370 (locale "en_US.UTF-8")
372 (bootloader (bootloader-configuration
373 (bootloader grub-bootloader)
374 (target "/dev/vda")))
375 (kernel-arguments '("console=ttyS0"))
376 (file-systems (cons (file-system
377 (device (file-system-label "my-root"))
381 (users (cons (user-account
383 (comment "Bob's sister")
385 (supplementary-groups '("wheel" "audio" "video")))
386 %base-user-accounts))
387 (services (cons (service marionette-service-type
388 (marionette-configuration
389 (imported-modules '((gnu services herd)
390 (guix combinators)))))
393 (define %simple-installation-script-for-/dev/vda
394 ;; Shell script of a simple installation.
400 export GUIX_BUILD_OPTIONS=--no-grafts
402 parted --script /dev/vda mklabel gpt \\
403 mkpart primary ext2 1M 3M \\
404 mkpart primary ext2 3M 1.4G \\
407 mkfs.ext4 -L my-root /dev/vda2
410 herd start cow-store /mnt
412 cp /etc/target-config.scm /mnt/etc/config.scm
413 guix system init /mnt/etc/config.scm /mnt --no-substitutes
417 (define %test-iso-image-installer
419 (name "iso-image-installer")
423 (mlet* %store-monad ((image (run-install
425 %minimal-os-on-vda-source
427 %simple-installation-script-for-/dev/vda
428 #:installation-disk-image-file-system-type
430 (command (qemu-command/writable-image image)))
431 (run-basic-test %minimal-os-on-vda command name)))))
438 (define-os-with-source (%separate-home-os %separate-home-os-source)
439 ;; The OS we want to install.
440 (use-modules (gnu) (gnu tests) (srfi srfi-1))
443 (host-name "liberigilo")
444 (timezone "Europe/Paris")
445 (locale "en_US.utf8")
447 (bootloader (bootloader-configuration
448 (bootloader grub-bootloader)
449 (target "/dev/vdb")))
450 (kernel-arguments '("console=ttyS0"))
451 (file-systems (cons* (file-system
452 (device (file-system-label "my-root"))
457 (mount-point "/home")
460 (users (cons* (user-account
466 %base-user-accounts))
467 (services (cons (service marionette-service-type
468 (marionette-configuration
469 (imported-modules '((gnu services herd)
470 (guix combinators)))))
473 (define %test-separate-home-os
475 (name "separate-home-os")
477 "Test basic functionality of an installed OS with a separate /home
478 partition. In particular, home directories must be correctly created (see
479 <https://bugs.gnu.org/21108>).")
481 (mlet* %store-monad ((image (run-install %separate-home-os
482 %separate-home-os-source
484 %simple-installation-script))
485 (command (qemu-command/writable-image image)))
486 (run-basic-test %separate-home-os command "separate-home-os")))))
490 ;;; Separate /gnu/store partition.
493 (define-os-with-source (%separate-store-os %separate-store-os-source)
494 ;; The OS we want to install.
495 (use-modules (gnu) (gnu tests) (srfi srfi-1))
498 (host-name "liberigilo")
499 (timezone "Europe/Paris")
500 (locale "en_US.UTF-8")
502 (bootloader (bootloader-configuration
503 (bootloader grub-bootloader)
504 (target "/dev/vdb")))
505 (kernel-arguments '("console=ttyS0"))
506 (file-systems (cons* (file-system
507 (device (file-system-label "root-fs"))
511 (device (file-system-label "store-fs"))
515 (users %base-user-accounts)
516 (services (cons (service marionette-service-type
517 (marionette-configuration
518 (imported-modules '((gnu services herd)
519 (guix combinators)))))
522 (define %separate-store-installation-script
523 ;; Installation with a separate /gnu partition.
529 export GUIX_BUILD_OPTIONS=--no-grafts
531 parted --script /dev/vdb mklabel gpt \\
532 mkpart primary ext2 1M 3M \\
533 mkpart primary ext2 3M 400M \\
534 mkpart primary ext2 400M 2.1G \\
537 mkfs.ext4 -L root-fs /dev/vdb2
538 mkfs.ext4 -L store-fs /dev/vdb3
541 mount /dev/vdb3 /mnt/gnu
544 herd start cow-store /mnt
546 cp /etc/target-config.scm /mnt/etc/config.scm
547 guix system init /mnt/etc/config.scm /mnt --no-substitutes
551 (define %test-separate-store-os
553 (name "separate-store-os")
555 "Test basic functionality of an OS installed like one would do by hand,
556 where /gnu lives on a separate partition.")
558 (mlet* %store-monad ((image (run-install %separate-store-os
559 %separate-store-os-source
561 %separate-store-installation-script))
562 (command (qemu-command/writable-image image)))
563 (run-basic-test %separate-store-os command "separate-store-os")))))
567 ;;; RAID root device.
570 (define-os-with-source (%raid-root-os %raid-root-os-source)
571 ;; An OS whose root partition is a RAID partition.
572 (use-modules (gnu) (gnu tests))
575 (host-name "raidified")
576 (timezone "Europe/Paris")
577 (locale "en_US.utf8")
579 (bootloader (bootloader-configuration
580 (bootloader grub-bootloader)
581 (target "/dev/vdb")))
582 (kernel-arguments '("console=ttyS0"))
584 ;; Add a kernel module for RAID-1 (aka. "mirror").
585 (initrd-modules (cons "raid1" %base-initrd-modules))
587 (mapped-devices (list (mapped-device
588 (source (list "/dev/vda2" "/dev/vda3"))
590 (type raid-device-mapping))))
591 (file-systems (cons (file-system
592 (device (file-system-label "root-fs"))
595 (dependencies mapped-devices))
597 (users %base-user-accounts)
598 (services (cons (service marionette-service-type
599 (marionette-configuration
600 (imported-modules '((gnu services herd)
601 (guix combinators)))))
604 (define %raid-root-installation-script
605 ;; Installation with a separate /gnu partition. See
606 ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
613 export GUIX_BUILD_OPTIONS=--no-grafts
614 parted --script /dev/vdb mklabel gpt \\
615 mkpart primary ext2 1M 3M \\
616 mkpart primary ext2 3M 1.4G \\
617 mkpart primary ext2 1.4G 2.8G \\
620 yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
622 mkfs.ext4 -L root-fs /dev/md0
625 herd start cow-store /mnt
627 cp /etc/target-config.scm /mnt/etc/config.scm
628 guix system init /mnt/etc/config.scm /mnt --no-substitutes
632 (define %test-raid-root-os
634 (name "raid-root-os")
636 "Test functionality of an OS installed with a RAID root partition managed
639 (mlet* %store-monad ((image (run-install %raid-root-os
642 %raid-root-installation-script
643 #:target-size (* 2800 MiB)))
644 (command (qemu-command/writable-image image)))
645 (run-basic-test %raid-root-os
646 `(,@command) "raid-root-os")))))
650 ;;; LUKS-encrypted root file system.
653 (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
654 ;; The OS we want to install.
655 (use-modules (gnu) (gnu tests) (srfi srfi-1))
658 (host-name "liberigilo")
659 (timezone "Europe/Paris")
660 (locale "en_US.UTF-8")
662 (bootloader (bootloader-configuration
663 (bootloader grub-bootloader)
664 (target "/dev/vdb")))
666 ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
667 ;; detection logic in 'enter-luks-passphrase'.
669 (mapped-devices (list (mapped-device
670 (source (uuid "12345678-1234-1234-1234-123456789abc"))
671 (target "the-root-device")
672 (type luks-device-mapping))))
673 (file-systems (cons (file-system
674 (device "/dev/mapper/the-root-device")
678 (users (cons (user-account
681 (supplementary-groups '("wheel" "audio" "video")))
682 %base-user-accounts))
683 (services (cons (service marionette-service-type
684 (marionette-configuration
685 (imported-modules '((gnu services herd)
686 (guix combinators)))))
689 (define %luks-passphrase
690 ;; LUKS encryption passphrase used in tests.
693 (define %encrypted-root-installation-script
694 ;; Shell script of a simple installation.
700 export GUIX_BUILD_OPTIONS=--no-grafts
701 ls -l /run/current-system/gc-roots
702 parted --script /dev/vdb mklabel gpt \\
703 mkpart primary ext2 1M 3M \\
704 mkpart primary ext2 3M 1.4G \\
707 echo -n " %luks-passphrase " | \\
708 cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
709 echo -n " %luks-passphrase " | \\
710 cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
711 mkfs.ext4 -L my-root /dev/mapper/the-root-device
712 mount LABEL=my-root /mnt
713 herd start cow-store /mnt
715 cp /etc/target-config.scm /mnt/etc/config.scm
716 guix system build /mnt/etc/config.scm
717 guix system init /mnt/etc/config.scm /mnt --no-substitutes
721 (define (enter-luks-passphrase marionette)
722 "Return a gexp to be inserted in the basic system test running on MARIONETTE
723 to enter the LUKS passphrase."
724 (let ((ocrad (file-append ocrad "/bin/ocrad")))
726 (define (passphrase-prompt? text)
727 (string-contains (pk 'screen-text text) "Enter pass"))
729 (define (bios-boot-screen? text)
730 ;; Return true if TEXT corresponds to the boot screen, before GRUB's
732 (string-prefix? "SeaBIOS" text))
734 (test-assert "enter LUKS passphrase for GRUB"
736 ;; At this point we have no choice but to use OCR to determine
737 ;; when the passphrase should be entered.
738 (wait-for-screen-text #$marionette passphrase-prompt?
740 (marionette-type #$(string-append %luks-passphrase "\n")
743 ;; Now wait until we leave the boot screen. This is necessary so
744 ;; we can then be sure we match the "Enter passphrase" prompt from
745 ;; 'cryptsetup', in the initrd.
746 (wait-for-screen-text #$marionette (negate bios-boot-screen?)
750 (test-assert "enter LUKS passphrase for the initrd"
752 ;; XXX: Here we use OCR as well but we could instead use QEMU
753 ;; '-serial stdio' and run it in an input pipe,
754 (wait-for-screen-text #$marionette passphrase-prompt?
757 (marionette-type #$(string-append %luks-passphrase "\n")
760 ;; Take a screenshot for debugging purposes.
761 (marionette-control (string-append "screendump " #$output
762 "/post-initrd-passphrase.ppm")
765 (define %test-encrypted-root-os
767 (name "encrypted-root-os")
769 "Test basic functionality of an OS installed like one would do by hand.
770 This test is expensive in terms of CPU and storage usage since we need to
771 build (current-guix) and then store a couple of full system images.")
773 (mlet* %store-monad ((image (run-install %encrypted-root-os
774 %encrypted-root-os-source
776 %encrypted-root-installation-script))
777 (command (qemu-command/writable-image image)))
778 (run-basic-test %encrypted-root-os command "encrypted-root-os"
779 #:initialization enter-luks-passphrase)))))
783 ;;; Btrfs root file system.
786 (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
787 ;; The OS we want to install.
788 (use-modules (gnu) (gnu tests) (srfi srfi-1))
791 (host-name "liberigilo")
792 (timezone "Europe/Paris")
793 (locale "en_US.UTF-8")
795 (bootloader (bootloader-configuration
796 (bootloader grub-bootloader)
797 (target "/dev/vdb")))
798 (kernel-arguments '("console=ttyS0"))
799 (file-systems (cons (file-system
800 (device (file-system-label "my-root"))
804 (users (cons (user-account
807 (supplementary-groups '("wheel" "audio" "video")))
808 %base-user-accounts))
809 (services (cons (service marionette-service-type
810 (marionette-configuration
811 (imported-modules '((gnu services herd)
812 (guix combinators)))))
815 (define %btrfs-root-installation-script
816 ;; Shell script of a simple installation.
822 export GUIX_BUILD_OPTIONS=--no-grafts
823 ls -l /run/current-system/gc-roots
824 parted --script /dev/vdb mklabel gpt \\
825 mkpart primary ext2 1M 3M \\
826 mkpart primary ext2 3M 2G \\
829 mkfs.btrfs -L my-root /dev/vdb2
831 btrfs subvolume create /mnt/home
832 herd start cow-store /mnt
834 cp /etc/target-config.scm /mnt/etc/config.scm
835 guix system build /mnt/etc/config.scm
836 guix system init /mnt/etc/config.scm /mnt --no-substitutes
840 (define %test-btrfs-root-os
842 (name "btrfs-root-os")
844 "Test basic functionality of an OS installed like one would do by hand.
845 This test is expensive in terms of CPU and storage usage since we need to
846 build (current-guix) and then store a couple of full system images.")
848 (mlet* %store-monad ((image (run-install %btrfs-root-os
849 %btrfs-root-os-source
851 %btrfs-root-installation-script))
852 (command (qemu-command/writable-image image)))
853 (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
857 ;;; JFS root file system.
860 (define-os-with-source (%jfs-root-os %jfs-root-os-source)
861 ;; The OS we want to install.
862 (use-modules (gnu) (gnu tests) (srfi srfi-1))
865 (host-name "liberigilo")
866 (timezone "Europe/Paris")
867 (locale "en_US.UTF-8")
869 (bootloader (bootloader-configuration
870 (bootloader grub-bootloader)
871 (target "/dev/vdb")))
872 (kernel-arguments '("console=ttyS0"))
873 (file-systems (cons (file-system
874 (device (file-system-label "my-root"))
878 (users (cons (user-account
881 (supplementary-groups '("wheel" "audio" "video")))
882 %base-user-accounts))
883 (services (cons (service marionette-service-type
884 (marionette-configuration
885 (imported-modules '((gnu services herd)
886 (guix combinators)))))
889 (define %jfs-root-installation-script
890 ;; Shell script of a simple installation.
896 export GUIX_BUILD_OPTIONS=--no-grafts
897 ls -l /run/current-system/gc-roots
898 parted --script /dev/vdb mklabel gpt \\
899 mkpart primary ext2 1M 3M \\
900 mkpart primary ext2 3M 2G \\
903 jfs_mkfs -L my-root -q /dev/vdb2
905 herd start cow-store /mnt
907 cp /etc/target-config.scm /mnt/etc/config.scm
908 guix system build /mnt/etc/config.scm
909 guix system init /mnt/etc/config.scm /mnt --no-substitutes
913 (define %test-jfs-root-os
917 "Test basic functionality of an OS installed like one would do by hand.
918 This test is expensive in terms of CPU and storage usage since we need to
919 build (current-guix) and then store a couple of full system images.")
921 (mlet* %store-monad ((image (run-install %jfs-root-os
924 %jfs-root-installation-script))
925 (command (qemu-command/writable-image image)))
926 (run-basic-test %jfs-root-os command "jfs-root-os")))))
930 ;;; Installation through the graphical interface.
934 ;; Syslog configuration that dumps to /dev/console, so we can see the
935 ;; installer's messages during the test.
936 (computed-file "syslog.conf"
938 (copy-file #$%default-syslog.conf #$output)
939 (chmod #$output #o644)
940 (let ((port (open-file #$output "a")))
941 (display "\n*.info /dev/console\n" port)
944 (define (operating-system-with-console-syslog os)
945 "Return OS with a syslog service that writes to /dev/console."
948 (services (modify-services (operating-system-user-services os)
949 (syslog-service-type config
951 (syslog-configuration
953 (config-file %syslog-conf)))))))
955 (define %root-password "foo")
957 (define* (gui-test-program marionette
962 (define (screenshot file)
963 (marionette-control (string-append "screendump " file)
966 (define-syntax-rule (marionette-eval* exp marionette)
967 (or (marionette-eval exp marionette)
968 (throw 'marionette-eval-failure 'exp)))
970 (setvbuf (current-output-port) 'none)
971 (setvbuf (current-error-port) 'none)
973 (marionette-eval* '(use-modules (gnu installer tests))
976 ;; Arrange so that 'converse' prints debugging output to the console.
977 (marionette-eval* '(let ((console (open-output-file "/dev/console")))
978 (setvbuf console 'none)
979 (conversation-log-port console))
982 ;; Tell the installer to not wait for the Connman "online" status.
983 (marionette-eval* '(call-with-output-file "/tmp/installer-assume-online"
987 ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
989 (marionette-eval* '(call-with-output-file
990 "/tmp/installer-system-init-options"
992 (write '("--no-grafts" "--no-substitutes")
996 (marionette-eval* '(define installer-socket
997 (open-installer-socket))
999 (screenshot "installer-start.ppm")
1001 (marionette-eval* '(choose-locale+keyboard installer-socket)
1003 (screenshot "installer-locale.ppm")
1005 ;; Choose the host name that the "basic" test expects.
1006 (marionette-eval* '(enter-host-name+passwords installer-socket
1007 #:host-name "liberigilo"
1014 (screenshot "installer-services.ppm")
1016 (marionette-eval* '(choose-services installer-socket
1017 #:choose-desktop-environment?
1019 #:choose-network-service?
1022 (screenshot "installer-partitioning.ppm")
1024 (marionette-eval* '(choose-partitioning installer-socket
1025 #:encrypted? #$encrypted?
1026 #:passphrase #$%luks-passphrase)
1028 (screenshot "installer-run.ppm")
1030 (marionette-eval* '(conclude-installation installer-socket)
1036 (define %extra-packages
1037 ;; Packages needed when installing with an encrypted root.
1039 lvm2-static cryptsetup-static e2fsck/static
1042 (define installation-os-for-gui-tests
1043 ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
1044 ;; target OS, as well as syslog output redirected to the console so we can
1045 ;; see what the installer is up to.
1046 (marionette-operating-system
1048 (inherit (operating-system-with-console-syslog
1049 (operating-system-add-packages
1050 (operating-system-with-current-guix
1053 (kernel-arguments '("console=ttyS0")))
1054 #:imported-modules '((gnu services herd)
1055 (gnu installer tests)
1056 (guix combinators))))
1058 (define* (installation-target-os-for-gui-tests
1059 #:key (encrypted? #f))
1061 (inherit %minimal-os)
1062 (users (append (list (user-account
1064 (comment "Bob's sister")
1066 (supplementary-groups
1067 '("wheel" "audio" "video")))
1070 (comment "Alice's brother")
1072 (supplementary-groups
1073 '("wheel" "audio" "video"))))
1074 %base-user-accounts))
1075 ;; The installer does not create a swap device in guided mode with
1076 ;; encryption support.
1077 (swap-devices (if encrypted? '() '("/dev/vdb2")))
1078 (services (cons (service dhcp-client-service-type)
1079 (operating-system-user-services %minimal-os)))))
1081 (define* (installation-target-desktop-os-for-gui-tests
1082 #:key (encrypted? #f))
1084 (inherit (installation-target-os-for-gui-tests
1085 #:encrypted? encrypted?))
1086 (keyboard-layout (keyboard-layout "us" "altgr-intl"))
1088 ;; Make sure that all the packages and services that may be used by the
1089 ;; graphical installer are available.
1091 (list openbox awesome i3-wm i3status
1092 dmenu st ratpoison xterm)
1096 (list (service gnome-desktop-service-type)
1097 (service xfce-desktop-service-type)
1098 (service mate-desktop-service-type)
1099 (service enlightenment-desktop-service-type)
1100 (set-xorg-configuration
1102 (keyboard-layout keyboard-layout)))
1103 (service marionette-service-type
1104 (marionette-configuration
1105 (imported-modules '((gnu services herd)
1107 (guix combinators))))))
1108 %desktop-services))))
1110 (define* (guided-installation-test name
1115 (install-size 'guess)
1116 (target-size (* 2200 MiB)))
1120 "Install an OS using the graphical installer and test it.")
1123 ((image (run-install target-os '(this is unused)
1125 #:os installation-os-for-gui-tests
1126 #:install-size install-size
1127 #:target-size target-size
1128 #:installation-disk-image-file-system-type
1131 (lambda (marionette)
1135 #:encrypted? encrypted?))))
1136 (command (qemu-command/writable-image image)))
1137 (run-basic-test target-os command name
1138 #:initialization (and encrypted? enter-luks-passphrase)
1139 #:root-password %root-password)))))
1141 (define %test-gui-installed-os
1142 (guided-installation-test
1144 #:target-os (installation-target-os-for-gui-tests)))
1146 (define %test-gui-installed-os-encrypted
1147 (guided-installation-test
1148 "gui-installed-os-encrypted"
1150 #:target-os (installation-target-os-for-gui-tests
1153 ;; Building a desktop image is very time and space consuming. Install all
1154 ;; desktop environments in a single test to reduce the overhead.
1155 (define %test-gui-installed-desktop-os-encrypted
1156 (guided-installation-test "gui-installed-desktop-os-encrypted"
1160 (installation-target-desktop-os-for-gui-tests
1162 ;; XXX: The disk-image size guess is too low. Use
1163 ;; a constant value until this is fixed.
1164 #:install-size (* 8000 MiB)
1165 #:target-size (* 9000 MiB)))
1167 ;;; install.scm ends here