Merge branch 'master' into core-updates
[jackhill/guix/guix.git] / gnu / tests / install.scm
CommitLineData
94b4274d 1;;; GNU Guix --- Functional package management for GNU
3adf320e 2;;; Copyright © 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
4f51fdba 3;;; Copyright © 2017, 2019 Tobias Geerinckx-Rice <me@tobias.gr>
94b4274d
LC
4;;;
5;;; This file is part of GNU Guix.
6;;;
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.
11;;;
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.
16;;;
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/>.
19
20(define-module (gnu tests install)
21 #:use-module (gnu)
a48a20fb 22 #:use-module (gnu bootloader extlinux)
94b4274d
LC
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))
ccb1a8c4 29 #:use-module (gnu packages admin)
a48a20fb 30 #:use-module (gnu packages bootloaders)
ccb1a8c4
LC
31 #:use-module (gnu packages cryptsetup)
32 #:use-module (gnu packages linux)
f7f292d3 33 #:use-module (gnu packages ocr)
94b4274d 34 #:use-module (gnu packages package-management)
59132b80 35 #:use-module (gnu packages virtualization)
ccb1a8c4 36 #:use-module (gnu services networking)
94b4274d
LC
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)
b1bf155f 43 #:export (%test-installed-os
a48a20fb 44 %test-installed-extlinux-os
fbc7b1f1 45 %test-iso-image-installer
5479aa2b 46 %test-separate-store-os
ae763b5b 47 %test-separate-home-os
245cc5f5 48 %test-raid-root-os
4f83afd2 49 %test-encrypted-root-os
4f51fdba 50 %test-btrfs-root-os
ccb1a8c4
LC
51 %test-jfs-root-os
52
e666a923
MO
53 %test-gui-installed-os
54 %test-gui-installed-os-encrypted))
94b4274d
LC
55
56;;; Commentary:
57;;;
59e80445 58;;; Test the installation of Guix using the documented approach at the
94b4274d
LC
59;;; command line.
60;;;
61;;; Code:
62
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))
66
67 (operating-system
68 (host-name "liberigilo")
69 (timezone "Europe/Paris")
70 (locale "en_US.UTF-8")
71
fdfdecdb
TGR
72 (bootloader (bootloader-configuration
73 (bootloader grub-bootloader)
74 (target "/dev/vdb")))
94b4274d
LC
75 (kernel-arguments '("console=ttyS0"))
76 (file-systems (cons (file-system
9ceeca08 77 (device (file-system-label "my-root"))
94b4274d
LC
78 (mount-point "/")
79 (type "ext4"))
80 %base-file-systems))
81 (users (cons (user-account
82 (name "alice")
83 (comment "Bob's sister")
84 (group "users")
cf848cc0 85 (supplementary-groups '("wheel" "audio" "video")))
94b4274d
LC
86 %base-user-accounts))
87 (services (cons (service marionette-service-type
a4bbf41b
LC
88 (marionette-configuration
89 (imported-modules '((gnu services herd)
f9d55c49 90 (guix build utils)
a4bbf41b 91 (guix combinators)))))
94b4274d
LC
92 %base-services))))
93
a48a20fb
MO
94(define (operating-system-add-packages os packages)
95 "Append PACKAGES to OS packages list."
96 (operating-system
97 (inherit os)
98 (packages (append packages (operating-system-packages os)))))
99
100(define-os-with-source (%minimal-extlinux-os
101 %minimal-extlinux-os-source)
102 (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
103 (srfi srfi-1))
104
105 (operating-system
106 (host-name "liberigilo")
107 (timezone "Europe/Paris")
108 (locale "en_US.UTF-8")
109
110 (bootloader (bootloader-configuration
111 (bootloader extlinux-bootloader-gpt)
045ebb3e 112 (target "/dev/vdb")))
a48a20fb
MO
113 (kernel-arguments '("console=ttyS0"))
114 (file-systems (cons (file-system
9ceeca08 115 (device (file-system-label "my-root"))
a48a20fb
MO
116 (mount-point "/")
117 (type "ext4"))
118 %base-file-systems))
119 (services (cons (service marionette-service-type
120 (marionette-configuration
121 (imported-modules '((gnu services herd)
122 (guix combinators)))))
123 %base-services))))
124
94b4274d
LC
125(define (operating-system-with-current-guix os)
126 "Return a variant of OS that uses the current Guix."
127 (operating-system
128 (inherit os)
129 (services (modify-services (operating-system-user-services os)
130 (guix-service-type config =>
131 (guix-configuration
132 (inherit config)
133 (guix (current-guix))))))))
134
94b4274d
LC
135\f
136(define MiB (expt 2 20))
137
b1bf155f
LC
138(define %simple-installation-script
139 ;; Shell script of a simple installation.
140 "\
141. /etc/profile
142set -e -x
143guix --version
144
145export GUIX_BUILD_OPTIONS=--no-grafts
146guix build isc-dhcp
147parted --script /dev/vdb mklabel gpt \\
148 mkpart primary ext2 1M 3M \\
198a7ac0 149 mkpart primary ext2 3M 1.4G \\
b1bf155f
LC
150 set 1 boot on \\
151 set 1 bios_grub on
152mkfs.ext4 -L my-root /dev/vdb2
153mount /dev/vdb2 /mnt
154df -h /mnt
155herd start cow-store /mnt
156mkdir /mnt/etc
157cp /etc/target-config.scm /mnt/etc/config.scm
158guix system init /mnt/etc/config.scm /mnt --no-substitutes
159sync
160reboot\n")
161
a48a20fb
MO
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.
166 "\
167. /etc/profile
168set -e -x
169guix --version
170
171export GUIX_BUILD_OPTIONS=--no-grafts
172guix build isc-dhcp
173parted --script /dev/vdb mklabel gpt \\
198a7ac0 174 mkpart ext2 1M 1.4G \\
a48a20fb
MO
175 set 1 legacy_boot on
176mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
177mount /dev/vdb1 /mnt
178df -h /mnt
179herd start cow-store /mnt
180mkdir /mnt/etc
181cp /etc/target-config.scm /mnt/etc/config.scm
182guix system init /mnt/etc/config.scm /mnt --no-substitutes
183sync
184reboot\n")
185
b1bf155f
LC
186(define* (run-install target-os target-os-source
187 #:key
188 (script %simple-installation-script)
ccb1a8c4 189 (gui-test #f)
a48a20fb 190 (packages '())
94b4274d 191 (os (marionette-operating-system
94b4274d 192 (operating-system
a48a20fb
MO
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
198 installation-os)
199 packages))
94b4274d
LC
200 (kernel-arguments '("console=ttyS0")))
201 #:imported-modules '((gnu services herd)
ccb1a8c4 202 (gnu installer tests)
94b4274d 203 (guix combinators))))
fbc7b1f1 204 (installation-disk-image-file-system-type "ext4")
5724a14e 205 (target-size (* 2200 MiB)))
59e80445 206 "Run SCRIPT (a shell script following the system installation procedure) in
b1bf155f 207OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
a48a20fb
MO
208the installed system. The packages specified in PACKAGES will be appended to
209packages defined in installation-os."
94b4274d
LC
210
211 (mlet* %store-monad ((_ (set-grafting #f))
212 (system (current-system))
b1bf155f 213 (target (operating-system-derivation target-os))
94b4274d
LC
214
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
218 ;; succeed.
219 (image (system-disk-image
220 (operating-system-with-gc-roots
221 os (list target))
91496dfc 222 #:disk-image-size 'guess
fbc7b1f1
CB
223 #:file-system-type
224 installation-disk-image-file-system-type)))
94b4274d 225 (define install
4ee96a79
LC
226 (with-imported-modules '((guix build utils)
227 (gnu build marionette))
228 #~(begin
229 (use-modules (guix build utils)
230 (gnu build marionette))
231
232 (set-path-environment-variable "PATH" '("bin")
233 (list #$qemu-minimal))
234
235 (system* "qemu-img" "create" "-f" "qcow2"
236 #$output #$(number->string target-size))
237
238 (define marionette
239 (make-marionette
fbc7b1f1
CB
240 `(,(which #$(qemu-command system))
241 "-no-reboot"
242 "-m" "800"
243 #$@(cond
244 ((string=? "ext4" installation-disk-image-file-system-type)
4e396041
LC
245 #~("-drive"
246 ,(string-append "file=" #$image
247 ",if=virtio,readonly")))
fbc7b1f1 248 ((string=? "iso9660" installation-disk-image-file-system-type)
4e396041 249 #~("-cdrom" #$image))
fbc7b1f1
CB
250 (else
251 (error
252 "unsupported installation-disk-image-file-system-type:"
253 installation-disk-image-file-system-type)))
254 "-drive"
255 ,(string-append "file=" #$output ",if=virtio")
256 ,@(if (file-exists? "/dev/kvm")
257 '("-enable-kvm")
258 '()))))
4ee96a79
LC
259
260 (pk 'uname (marionette-eval '(uname) marionette))
261
262 ;; Wait for tty1.
263 (marionette-eval '(begin
264 (use-modules (gnu services herd))
265 (start 'term-tty1))
266 marionette)
267
ccb1a8c4
LC
268 (when #$(->bool script)
269 (marionette-eval '(call-with-output-file "/etc/target-config.scm"
270 (lambda (port)
271 (write '#$target-os-source port)))
272 marionette)
273 (exit (marionette-eval '(zero? (system #$script))
274 marionette)))
275
276 (when #$(->bool gui-test)
277 (wait-for-unix-socket "/var/guix/installer-socket"
278 marionette)
279 (format #t "installer socket ready~%")
280 (force-output)
281 (exit #$(and gui-test
282 (gui-test #~marionette)))))))
b1bf155f
LC
283
284 (gexp->derivation "installation" install)))
285
b800b8da 286(define* (qemu-command/writable-image image #:key (memory-size 256))
b1bf155f 287 "Return as a monadic value the command to run QEMU on a writable copy of
1a034f04 288IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
b1bf155f
LC
289 (mlet %store-monad ((system (current-system)))
290 (return #~(let ((image #$image))
291 ;; First we need a writable copy of the image.
130079ae
LC
292 (format #t "creating writable image from '~a'...~%" image)
293 (unless (zero? (system* #+(file-append qemu-minimal
294 "/bin/qemu-img")
295 "create" "-f" "qcow2"
296 "-o"
297 (string-append "backing_file=" image)
298 "disk.img"))
299 (error "failed to create writable QEMU image" image))
300
b1bf155f
LC
301 (chmod "disk.img" #o644)
302 `(,(string-append #$qemu-minimal "/bin/"
303 #$(qemu-command system))
304 ,@(if (file-exists? "/dev/kvm")
305 '("-enable-kvm")
306 '())
b800b8da 307 "-no-reboot" "-m" #$(number->string memory-size)
b1bf155f
LC
308 "-drive" "file=disk.img,if=virtio")))))
309
b1bf155f
LC
310(define %test-installed-os
311 (system-test
312 (name "installed-os")
313 (description
314 "Test basic functionality of an OS installed like one would do by hand.
315This test is expensive in terms of CPU and storage usage since we need to
316build (current-guix) and then store a couple of full system images.")
317 (value
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
321 "installed-os")))))
322
a48a20fb
MO
323(define %test-installed-extlinux-os
324 (system-test
325 (name "installed-extlinux-os")
326 (description
327 "Test basic functionality of an OS booted with an extlinux bootloader. As
328per %test-installed-os, this test is expensive in terms of CPU and storage.")
329 (value
330 (mlet* %store-monad ((image (run-install %minimal-extlinux-os
331 %minimal-extlinux-os-source
332 #:packages
333 (list syslinux)
334 #:script
335 %extlinux-gpt-installation-script))
336 (command (qemu-command/writable-image image)))
337 (run-basic-test %minimal-extlinux-os command
338 "installed-extlinux-os")))))
339
b1bf155f 340\f
fbc7b1f1
CB
341;;;
342;;; Installation through an ISO image.
343;;;
344
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))
348
349 (operating-system
350 (host-name "liberigilo")
351 (timezone "Europe/Paris")
352 (locale "en_US.UTF-8")
353
fdfdecdb
TGR
354 (bootloader (bootloader-configuration
355 (bootloader grub-bootloader)
356 (target "/dev/vda")))
fbc7b1f1
CB
357 (kernel-arguments '("console=ttyS0"))
358 (file-systems (cons (file-system
9ceeca08 359 (device (file-system-label "my-root"))
fbc7b1f1
CB
360 (mount-point "/")
361 (type "ext4"))
362 %base-file-systems))
363 (users (cons (user-account
364 (name "alice")
365 (comment "Bob's sister")
366 (group "users")
cf848cc0 367 (supplementary-groups '("wheel" "audio" "video")))
fbc7b1f1
CB
368 %base-user-accounts))
369 (services (cons (service marionette-service-type
370 (marionette-configuration
371 (imported-modules '((gnu services herd)
372 (guix combinators)))))
373 %base-services))))
374
375(define %simple-installation-script-for-/dev/vda
376 ;; Shell script of a simple installation.
377 "\
378. /etc/profile
379set -e -x
380guix --version
381
382export GUIX_BUILD_OPTIONS=--no-grafts
383guix build isc-dhcp
384parted --script /dev/vda mklabel gpt \\
385 mkpart primary ext2 1M 3M \\
198a7ac0 386 mkpart primary ext2 3M 1.4G \\
fbc7b1f1
CB
387 set 1 boot on \\
388 set 1 bios_grub on
389mkfs.ext4 -L my-root /dev/vda2
390mount /dev/vda2 /mnt
391df -h /mnt
392herd start cow-store /mnt
393mkdir /mnt/etc
394cp /etc/target-config.scm /mnt/etc/config.scm
395guix system init /mnt/etc/config.scm /mnt --no-substitutes
396sync
397reboot\n")
398
399(define %test-iso-image-installer
400 (system-test
401 (name "iso-image-installer")
402 (description
403 "")
404 (value
405 (mlet* %store-monad ((image (run-install
406 %minimal-os-on-vda
407 %minimal-os-on-vda-source
408 #:script
409 %simple-installation-script-for-/dev/vda
410 #:installation-disk-image-file-system-type
411 "iso9660"))
412 (command (qemu-command/writable-image image)))
413 (run-basic-test %minimal-os-on-vda command name)))))
414
415\f
ae763b5b
LC
416;;;
417;;; Separate /home.
418;;;
419
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))
423
424 (operating-system
425 (host-name "liberigilo")
426 (timezone "Europe/Paris")
427 (locale "en_US.utf8")
428
fdfdecdb
TGR
429 (bootloader (bootloader-configuration
430 (bootloader grub-bootloader)
431 (target "/dev/vdb")))
ae763b5b
LC
432 (kernel-arguments '("console=ttyS0"))
433 (file-systems (cons* (file-system
9ceeca08 434 (device (file-system-label "my-root"))
ae763b5b
LC
435 (mount-point "/")
436 (type "ext4"))
437 (file-system
438 (device "none")
ae763b5b
LC
439 (mount-point "/home")
440 (type "tmpfs"))
441 %base-file-systems))
442 (users (cons* (user-account
443 (name "alice")
cf848cc0 444 (group "users"))
ae763b5b
LC
445 (user-account
446 (name "charlie")
cf848cc0 447 (group "users"))
ae763b5b
LC
448 %base-user-accounts))
449 (services (cons (service marionette-service-type
450 (marionette-configuration
451 (imported-modules '((gnu services herd)
452 (guix combinators)))))
453 %base-services))))
454
455(define %test-separate-home-os
456 (system-test
457 (name "separate-home-os")
458 (description
459 "Test basic functionality of an installed OS with a separate /home
460partition. In particular, home directories must be correctly created (see
461<https://bugs.gnu.org/21108>).")
462 (value
463 (mlet* %store-monad ((image (run-install %separate-home-os
464 %separate-home-os-source
465 #:script
466 %simple-installation-script))
467 (command (qemu-command/writable-image image)))
468 (run-basic-test %separate-home-os command "separate-home-os")))))
469
470\f
5479aa2b
LC
471;;;
472;;; Separate /gnu/store partition.
473;;;
474
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))
478
479 (operating-system
480 (host-name "liberigilo")
481 (timezone "Europe/Paris")
482 (locale "en_US.UTF-8")
483
fdfdecdb
TGR
484 (bootloader (bootloader-configuration
485 (bootloader grub-bootloader)
486 (target "/dev/vdb")))
5479aa2b
LC
487 (kernel-arguments '("console=ttyS0"))
488 (file-systems (cons* (file-system
9ceeca08 489 (device (file-system-label "root-fs"))
5479aa2b
LC
490 (mount-point "/")
491 (type "ext4"))
492 (file-system
9ceeca08 493 (device (file-system-label "store-fs"))
5479aa2b 494 (mount-point "/gnu")
38434419 495 (type "ext4"))
5479aa2b
LC
496 %base-file-systems))
497 (users %base-user-accounts)
498 (services (cons (service marionette-service-type
499 (marionette-configuration
500 (imported-modules '((gnu services herd)
501 (guix combinators)))))
502 %base-services))))
503
504(define %separate-store-installation-script
505 ;; Installation with a separate /gnu partition.
506 "\
507. /etc/profile
508set -e -x
509guix --version
510
511export GUIX_BUILD_OPTIONS=--no-grafts
512guix build isc-dhcp
513parted --script /dev/vdb mklabel gpt \\
514 mkpart primary ext2 1M 3M \\
307ec732
LC
515 mkpart primary ext2 3M 400M \\
516 mkpart primary ext2 400M 2.1G \\
5479aa2b
LC
517 set 1 boot on \\
518 set 1 bios_grub on
519mkfs.ext4 -L root-fs /dev/vdb2
520mkfs.ext4 -L store-fs /dev/vdb3
521mount /dev/vdb2 /mnt
522mkdir /mnt/gnu
523mount /dev/vdb3 /mnt/gnu
524df -h /mnt
307ec732 525df -h /mnt/gnu
5479aa2b
LC
526herd start cow-store /mnt
527mkdir /mnt/etc
528cp /etc/target-config.scm /mnt/etc/config.scm
529guix system init /mnt/etc/config.scm /mnt --no-substitutes
530sync
531reboot\n")
532
533(define %test-separate-store-os
534 (system-test
535 (name "separate-store-os")
536 (description
537 "Test basic functionality of an OS installed like one would do by hand,
538where /gnu lives on a separate partition.")
539 (value
540 (mlet* %store-monad ((image (run-install %separate-store-os
541 %separate-store-os-source
542 #:script
543 %separate-store-installation-script))
544 (command (qemu-command/writable-image image)))
545 (run-basic-test %separate-store-os command "separate-store-os")))))
546
547\f
245cc5f5
LC
548;;;
549;;; RAID root device.
550;;;
551
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))
555
556 (operating-system
557 (host-name "raidified")
558 (timezone "Europe/Paris")
559 (locale "en_US.utf8")
560
fdfdecdb
TGR
561 (bootloader (bootloader-configuration
562 (bootloader grub-bootloader)
563 (target "/dev/vdb")))
245cc5f5 564 (kernel-arguments '("console=ttyS0"))
bc499b11 565
3adf320e
LC
566 ;; Add a kernel module for RAID-1 (aka. "mirror").
567 (initrd-modules (cons "raid1" %base-initrd-modules))
bc499b11 568
245cc5f5
LC
569 (mapped-devices (list (mapped-device
570 (source (list "/dev/vda2" "/dev/vda3"))
571 (target "/dev/md0")
572 (type raid-device-mapping))))
573 (file-systems (cons (file-system
9ceeca08 574 (device (file-system-label "root-fs"))
245cc5f5
LC
575 (mount-point "/")
576 (type "ext4")
577 (dependencies mapped-devices))
578 %base-file-systems))
579 (users %base-user-accounts)
580 (services (cons (service marionette-service-type
581 (marionette-configuration
582 (imported-modules '((gnu services herd)
583 (guix combinators)))))
584 %base-services))))
585
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
589 ;; mdadm.
590 "\
591. /etc/profile
592set -e -x
593guix --version
594
595export GUIX_BUILD_OPTIONS=--no-grafts
596parted --script /dev/vdb mklabel gpt \\
597 mkpart primary ext2 1M 3M \\
3adf320e
LC
598 mkpart primary ext2 3M 1.4G \\
599 mkpart primary ext2 1.4G 2.8G \\
245cc5f5
LC
600 set 1 boot on \\
601 set 1 bios_grub on
3adf320e 602yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
245cc5f5
LC
603 /dev/vdb2 /dev/vdb3
604mkfs.ext4 -L root-fs /dev/md0
605mount /dev/md0 /mnt
606df -h /mnt
607herd start cow-store /mnt
608mkdir /mnt/etc
609cp /etc/target-config.scm /mnt/etc/config.scm
610guix system init /mnt/etc/config.scm /mnt --no-substitutes
611sync
612reboot\n")
613
614(define %test-raid-root-os
615 (system-test
616 (name "raid-root-os")
617 (description
618 "Test functionality of an OS installed with a RAID root partition managed
619by 'mdadm'.")
620 (value
621 (mlet* %store-monad ((image (run-install %raid-root-os
622 %raid-root-os-source
623 #:script
624 %raid-root-installation-script
3adf320e 625 #:target-size (* 2800 MiB)))
245cc5f5
LC
626 (command (qemu-command/writable-image image)))
627 (run-basic-test %raid-root-os
628 `(,@command) "raid-root-os")))))
629
630\f
5479aa2b
LC
631;;;
632;;; LUKS-encrypted root file system.
633;;;
634
b1bf155f
LC
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))
638
639 (operating-system
640 (host-name "liberigilo")
641 (timezone "Europe/Paris")
642 (locale "en_US.UTF-8")
643
fdfdecdb
TGR
644 (bootloader (bootloader-configuration
645 (bootloader grub-bootloader)
646 (target "/dev/vdb")))
f7f292d3
LC
647
648 ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
649 ;; detection logic in 'enter-luks-passphrase'.
650
651 (mapped-devices (list (mapped-device
652 (source (uuid "12345678-1234-1234-1234-123456789abc"))
653 (target "the-root-device")
654 (type luks-device-mapping))))
b1bf155f
LC
655 (file-systems (cons (file-system
656 (device "/dev/mapper/the-root-device")
b1bf155f
LC
657 (mount-point "/")
658 (type "ext4"))
659 %base-file-systems))
b1bf155f
LC
660 (users (cons (user-account
661 (name "charlie")
662 (group "users")
b1bf155f
LC
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)))))
669 %base-services))))
670
43e282ac
LC
671(define %luks-passphrase
672 ;; LUKS encryption passphrase used in tests.
673 "thepassphrase")
674
b1bf155f
LC
675(define %encrypted-root-installation-script
676 ;; Shell script of a simple installation.
43e282ac 677 (string-append "\
94b4274d 678. /etc/profile
b1bf155f 679set -e -x
94b4274d 680guix --version
94b4274d
LC
681
682export GUIX_BUILD_OPTIONS=--no-grafts
b1bf155f 683ls -l /run/current-system/gc-roots
94b4274d
LC
684parted --script /dev/vdb mklabel gpt \\
685 mkpart primary ext2 1M 3M \\
8dfb0c96 686 mkpart primary ext2 3M 1.4G \\
94b4274d
LC
687 set 1 boot on \\
688 set 1 bios_grub on
43e282ac 689echo -n " %luks-passphrase " | \\
f7f292d3 690 cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
43e282ac 691echo -n " %luks-passphrase " | \\
b1bf155f
LC
692 cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
693mkfs.ext4 -L my-root /dev/mapper/the-root-device
694mount LABEL=my-root /mnt
94b4274d
LC
695herd start cow-store /mnt
696mkdir /mnt/etc
b1bf155f 697cp /etc/target-config.scm /mnt/etc/config.scm
b1bf155f 698guix system build /mnt/etc/config.scm
94b4274d
LC
699guix system init /mnt/etc/config.scm /mnt --no-substitutes
700sync
43e282ac 701reboot\n"))
94b4274d 702
f7f292d3
LC
703(define (enter-luks-passphrase marionette)
704 "Return a gexp to be inserted in the basic system test running on MARIONETTE
705to enter the LUKS passphrase."
706 (let ((ocrad (file-append ocrad "/bin/ocrad")))
707 #~(begin
708 (define (passphrase-prompt? text)
709 (string-contains (pk 'screen-text text) "Enter pass"))
710
711 (define (bios-boot-screen? text)
712 ;; Return true if TEXT corresponds to the boot screen, before GRUB's
713 ;; menu.
714 (string-prefix? "SeaBIOS" text))
715
716 (test-assert "enter LUKS passphrase for GRUB"
717 (begin
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?
721 #:ocrad #$ocrad)
43e282ac
LC
722 (marionette-type #$(string-append %luks-passphrase "\n")
723 #$marionette)
f7f292d3
LC
724
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?)
729 #:ocrad #$ocrad
730 #:timeout 20)))
731
732 (test-assert "enter LUKS passphrase for the initrd"
733 (begin
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?
737 #:ocrad #$ocrad
738 #:timeout 60)
43e282ac
LC
739 (marionette-type #$(string-append %luks-passphrase "\n")
740 #$marionette)
f7f292d3
LC
741
742 ;; Take a screenshot for debugging purposes.
743 (marionette-control (string-append "screendump " #$output
744 "/post-initrd-passphrase.ppm")
745 #$marionette))))))
746
4f83afd2 747(define %test-encrypted-root-os
98b65b5f 748 (system-test
b1bf155f 749 (name "encrypted-root-os")
98b65b5f
LC
750 (description
751 "Test basic functionality of an OS installed like one would do by hand.
752This test is expensive in terms of CPU and storage usage since we need to
753build (current-guix) and then store a couple of full system images.")
754 (value
b1bf155f
LC
755 (mlet* %store-monad ((image (run-install %encrypted-root-os
756 %encrypted-root-os-source
757 #:script
758 %encrypted-root-installation-script))
759 (command (qemu-command/writable-image image)))
f7f292d3
LC
760 (run-basic-test %encrypted-root-os command "encrypted-root-os"
761 #:initialization enter-luks-passphrase)))))
94b4274d 762
b1a505ba
DC
763\f
764;;;
765;;; Btrfs root file system.
766;;;
767
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))
771
772 (operating-system
773 (host-name "liberigilo")
774 (timezone "Europe/Paris")
775 (locale "en_US.UTF-8")
776
fdfdecdb
TGR
777 (bootloader (bootloader-configuration
778 (bootloader grub-bootloader)
779 (target "/dev/vdb")))
b1a505ba
DC
780 (kernel-arguments '("console=ttyS0"))
781 (file-systems (cons (file-system
9ceeca08 782 (device (file-system-label "my-root"))
b1a505ba
DC
783 (mount-point "/")
784 (type "btrfs"))
785 %base-file-systems))
786 (users (cons (user-account
787 (name "charlie")
788 (group "users")
b1a505ba
DC
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)))))
795 %base-services))))
796
797(define %btrfs-root-installation-script
798 ;; Shell script of a simple installation.
799 "\
800. /etc/profile
801set -e -x
802guix --version
803
804export GUIX_BUILD_OPTIONS=--no-grafts
805ls -l /run/current-system/gc-roots
806parted --script /dev/vdb mklabel gpt \\
807 mkpart primary ext2 1M 3M \\
5724a14e 808 mkpart primary ext2 3M 2G \\
b1a505ba
DC
809 set 1 boot on \\
810 set 1 bios_grub on
811mkfs.btrfs -L my-root /dev/vdb2
812mount /dev/vdb2 /mnt
813btrfs subvolume create /mnt/home
814herd start cow-store /mnt
815mkdir /mnt/etc
816cp /etc/target-config.scm /mnt/etc/config.scm
817guix system build /mnt/etc/config.scm
818guix system init /mnt/etc/config.scm /mnt --no-substitutes
819sync
820reboot\n")
821
822(define %test-btrfs-root-os
823 (system-test
824 (name "btrfs-root-os")
825 (description
826 "Test basic functionality of an OS installed like one would do by hand.
827This test is expensive in terms of CPU and storage usage since we need to
828build (current-guix) and then store a couple of full system images.")
829 (value
830 (mlet* %store-monad ((image (run-install %btrfs-root-os
831 %btrfs-root-os-source
832 #:script
833 %btrfs-root-installation-script))
834 (command (qemu-command/writable-image image)))
835 (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
836
4f51fdba
TGR
837\f
838;;;
839;;; JFS root file system.
840;;;
841
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))
845
846 (operating-system
847 (host-name "liberigilo")
848 (timezone "Europe/Paris")
849 (locale "en_US.UTF-8")
850
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"))
857 (mount-point "/")
858 (type "jfs"))
859 %base-file-systems))
860 (users (cons (user-account
861 (name "charlie")
862 (group "users")
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)))))
869 %base-services))))
870
871(define %jfs-root-installation-script
872 ;; Shell script of a simple installation.
873 "\
874. /etc/profile
875set -e -x
876guix --version
877
878export GUIX_BUILD_OPTIONS=--no-grafts
879ls -l /run/current-system/gc-roots
880parted --script /dev/vdb mklabel gpt \\
881 mkpart primary ext2 1M 3M \\
882 mkpart primary ext2 3M 2G \\
883 set 1 boot on \\
884 set 1 bios_grub on
885jfs_mkfs -L my-root -q /dev/vdb2
886mount /dev/vdb2 /mnt
887herd start cow-store /mnt
888mkdir /mnt/etc
889cp /etc/target-config.scm /mnt/etc/config.scm
890guix system build /mnt/etc/config.scm
891guix system init /mnt/etc/config.scm /mnt --no-substitutes
892sync
893reboot\n")
894
895(define %test-jfs-root-os
896 (system-test
897 (name "jfs-root-os")
898 (description
899 "Test basic functionality of an OS installed like one would do by hand.
900This test is expensive in terms of CPU and storage usage since we need to
901build (current-guix) and then store a couple of full system images.")
902 (value
903 (mlet* %store-monad ((image (run-install %jfs-root-os
904 %jfs-root-os-source
905 #:script
906 %jfs-root-installation-script))
907 (command (qemu-command/writable-image image)))
908 (run-basic-test %jfs-root-os command "jfs-root-os")))))
909
ccb1a8c4
LC
910\f
911;;;
912;;; Installation through the graphical interface.
913;;;
914
915(define %syslog-conf
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"
919 #~(begin
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)
924 #t))))
925
926(define (operating-system-with-console-syslog os)
927 "Return OS with a syslog service that writes to /dev/console."
928 (operating-system
929 (inherit os)
930 (services (modify-services (operating-system-user-services os)
931 (syslog-service-type config
932 =>
933 (syslog-configuration
934 (inherit config)
935 (config-file %syslog-conf)))))))
936
937(define %root-password "foo")
938
939(define* (gui-test-program marionette #:key (encrypted? #f))
940 #~(let ()
941 (define (screenshot file)
942 (marionette-control (string-append "screendump " file)
943 #$marionette))
944
945 (setvbuf (current-output-port) 'none)
946 (setvbuf (current-error-port) 'none)
947
948 (marionette-eval '(use-modules (gnu installer tests))
949 #$marionette)
950
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))
955 #$marionette)
956
957 ;; Tell the installer to not wait for the Connman "online" status.
958 (marionette-eval '(call-with-output-file "/tmp/installer-assume-online"
959 (const #t))
960 #$marionette)
961
962 ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
963 ;; network access.
964 (marionette-eval '(call-with-output-file
965 "/tmp/installer-system-init-options"
966 (lambda (port)
967 (write '("--no-grafts" "--no-substitutes")
968 port)))
969 #$marionette)
970
971 (marionette-eval '(define installer-socket
972 (open-installer-socket))
973 #$marionette)
974 (screenshot "installer-start.ppm")
975
976 (marionette-eval '(choose-locale+keyboard installer-socket)
977 #$marionette)
978 (screenshot "installer-locale.ppm")
979
980 ;; Choose the host name that the "basic" test expects.
981 (marionette-eval '(enter-host-name+passwords installer-socket
982 #:host-name "liberigilo"
983 #:root-password
984 #$%root-password
985 #:users
986 '(("alice" "pass1")
987 ("bob" "pass2")))
988 #$marionette)
989 (screenshot "installer-services.ppm")
990
991 (marionette-eval '(choose-services installer-socket
992 #:desktop-environments '()
993 #:choose-network-service?
994 (const #f))
995 #$marionette)
996 (screenshot "installer-partitioning.ppm")
997
998 (marionette-eval '(choose-partitioning installer-socket
999 #:encrypted? #$encrypted?
1000 #:passphrase #$%luks-passphrase)
1001 #$marionette)
1002 (screenshot "installer-run.ppm")
1003
1004 (marionette-eval '(conclude-installation installer-socket)
1005 #$marionette)
1006
1007 (sync)
1008 #t))
1009
1010(define %extra-packages
1011 ;; Packages needed when installing with an encrypted root.
1012 (list isc-dhcp
1013 lvm2-static cryptsetup-static e2fsck/static
1014 loadkeys-static))
1015
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
1021 (operating-system
1022 (inherit (operating-system-with-console-syslog
1023 (operating-system-add-packages
1024 (operating-system-with-current-guix
1025 installation-os)
1026 %extra-packages)))
1027 (kernel-arguments '("console=ttyS0")))
1028 #:imported-modules '((gnu services herd)
1029 (gnu installer tests)
1030 (guix combinators))))
1031
1032(define* (guided-installation-test name #:key encrypted?)
1033 (define os
1034 (operating-system
1035 (inherit %minimal-os)
1036 (users (append (list (user-account
1037 (name "alice")
1038 (comment "Bob's sister")
1039 (group "users")
1040 (supplementary-groups
1041 '("wheel" "audio" "video")))
1042 (user-account
1043 (name "bob")
1044 (comment "Alice's brother")
1045 (group "users")
1046 (supplementary-groups
1047 '("wheel" "audio" "video"))))
1048 %base-user-accounts))
e666a923
MO
1049 ;; The installer does not create a swap device in guided mode with
1050 ;; encryption support.
1051 (swap-devices (if encrypted? '() '("/dev/vdb2")))
ccb1a8c4
LC
1052 (services (cons (service dhcp-client-service-type)
1053 (operating-system-user-services %minimal-os)))))
1054
1055 (system-test
1056 (name name)
1057 (description
1058 "Install an OS using the graphical installer and test it.")
1059 (value
1060 (mlet* %store-monad ((image (run-install os '(this is unused)
1061 #:script #f
1062 #:os installation-os-for-gui-tests
1063 #:gui-test
1064 (lambda (marionette)
1065 (gui-test-program
1066 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)))))
1072
1073(define %test-gui-installed-os
1074 (guided-installation-test "gui-installed-os"
1075 #:encrypted? #f))
1076
e666a923
MO
1077(define %test-gui-installed-os-encrypted
1078 (guided-installation-test "gui-installed-os-encrypted"
1079 #:encrypted? #t))
ccb1a8c4 1080
94b4274d 1081;;; install.scm ends here