install.scm 30 KB

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