install.scm 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr>
  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. (define-module (gnu tests install)
  20. #:use-module (gnu)
  21. #:use-module (gnu bootloader extlinux)
  22. #:use-module (gnu tests)
  23. #:use-module (gnu tests base)
  24. #:use-module (gnu system)
  25. #:use-module (gnu system install)
  26. #:use-module (gnu system vm)
  27. #:use-module ((gnu build vm) #:select (qemu-command))
  28. #:use-module (gnu packages bootloaders)
  29. #:use-module (gnu packages ocr)
  30. #:use-module (gnu packages package-management)
  31. #:use-module (gnu packages virtualization)
  32. #:use-module (guix store)
  33. #:use-module (guix monads)
  34. #:use-module (guix packages)
  35. #:use-module (guix grafts)
  36. #:use-module (guix gexp)
  37. #:use-module (guix utils)
  38. #:export (%test-installed-os
  39. %test-installed-extlinux-os
  40. %test-iso-image-installer
  41. %test-separate-store-os
  42. %test-separate-home-os
  43. %test-raid-root-os
  44. %test-encrypted-root-os
  45. %test-btrfs-root-os))
  46. ;;; Commentary:
  47. ;;;
  48. ;;; Test the installation of Guix using the documented approach at the
  49. ;;; command line.
  50. ;;;
  51. ;;; Code:
  52. (define-os-with-source (%minimal-os %minimal-os-source)
  53. ;; The OS we want to install.
  54. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  55. (operating-system
  56. (host-name "liberigilo")
  57. (timezone "Europe/Paris")
  58. (locale "en_US.UTF-8")
  59. (bootloader (bootloader-configuration
  60. (bootloader grub-bootloader)
  61. (target "/dev/vdb")))
  62. (kernel-arguments '("console=ttyS0"))
  63. (file-systems (cons (file-system
  64. (device (file-system-label "my-root"))
  65. (mount-point "/")
  66. (type "ext4"))
  67. %base-file-systems))
  68. (users (cons (user-account
  69. (name "alice")
  70. (comment "Bob's sister")
  71. (group "users")
  72. (supplementary-groups '("wheel" "audio" "video")))
  73. %base-user-accounts))
  74. (services (cons (service marionette-service-type
  75. (marionette-configuration
  76. (imported-modules '((gnu services herd)
  77. (guix build utils)
  78. (guix combinators)))))
  79. %base-services))))
  80. (define (operating-system-add-packages os packages)
  81. "Append PACKAGES to OS packages list."
  82. (operating-system
  83. (inherit os)
  84. (packages (append packages (operating-system-packages os)))))
  85. (define-os-with-source (%minimal-extlinux-os
  86. %minimal-extlinux-os-source)
  87. (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
  88. (srfi srfi-1))
  89. (operating-system
  90. (host-name "liberigilo")
  91. (timezone "Europe/Paris")
  92. (locale "en_US.UTF-8")
  93. (bootloader (bootloader-configuration
  94. (bootloader extlinux-bootloader-gpt)
  95. (target "/dev/vdb")))
  96. (kernel-arguments '("console=ttyS0"))
  97. (file-systems (cons (file-system
  98. (device (file-system-label "my-root"))
  99. (mount-point "/")
  100. (type "ext4"))
  101. %base-file-systems))
  102. (services (cons (service marionette-service-type
  103. (marionette-configuration
  104. (imported-modules '((gnu services herd)
  105. (guix combinators)))))
  106. %base-services))))
  107. (define (operating-system-with-current-guix os)
  108. "Return a variant of OS that uses the current Guix."
  109. (operating-system
  110. (inherit os)
  111. (services (modify-services (operating-system-user-services os)
  112. (guix-service-type config =>
  113. (guix-configuration
  114. (inherit config)
  115. (guix (current-guix))))))))
  116. (define MiB (expt 2 20))
  117. (define %simple-installation-script
  118. ;; Shell script of a simple installation.
  119. "\
  120. . /etc/profile
  121. set -e -x
  122. guix --version
  123. export GUIX_BUILD_OPTIONS=--no-grafts
  124. guix build isc-dhcp
  125. parted --script /dev/vdb mklabel gpt \\
  126. mkpart primary ext2 1M 3M \\
  127. mkpart primary ext2 3M 1.4G \\
  128. set 1 boot on \\
  129. set 1 bios_grub on
  130. mkfs.ext4 -L my-root /dev/vdb2
  131. mount /dev/vdb2 /mnt
  132. df -h /mnt
  133. herd start cow-store /mnt
  134. mkdir /mnt/etc
  135. cp /etc/target-config.scm /mnt/etc/config.scm
  136. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  137. sync
  138. reboot\n")
  139. (define %extlinux-gpt-installation-script
  140. ;; Shell script of a simple installation.
  141. ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
  142. ;; we make sure to pass -O '^64bit' to mkfs.
  143. "\
  144. . /etc/profile
  145. set -e -x
  146. guix --version
  147. export GUIX_BUILD_OPTIONS=--no-grafts
  148. guix build isc-dhcp
  149. parted --script /dev/vdb mklabel gpt \\
  150. mkpart ext2 1M 1.4G \\
  151. set 1 legacy_boot on
  152. mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
  153. mount /dev/vdb1 /mnt
  154. df -h /mnt
  155. herd start cow-store /mnt
  156. mkdir /mnt/etc
  157. cp /etc/target-config.scm /mnt/etc/config.scm
  158. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  159. sync
  160. reboot\n")
  161. (define* (run-install target-os target-os-source
  162. #:key
  163. (script %simple-installation-script)
  164. (packages '())
  165. (os (marionette-operating-system
  166. (operating-system
  167. ;; Since the image has no network access, use the
  168. ;; current Guix so the store items we need are in
  169. ;; the image and add packages provided.
  170. (inherit (operating-system-add-packages
  171. (operating-system-with-current-guix
  172. installation-os)
  173. packages))
  174. (kernel-arguments '("console=ttyS0")))
  175. #:imported-modules '((gnu services herd)
  176. (guix combinators))))
  177. (installation-disk-image-file-system-type "ext4")
  178. (target-size (* 2200 MiB)))
  179. "Run SCRIPT (a shell script following the system installation procedure) in
  180. OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
  181. the installed system. The packages specified in PACKAGES will be appended to
  182. packages defined in installation-os."
  183. (mlet* %store-monad ((_ (set-grafting #f))
  184. (system (current-system))
  185. (target (operating-system-derivation target-os))
  186. ;; Since the installation system has no network access,
  187. ;; we cheat a little bit by adding TARGET to its GC
  188. ;; roots. This way, we know 'guix system init' will
  189. ;; succeed.
  190. (image (system-disk-image
  191. (operating-system-with-gc-roots
  192. os (list target))
  193. #:disk-image-size 'guess
  194. #:file-system-type
  195. installation-disk-image-file-system-type)))
  196. (define install
  197. (with-imported-modules '((guix build utils)
  198. (gnu build marionette))
  199. #~(begin
  200. (use-modules (guix build utils)
  201. (gnu build marionette))
  202. (set-path-environment-variable "PATH" '("bin")
  203. (list #$qemu-minimal))
  204. (system* "qemu-img" "create" "-f" "qcow2"
  205. #$output #$(number->string target-size))
  206. (define marionette
  207. (make-marionette
  208. `(,(which #$(qemu-command system))
  209. "-no-reboot"
  210. "-m" "800"
  211. #$@(cond
  212. ((string=? "ext4" installation-disk-image-file-system-type)
  213. #~("-drive"
  214. ,(string-append "file=" #$image
  215. ",if=virtio,readonly")))
  216. ((string=? "iso9660" installation-disk-image-file-system-type)
  217. #~("-cdrom" #$image))
  218. (else
  219. (error
  220. "unsupported installation-disk-image-file-system-type:"
  221. installation-disk-image-file-system-type)))
  222. "-drive"
  223. ,(string-append "file=" #$output ",if=virtio")
  224. ,@(if (file-exists? "/dev/kvm")
  225. '("-enable-kvm")
  226. '()))))
  227. (pk 'uname (marionette-eval '(uname) marionette))
  228. ;; Wait for tty1.
  229. (marionette-eval '(begin
  230. (use-modules (gnu services herd))
  231. (start 'term-tty1))
  232. marionette)
  233. (marionette-eval '(call-with-output-file "/etc/target-config.scm"
  234. (lambda (port)
  235. (write '#$target-os-source port)))
  236. marionette)
  237. (exit (marionette-eval '(zero? (system #$script))
  238. marionette)))))
  239. (gexp->derivation "installation" install)))
  240. (define* (qemu-command/writable-image image #:key (memory-size 256))
  241. "Return as a monadic value the command to run QEMU on a writable copy of
  242. IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
  243. (mlet %store-monad ((system (current-system)))
  244. (return #~(let ((image #$image))
  245. ;; First we need a writable copy of the image.
  246. (format #t "creating writable image from '~a'...~%" image)
  247. (unless (zero? (system* #+(file-append qemu-minimal
  248. "/bin/qemu-img")
  249. "create" "-f" "qcow2"
  250. "-o"
  251. (string-append "backing_file=" image)
  252. "disk.img"))
  253. (error "failed to create writable QEMU image" image))
  254. (chmod "disk.img" #o644)
  255. `(,(string-append #$qemu-minimal "/bin/"
  256. #$(qemu-command system))
  257. ,@(if (file-exists? "/dev/kvm")
  258. '("-enable-kvm")
  259. '())
  260. "-no-reboot" "-m" #$(number->string memory-size)
  261. "-drive" "file=disk.img,if=virtio")))))
  262. (define %test-installed-os
  263. (system-test
  264. (name "installed-os")
  265. (description
  266. "Test basic functionality of an OS installed like one would do by hand.
  267. This test is expensive in terms of CPU and storage usage since we need to
  268. build (current-guix) and then store a couple of full system images.")
  269. (value
  270. (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
  271. (command (qemu-command/writable-image image)))
  272. (run-basic-test %minimal-os command
  273. "installed-os")))))
  274. (define %test-installed-extlinux-os
  275. (system-test
  276. (name "installed-extlinux-os")
  277. (description
  278. "Test basic functionality of an OS booted with an extlinux bootloader. As
  279. per %test-installed-os, this test is expensive in terms of CPU and storage.")
  280. (value
  281. (mlet* %store-monad ((image (run-install %minimal-extlinux-os
  282. %minimal-extlinux-os-source
  283. #:packages
  284. (list syslinux)
  285. #:script
  286. %extlinux-gpt-installation-script))
  287. (command (qemu-command/writable-image image)))
  288. (run-basic-test %minimal-extlinux-os command
  289. "installed-extlinux-os")))))
  290. ;;;
  291. ;;; Installation through an ISO image.
  292. ;;;
  293. (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-source)
  294. ;; The OS we want to install.
  295. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  296. (operating-system
  297. (host-name "liberigilo")
  298. (timezone "Europe/Paris")
  299. (locale "en_US.UTF-8")
  300. (bootloader (bootloader-configuration
  301. (bootloader grub-bootloader)
  302. (target "/dev/vda")))
  303. (kernel-arguments '("console=ttyS0"))
  304. (file-systems (cons (file-system
  305. (device (file-system-label "my-root"))
  306. (mount-point "/")
  307. (type "ext4"))
  308. %base-file-systems))
  309. (users (cons (user-account
  310. (name "alice")
  311. (comment "Bob's sister")
  312. (group "users")
  313. (supplementary-groups '("wheel" "audio" "video")))
  314. %base-user-accounts))
  315. (services (cons (service marionette-service-type
  316. (marionette-configuration
  317. (imported-modules '((gnu services herd)
  318. (guix combinators)))))
  319. %base-services))))
  320. (define %simple-installation-script-for-/dev/vda
  321. ;; Shell script of a simple installation.
  322. "\
  323. . /etc/profile
  324. set -e -x
  325. guix --version
  326. export GUIX_BUILD_OPTIONS=--no-grafts
  327. guix build isc-dhcp
  328. parted --script /dev/vda mklabel gpt \\
  329. mkpart primary ext2 1M 3M \\
  330. mkpart primary ext2 3M 1.4G \\
  331. set 1 boot on \\
  332. set 1 bios_grub on
  333. mkfs.ext4 -L my-root /dev/vda2
  334. mount /dev/vda2 /mnt
  335. df -h /mnt
  336. herd start cow-store /mnt
  337. mkdir /mnt/etc
  338. cp /etc/target-config.scm /mnt/etc/config.scm
  339. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  340. sync
  341. reboot\n")
  342. (define %test-iso-image-installer
  343. (system-test
  344. (name "iso-image-installer")
  345. (description
  346. "")
  347. (value
  348. (mlet* %store-monad ((image (run-install
  349. %minimal-os-on-vda
  350. %minimal-os-on-vda-source
  351. #:script
  352. %simple-installation-script-for-/dev/vda
  353. #:installation-disk-image-file-system-type
  354. "iso9660"))
  355. (command (qemu-command/writable-image image)))
  356. (run-basic-test %minimal-os-on-vda command name)))))
  357. ;;;
  358. ;;; Separate /home.
  359. ;;;
  360. (define-os-with-source (%separate-home-os %separate-home-os-source)
  361. ;; The OS we want to install.
  362. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  363. (operating-system
  364. (host-name "liberigilo")
  365. (timezone "Europe/Paris")
  366. (locale "en_US.utf8")
  367. (bootloader (bootloader-configuration
  368. (bootloader grub-bootloader)
  369. (target "/dev/vdb")))
  370. (kernel-arguments '("console=ttyS0"))
  371. (file-systems (cons* (file-system
  372. (device (file-system-label "my-root"))
  373. (mount-point "/")
  374. (type "ext4"))
  375. (file-system
  376. (device "none")
  377. (mount-point "/home")
  378. (type "tmpfs"))
  379. %base-file-systems))
  380. (users (cons* (user-account
  381. (name "alice")
  382. (group "users"))
  383. (user-account
  384. (name "charlie")
  385. (group "users"))
  386. %base-user-accounts))
  387. (services (cons (service marionette-service-type
  388. (marionette-configuration
  389. (imported-modules '((gnu services herd)
  390. (guix combinators)))))
  391. %base-services))))
  392. (define %test-separate-home-os
  393. (system-test
  394. (name "separate-home-os")
  395. (description
  396. "Test basic functionality of an installed OS with a separate /home
  397. partition. In particular, home directories must be correctly created (see
  398. <https://bugs.gnu.org/21108>).")
  399. (value
  400. (mlet* %store-monad ((image (run-install %separate-home-os
  401. %separate-home-os-source
  402. #:script
  403. %simple-installation-script))
  404. (command (qemu-command/writable-image image)))
  405. (run-basic-test %separate-home-os command "separate-home-os")))))
  406. ;;;
  407. ;;; Separate /gnu/store partition.
  408. ;;;
  409. (define-os-with-source (%separate-store-os %separate-store-os-source)
  410. ;; The OS we want to install.
  411. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  412. (operating-system
  413. (host-name "liberigilo")
  414. (timezone "Europe/Paris")
  415. (locale "en_US.UTF-8")
  416. (bootloader (bootloader-configuration
  417. (bootloader grub-bootloader)
  418. (target "/dev/vdb")))
  419. (kernel-arguments '("console=ttyS0"))
  420. (file-systems (cons* (file-system
  421. (device (file-system-label "root-fs"))
  422. (mount-point "/")
  423. (type "ext4"))
  424. (file-system
  425. (device (file-system-label "store-fs"))
  426. (mount-point "/gnu")
  427. (type "ext4"))
  428. %base-file-systems))
  429. (users %base-user-accounts)
  430. (services (cons (service marionette-service-type
  431. (marionette-configuration
  432. (imported-modules '((gnu services herd)
  433. (guix combinators)))))
  434. %base-services))))
  435. (define %separate-store-installation-script
  436. ;; Installation with a separate /gnu partition.
  437. "\
  438. . /etc/profile
  439. set -e -x
  440. guix --version
  441. export GUIX_BUILD_OPTIONS=--no-grafts
  442. guix build isc-dhcp
  443. parted --script /dev/vdb mklabel gpt \\
  444. mkpart primary ext2 1M 3M \\
  445. mkpart primary ext2 3M 400M \\
  446. mkpart primary ext2 400M 2.1G \\
  447. set 1 boot on \\
  448. set 1 bios_grub on
  449. mkfs.ext4 -L root-fs /dev/vdb2
  450. mkfs.ext4 -L store-fs /dev/vdb3
  451. mount /dev/vdb2 /mnt
  452. mkdir /mnt/gnu
  453. mount /dev/vdb3 /mnt/gnu
  454. df -h /mnt
  455. df -h /mnt/gnu
  456. herd start cow-store /mnt
  457. mkdir /mnt/etc
  458. cp /etc/target-config.scm /mnt/etc/config.scm
  459. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  460. sync
  461. reboot\n")
  462. (define %test-separate-store-os
  463. (system-test
  464. (name "separate-store-os")
  465. (description
  466. "Test basic functionality of an OS installed like one would do by hand,
  467. where /gnu lives on a separate partition.")
  468. (value
  469. (mlet* %store-monad ((image (run-install %separate-store-os
  470. %separate-store-os-source
  471. #:script
  472. %separate-store-installation-script))
  473. (command (qemu-command/writable-image image)))
  474. (run-basic-test %separate-store-os command "separate-store-os")))))
  475. ;;;
  476. ;;; RAID root device.
  477. ;;;
  478. (define-os-with-source (%raid-root-os %raid-root-os-source)
  479. ;; An OS whose root partition is a RAID partition.
  480. (use-modules (gnu) (gnu tests))
  481. (operating-system
  482. (host-name "raidified")
  483. (timezone "Europe/Paris")
  484. (locale "en_US.utf8")
  485. (bootloader (bootloader-configuration
  486. (bootloader grub-bootloader)
  487. (target "/dev/vdb")))
  488. (kernel-arguments '("console=ttyS0"))
  489. ;; Add a kernel module for RAID-0 (aka. "stripe").
  490. (initrd-modules (cons "raid0" %base-initrd-modules))
  491. (mapped-devices (list (mapped-device
  492. (source (list "/dev/vda2" "/dev/vda3"))
  493. (target "/dev/md0")
  494. (type raid-device-mapping))))
  495. (file-systems (cons (file-system
  496. (device (file-system-label "root-fs"))
  497. (mount-point "/")
  498. (type "ext4")
  499. (dependencies mapped-devices))
  500. %base-file-systems))
  501. (users %base-user-accounts)
  502. (services (cons (service marionette-service-type
  503. (marionette-configuration
  504. (imported-modules '((gnu services herd)
  505. (guix combinators)))))
  506. %base-services))))
  507. (define %raid-root-installation-script
  508. ;; Installation with a separate /gnu partition. See
  509. ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
  510. ;; mdadm.
  511. "\
  512. . /etc/profile
  513. set -e -x
  514. guix --version
  515. export GUIX_BUILD_OPTIONS=--no-grafts
  516. parted --script /dev/vdb mklabel gpt \\
  517. mkpart primary ext2 1M 3M \\
  518. mkpart primary ext2 3M 600M \\
  519. mkpart primary ext2 600M 1200M \\
  520. set 1 boot on \\
  521. set 1 bios_grub on
  522. mdadm --create /dev/md0 --verbose --level=stripe --raid-devices=2 \\
  523. /dev/vdb2 /dev/vdb3
  524. mkfs.ext4 -L root-fs /dev/md0
  525. mount /dev/md0 /mnt
  526. df -h /mnt
  527. herd start cow-store /mnt
  528. mkdir /mnt/etc
  529. cp /etc/target-config.scm /mnt/etc/config.scm
  530. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  531. sync
  532. reboot\n")
  533. (define %test-raid-root-os
  534. (system-test
  535. (name "raid-root-os")
  536. (description
  537. "Test functionality of an OS installed with a RAID root partition managed
  538. by 'mdadm'.")
  539. (value
  540. (mlet* %store-monad ((image (run-install %raid-root-os
  541. %raid-root-os-source
  542. #:script
  543. %raid-root-installation-script
  544. #:target-size (* 1300 MiB)))
  545. (command (qemu-command/writable-image image)))
  546. (run-basic-test %raid-root-os
  547. `(,@command) "raid-root-os")))))
  548. ;;;
  549. ;;; LUKS-encrypted root file system.
  550. ;;;
  551. (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
  552. ;; The OS we want to install.
  553. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  554. (operating-system
  555. (host-name "liberigilo")
  556. (timezone "Europe/Paris")
  557. (locale "en_US.UTF-8")
  558. (bootloader (bootloader-configuration
  559. (bootloader grub-bootloader)
  560. (target "/dev/vdb")))
  561. ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
  562. ;; detection logic in 'enter-luks-passphrase'.
  563. (mapped-devices (list (mapped-device
  564. (source (uuid "12345678-1234-1234-1234-123456789abc"))
  565. (target "the-root-device")
  566. (type luks-device-mapping))))
  567. (file-systems (cons (file-system
  568. (device "/dev/mapper/the-root-device")
  569. (mount-point "/")
  570. (type "ext4"))
  571. %base-file-systems))
  572. (users (cons (user-account
  573. (name "charlie")
  574. (group "users")
  575. (supplementary-groups '("wheel" "audio" "video")))
  576. %base-user-accounts))
  577. (services (cons (service marionette-service-type
  578. (marionette-configuration
  579. (imported-modules '((gnu services herd)
  580. (guix combinators)))))
  581. %base-services))))
  582. (define %encrypted-root-installation-script
  583. ;; Shell script of a simple installation.
  584. "\
  585. . /etc/profile
  586. set -e -x
  587. guix --version
  588. export GUIX_BUILD_OPTIONS=--no-grafts
  589. ls -l /run/current-system/gc-roots
  590. parted --script /dev/vdb mklabel gpt \\
  591. mkpart primary ext2 1M 3M \\
  592. mkpart primary ext2 3M 1.4G \\
  593. set 1 boot on \\
  594. set 1 bios_grub on
  595. echo -n thepassphrase | \\
  596. cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
  597. echo -n thepassphrase | \\
  598. cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
  599. mkfs.ext4 -L my-root /dev/mapper/the-root-device
  600. mount LABEL=my-root /mnt
  601. herd start cow-store /mnt
  602. mkdir /mnt/etc
  603. cp /etc/target-config.scm /mnt/etc/config.scm
  604. guix system build /mnt/etc/config.scm
  605. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  606. sync
  607. reboot\n")
  608. (define (enter-luks-passphrase marionette)
  609. "Return a gexp to be inserted in the basic system test running on MARIONETTE
  610. to enter the LUKS passphrase."
  611. (let ((ocrad (file-append ocrad "/bin/ocrad")))
  612. #~(begin
  613. (define (passphrase-prompt? text)
  614. (string-contains (pk 'screen-text text) "Enter pass"))
  615. (define (bios-boot-screen? text)
  616. ;; Return true if TEXT corresponds to the boot screen, before GRUB's
  617. ;; menu.
  618. (string-prefix? "SeaBIOS" text))
  619. (test-assert "enter LUKS passphrase for GRUB"
  620. (begin
  621. ;; At this point we have no choice but to use OCR to determine
  622. ;; when the passphrase should be entered.
  623. (wait-for-screen-text #$marionette passphrase-prompt?
  624. #:ocrad #$ocrad)
  625. (marionette-type "thepassphrase\n" #$marionette)
  626. ;; Now wait until we leave the boot screen. This is necessary so
  627. ;; we can then be sure we match the "Enter passphrase" prompt from
  628. ;; 'cryptsetup', in the initrd.
  629. (wait-for-screen-text #$marionette (negate bios-boot-screen?)
  630. #:ocrad #$ocrad
  631. #:timeout 20)))
  632. (test-assert "enter LUKS passphrase for the initrd"
  633. (begin
  634. ;; XXX: Here we use OCR as well but we could instead use QEMU
  635. ;; '-serial stdio' and run it in an input pipe,
  636. (wait-for-screen-text #$marionette passphrase-prompt?
  637. #:ocrad #$ocrad
  638. #:timeout 60)
  639. (marionette-type "thepassphrase\n" #$marionette)
  640. ;; Take a screenshot for debugging purposes.
  641. (marionette-control (string-append "screendump " #$output
  642. "/post-initrd-passphrase.ppm")
  643. #$marionette))))))
  644. (define %test-encrypted-root-os
  645. (system-test
  646. (name "encrypted-root-os")
  647. (description
  648. "Test basic functionality of an OS installed like one would do by hand.
  649. This test is expensive in terms of CPU and storage usage since we need to
  650. build (current-guix) and then store a couple of full system images.")
  651. (value
  652. (mlet* %store-monad ((image (run-install %encrypted-root-os
  653. %encrypted-root-os-source
  654. #:script
  655. %encrypted-root-installation-script))
  656. (command (qemu-command/writable-image image)))
  657. (run-basic-test %encrypted-root-os command "encrypted-root-os"
  658. #:initialization enter-luks-passphrase)))))
  659. ;;;
  660. ;;; Btrfs root file system.
  661. ;;;
  662. (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
  663. ;; The OS we want to install.
  664. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  665. (operating-system
  666. (host-name "liberigilo")
  667. (timezone "Europe/Paris")
  668. (locale "en_US.UTF-8")
  669. (bootloader (bootloader-configuration
  670. (bootloader grub-bootloader)
  671. (target "/dev/vdb")))
  672. (kernel-arguments '("console=ttyS0"))
  673. (file-systems (cons (file-system
  674. (device (file-system-label "my-root"))
  675. (mount-point "/")
  676. (type "btrfs"))
  677. %base-file-systems))
  678. (users (cons (user-account
  679. (name "charlie")
  680. (group "users")
  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)))))
  687. %base-services))))
  688. (define %btrfs-root-installation-script
  689. ;; Shell script of a simple installation.
  690. "\
  691. . /etc/profile
  692. set -e -x
  693. guix --version
  694. export GUIX_BUILD_OPTIONS=--no-grafts
  695. ls -l /run/current-system/gc-roots
  696. parted --script /dev/vdb mklabel gpt \\
  697. mkpart primary ext2 1M 3M \\
  698. mkpart primary ext2 3M 2G \\
  699. set 1 boot on \\
  700. set 1 bios_grub on
  701. mkfs.btrfs -L my-root /dev/vdb2
  702. mount /dev/vdb2 /mnt
  703. btrfs subvolume create /mnt/home
  704. herd start cow-store /mnt
  705. mkdir /mnt/etc
  706. cp /etc/target-config.scm /mnt/etc/config.scm
  707. guix system build /mnt/etc/config.scm
  708. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  709. sync
  710. reboot\n")
  711. (define %test-btrfs-root-os
  712. (system-test
  713. (name "btrfs-root-os")
  714. (description
  715. "Test basic functionality of an OS installed like one would do by hand.
  716. This test is expensive in terms of CPU and storage usage since we need to
  717. build (current-guix) and then store a couple of full system images.")
  718. (value
  719. (mlet* %store-monad ((image (run-install %btrfs-root-os
  720. %btrfs-root-os-source
  721. #:script
  722. %btrfs-root-installation-script))
  723. (command (qemu-command/writable-image image)))
  724. (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
  725. ;;; install.scm ends here