install.scm 31 KB

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