install.scm 32 KB

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