install.scm 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2017, 2019, 2021 Tobias Geerinckx-Rice <me@tobias.gr>
  4. ;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
  5. ;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
  6. ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  7. ;;; Copyright © 2020, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
  8. ;;;
  9. ;;; This file is part of GNU Guix.
  10. ;;;
  11. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  12. ;;; under the terms of the GNU General Public License as published by
  13. ;;; the Free Software Foundation; either version 3 of the License, or (at
  14. ;;; your option) any later version.
  15. ;;;
  16. ;;; GNU Guix is distributed in the hope that it will be useful, but
  17. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. ;;; GNU General Public License for more details.
  20. ;;;
  21. ;;; You should have received a copy of the GNU General Public License
  22. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  23. (define-module (gnu tests install)
  24. #:use-module (gnu)
  25. #:use-module (gnu bootloader extlinux)
  26. #:use-module (gnu image)
  27. #:use-module (gnu tests)
  28. #:use-module (gnu tests base)
  29. #:use-module (gnu system)
  30. #:use-module (gnu system image)
  31. #:use-module (gnu system install)
  32. #:use-module (gnu system vm)
  33. #:use-module ((gnu build marionette) #:select (qemu-command))
  34. #:use-module (gnu packages admin)
  35. #:use-module (gnu packages bootloaders)
  36. #:use-module (gnu packages commencement) ;for 'guile-final'
  37. #:use-module (gnu packages cryptsetup)
  38. #:use-module (gnu packages disk)
  39. #:use-module (gnu packages emacs)
  40. #:use-module (gnu packages emacs-xyz)
  41. #:use-module (gnu packages firmware)
  42. #:use-module (gnu packages linux)
  43. #:use-module (gnu packages ocr)
  44. #:use-module (gnu packages openbox)
  45. #:use-module (gnu packages package-management)
  46. #:use-module (gnu packages ratpoison)
  47. #:use-module (gnu packages suckless)
  48. #:use-module (gnu packages virtualization)
  49. #:use-module (gnu packages wm)
  50. #:use-module (gnu packages xorg)
  51. #:use-module (gnu services desktop)
  52. #:use-module (gnu services networking)
  53. #:use-module (gnu services xorg)
  54. #:use-module (guix store)
  55. #:use-module (guix monads)
  56. #:use-module (guix packages)
  57. #:use-module (guix grafts)
  58. #:use-module (guix gexp)
  59. #:use-module (guix utils)
  60. #:use-module (srfi srfi-1)
  61. #:export (%test-installed-os
  62. %test-installed-extlinux-os
  63. %test-iso-image-installer
  64. %test-separate-store-os
  65. %test-separate-home-os
  66. %test-raid-root-os
  67. %test-encrypted-root-os
  68. %test-encrypted-root-not-boot-os
  69. %test-btrfs-root-os
  70. %test-btrfs-root-on-subvolume-os
  71. %test-btrfs-raid-root-os
  72. %test-jfs-root-os
  73. %test-f2fs-root-os
  74. %test-xfs-root-os
  75. %test-lvm-separate-home-os
  76. %test-gui-installed-os
  77. %test-gui-uefi-installed-os
  78. %test-gui-installed-os-encrypted
  79. %test-gui-installed-desktop-os-encrypted))
  80. ;;; Commentary:
  81. ;;;
  82. ;;; Test the installation of Guix using the documented approach at the
  83. ;;; command line.
  84. ;;;
  85. ;;; Code:
  86. (define-os-with-source (%minimal-os %minimal-os-source)
  87. ;; The OS we want to install.
  88. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  89. (operating-system
  90. (host-name "liberigilo")
  91. (timezone "Europe/Paris")
  92. (locale "en_US.UTF-8")
  93. (bootloader (bootloader-configuration
  94. (bootloader grub-bootloader)
  95. (targets (list "/dev/vdb"))))
  96. (kernel-arguments '("console=ttyS0"))
  97. (file-systems (cons (file-system
  98. (device (file-system-label "my-root"))
  99. (mount-point "/")
  100. (type "ext4"))
  101. %base-file-systems))
  102. (users (cons (user-account
  103. (name "alice")
  104. (comment "Bob's sister")
  105. (group "users")
  106. (supplementary-groups '("wheel" "audio" "video")))
  107. %base-user-accounts))
  108. (services (cons (service marionette-service-type
  109. (marionette-configuration
  110. (imported-modules '((gnu services herd)
  111. (guix build utils)
  112. (guix combinators)))))
  113. %base-services))))
  114. (define (operating-system-add-packages os packages)
  115. "Append PACKAGES to OS packages list."
  116. (operating-system
  117. (inherit os)
  118. (packages (append packages (operating-system-packages os)))))
  119. (define-os-with-source (%minimal-extlinux-os
  120. %minimal-extlinux-os-source)
  121. (use-modules (gnu) (gnu tests) (gnu bootloader extlinux)
  122. (srfi srfi-1))
  123. (operating-system
  124. (host-name "liberigilo")
  125. (timezone "Europe/Paris")
  126. (locale "en_US.UTF-8")
  127. (bootloader (bootloader-configuration
  128. (bootloader extlinux-bootloader-gpt)
  129. (targets (list "/dev/vdb"))))
  130. (kernel-arguments '("console=ttyS0"))
  131. (file-systems (cons (file-system
  132. (device (file-system-label "my-root"))
  133. (mount-point "/")
  134. (type "ext4"))
  135. %base-file-systems))
  136. (services (cons (service marionette-service-type
  137. (marionette-configuration
  138. (imported-modules '((gnu services herd)
  139. (guix combinators)))))
  140. %base-services))))
  141. (define (operating-system-with-current-guix os)
  142. "Return a variant of OS that uses the current Guix."
  143. (operating-system
  144. (inherit os)
  145. (services (modify-services (operating-system-user-services os)
  146. (guix-service-type config =>
  147. (guix-configuration
  148. (inherit config)
  149. (guix (current-guix))))))))
  150. (define MiB (expt 2 20))
  151. (define %simple-installation-script
  152. ;; Shell script of a simple installation.
  153. "\
  154. . /etc/profile
  155. set -e -x
  156. guix --version
  157. export GUIX_BUILD_OPTIONS=--no-grafts
  158. guix build isc-dhcp
  159. parted --script /dev/vdb mklabel gpt \\
  160. mkpart primary ext2 1M 3M \\
  161. mkpart primary ext2 3M 1.6G \\
  162. set 1 boot on \\
  163. set 1 bios_grub on
  164. mkfs.ext4 -L my-root /dev/vdb2
  165. mount /dev/vdb2 /mnt
  166. df -h /mnt
  167. herd start cow-store /mnt
  168. mkdir /mnt/etc
  169. cp /etc/target-config.scm /mnt/etc/config.scm
  170. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  171. sync
  172. reboot\n")
  173. (define %extlinux-gpt-installation-script
  174. ;; Shell script of a simple installation.
  175. ;; As syslinux 6.0.3 does not handle 64bits ext4 partitions,
  176. ;; we make sure to pass -O '^64bit' to mkfs.
  177. "\
  178. . /etc/profile
  179. set -e -x
  180. guix --version
  181. export GUIX_BUILD_OPTIONS=--no-grafts
  182. guix build isc-dhcp
  183. parted --script /dev/vdb mklabel gpt \\
  184. mkpart ext2 1M 1.6G \\
  185. set 1 legacy_boot on
  186. mkfs.ext4 -L my-root -O '^64bit' /dev/vdb1
  187. mount /dev/vdb1 /mnt
  188. df -h /mnt
  189. herd start cow-store /mnt
  190. mkdir /mnt/etc
  191. cp /etc/target-config.scm /mnt/etc/config.scm
  192. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  193. sync
  194. reboot\n")
  195. (define (uefi-firmware system)
  196. "Return the appropriate QEMU OVMF UEFI firmware for the given SYSTEM."
  197. (cond
  198. ((string-prefix? "x86_64" system)
  199. (file-append ovmf "/share/firmware/ovmf_x64.bin"))
  200. ((string-prefix? "i686" system)
  201. (file-append ovmf "/share/firmware/ovmf_ia32.bin"))
  202. (else #f)))
  203. (define* (run-install target-os target-os-source
  204. #:key
  205. (script %simple-installation-script)
  206. (gui-test #f)
  207. (packages '())
  208. (os (marionette-operating-system
  209. (operating-system
  210. ;; Since the image has no network access, use the
  211. ;; current Guix so the store items we need are in
  212. ;; the image and add packages provided.
  213. (inherit (operating-system-add-packages
  214. (operating-system-with-current-guix
  215. installation-os)
  216. packages))
  217. (kernel-arguments '("console=ttyS0")))
  218. #:imported-modules '((gnu services herd)
  219. (gnu installer tests)
  220. (guix combinators))))
  221. (uefi-support? #f)
  222. (installation-image-type 'efi-raw)
  223. (install-size 'guess)
  224. (target-size (* 2200 MiB)))
  225. "Run SCRIPT (a shell script following the system installation procedure) in
  226. OS to install TARGET-OS. Return a VM image of TARGET-SIZE bytes containing
  227. the installed system. The packages specified in PACKAGES will be appended to
  228. packages defined in installation-os."
  229. (mlet* %store-monad ((_ (set-grafting #f))
  230. (system (current-system))
  231. (uefi-firmware -> (and uefi-support?
  232. (uefi-firmware system)))
  233. ;; Since the installation system has no network access,
  234. ;; we cheat a little bit by adding TARGET to its GC
  235. ;; roots. This way, we know 'guix system init' will
  236. ;; succeed. Also add guile-final, which is pulled in
  237. ;; through provenance.drv and may not always be present.
  238. (target (operating-system-derivation target-os))
  239. (base-image ->
  240. (os->image
  241. (operating-system-with-gc-roots
  242. os (list target guile-final))
  243. #:type (lookup-image-type-by-name
  244. installation-image-type)))
  245. (image ->
  246. (system-image
  247. (image
  248. (inherit base-image)
  249. (size install-size)
  250. ;; Don't provide substitutes; too big.
  251. (substitutable? #f)))))
  252. (define install
  253. (with-imported-modules '((guix build utils)
  254. (gnu build marionette))
  255. #~(begin
  256. (use-modules (guix build utils)
  257. (gnu build marionette))
  258. (set-path-environment-variable "PATH" '("bin")
  259. (list #$qemu-minimal))
  260. (system* "qemu-img" "create" "-f" "qcow2"
  261. #$output #$(number->string target-size))
  262. (define marionette
  263. (make-marionette
  264. `(,(which #$(qemu-command system))
  265. "-no-reboot"
  266. "-m" "1200"
  267. ,@(if #$uefi-firmware
  268. '("-bios" #$uefi-firmware)
  269. '())
  270. #$@(cond
  271. ((eq? 'efi-raw installation-image-type)
  272. #~("-drive"
  273. ,(string-append "file=" #$image
  274. ",if=virtio,readonly")))
  275. ((eq? 'uncompressed-iso9660 installation-image-type)
  276. #~("-cdrom" #$image))
  277. (else
  278. (error
  279. "unsupported installation-image-type:"
  280. installation-image-type)))
  281. "-drive"
  282. ,(string-append "file=" #$output ",if=virtio")
  283. ,@(if (file-exists? "/dev/kvm")
  284. '("-enable-kvm")
  285. '()))))
  286. (pk 'uname (marionette-eval '(uname) marionette))
  287. ;; Wait for tty1.
  288. (marionette-eval '(begin
  289. (use-modules (gnu services herd))
  290. (start 'term-tty1))
  291. marionette)
  292. (when #$(->bool script)
  293. (marionette-eval '(call-with-output-file "/etc/target-config.scm"
  294. (lambda (port)
  295. (write '#$target-os-source port)))
  296. marionette)
  297. ;; Run SCRIPT. It typically invokes 'reboot' as a last step and
  298. ;; thus normally gets killed with SIGTERM by PID 1.
  299. (let ((status (marionette-eval '(system #$script) marionette)))
  300. (exit (or (eof-object? status)
  301. (equal? (status:term-sig status) SIGTERM)
  302. (equal? (status:exit-val status) 0)))))
  303. (when #$(->bool gui-test)
  304. (wait-for-unix-socket "/var/guix/installer-socket"
  305. marionette)
  306. (format #t "installer socket ready~%")
  307. (force-output)
  308. (exit #$(and gui-test
  309. (gui-test #~marionette)))))))
  310. (gexp->derivation "installation" install
  311. #:substitutable? #f))) ;too big
  312. (define* (qemu-command/writable-image image
  313. #:key
  314. (uefi-support? #f)
  315. (memory-size 256))
  316. "Return as a monadic value the command to run QEMU on a writable copy of
  317. IMAGE, a disk image. The QEMU VM has access to MEMORY-SIZE MiB of RAM."
  318. (mlet* %store-monad ((system (current-system))
  319. (uefi-firmware -> (and uefi-support?
  320. (uefi-firmware system))))
  321. (return #~(let ((image #$image))
  322. ;; First we need a writable copy of the image.
  323. (format #t "creating writable image from '~a'...~%" image)
  324. (unless (zero? (system* #+(file-append qemu-minimal
  325. "/bin/qemu-img")
  326. "create" "-f" "qcow2" "-F" "qcow2"
  327. "-o"
  328. (string-append "backing_file=" image)
  329. "disk.img"))
  330. (error "failed to create writable QEMU image" image))
  331. (chmod "disk.img" #o644)
  332. `(,(string-append #$qemu-minimal "/bin/"
  333. #$(qemu-command system))
  334. ,@(if (file-exists? "/dev/kvm")
  335. '("-enable-kvm")
  336. '())
  337. ,@(if #$uefi-firmware
  338. '("-bios" #$uefi-firmware)
  339. '())
  340. "-no-reboot" "-m" #$(number->string memory-size)
  341. "-drive" "file=disk.img,if=virtio")))))
  342. (define %test-installed-os
  343. (system-test
  344. (name "installed-os")
  345. (description
  346. "Test basic functionality of an OS installed like one would do by hand.
  347. This test is expensive in terms of CPU and storage usage since we need to
  348. build (current-guix) and then store a couple of full system images.")
  349. (value
  350. (mlet* %store-monad ((image (run-install %minimal-os %minimal-os-source))
  351. (command (qemu-command/writable-image image)))
  352. (run-basic-test %minimal-os command
  353. "installed-os")))))
  354. (define %test-installed-extlinux-os
  355. (system-test
  356. (name "installed-extlinux-os")
  357. (description
  358. "Test basic functionality of an OS booted with an extlinux bootloader. As
  359. per %test-installed-os, this test is expensive in terms of CPU and storage.")
  360. (value
  361. (mlet* %store-monad ((image (run-install %minimal-extlinux-os
  362. %minimal-extlinux-os-source
  363. #:packages
  364. (list syslinux)
  365. #:script
  366. %extlinux-gpt-installation-script))
  367. (command (qemu-command/writable-image image)))
  368. (run-basic-test %minimal-extlinux-os command
  369. "installed-extlinux-os")))))
  370. ;;;
  371. ;;; Installation through an ISO image.
  372. ;;;
  373. (define-os-with-source (%minimal-os-on-vda %minimal-os-on-vda-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.UTF-8")
  380. (bootloader (bootloader-configuration
  381. (bootloader grub-bootloader)
  382. (targets (list "/dev/vda"))))
  383. (kernel-arguments '("console=ttyS0"))
  384. (file-systems (cons (file-system
  385. (device (file-system-label "my-root"))
  386. (mount-point "/")
  387. (type "ext4"))
  388. %base-file-systems))
  389. (users (cons (user-account
  390. (name "alice")
  391. (comment "Bob's sister")
  392. (group "users")
  393. (supplementary-groups '("wheel" "audio" "video")))
  394. %base-user-accounts))
  395. (services (cons (service marionette-service-type
  396. (marionette-configuration
  397. (imported-modules '((gnu services herd)
  398. (guix build utils)
  399. (guix combinators)))))
  400. %base-services))))
  401. (define %simple-installation-script-for-/dev/vda
  402. ;; Shell script of a simple installation.
  403. "\
  404. . /etc/profile
  405. set -e -x
  406. guix --version
  407. export GUIX_BUILD_OPTIONS=--no-grafts
  408. guix build isc-dhcp
  409. parted --script /dev/vda mklabel gpt \\
  410. mkpart primary ext2 1M 3M \\
  411. mkpart primary ext2 3M 1.6G \\
  412. set 1 boot on \\
  413. set 1 bios_grub on
  414. mkfs.ext4 -L my-root /dev/vda2
  415. mount /dev/vda2 /mnt
  416. df -h /mnt
  417. herd start cow-store /mnt
  418. mkdir /mnt/etc
  419. cp /etc/target-config.scm /mnt/etc/config.scm
  420. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  421. sync
  422. reboot\n")
  423. (define %test-iso-image-installer
  424. (system-test
  425. (name "iso-image-installer")
  426. (description
  427. "")
  428. (value
  429. (mlet* %store-monad ((image (run-install
  430. %minimal-os-on-vda
  431. %minimal-os-on-vda-source
  432. #:script
  433. %simple-installation-script-for-/dev/vda
  434. #:installation-image-type
  435. 'uncompressed-iso9660))
  436. (command (qemu-command/writable-image image)))
  437. (run-basic-test %minimal-os-on-vda command name)))))
  438. ;;;
  439. ;;; Separate /home.
  440. ;;;
  441. (define-os-with-source (%separate-home-os %separate-home-os-source)
  442. ;; The OS we want to install.
  443. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  444. (operating-system
  445. (host-name "liberigilo")
  446. (timezone "Europe/Paris")
  447. (locale "en_US.utf8")
  448. (bootloader (bootloader-configuration
  449. (bootloader grub-bootloader)
  450. (targets '("/dev/vdb"))))
  451. (kernel-arguments '("console=ttyS0"))
  452. (file-systems (cons* (file-system
  453. (device (file-system-label "my-root"))
  454. (mount-point "/")
  455. (type "ext4"))
  456. (file-system
  457. (device "none")
  458. (mount-point "/home")
  459. (type "tmpfs"))
  460. %base-file-systems))
  461. (users (cons* (user-account
  462. (name "alice")
  463. (group "users"))
  464. (user-account
  465. (name "charlie")
  466. (group "users"))
  467. %base-user-accounts))
  468. (services (cons (service marionette-service-type
  469. (marionette-configuration
  470. (imported-modules '((gnu services herd)
  471. (guix combinators)))))
  472. %base-services))))
  473. (define %test-separate-home-os
  474. (system-test
  475. (name "separate-home-os")
  476. (description
  477. "Test basic functionality of an installed OS with a separate /home
  478. partition. In particular, home directories must be correctly created (see
  479. <https://bugs.gnu.org/21108>).")
  480. (value
  481. (mlet* %store-monad ((image (run-install %separate-home-os
  482. %separate-home-os-source
  483. #:script
  484. %simple-installation-script))
  485. (command (qemu-command/writable-image image)))
  486. (run-basic-test %separate-home-os command "separate-home-os")))))
  487. ;;;
  488. ;;; Separate /gnu/store partition.
  489. ;;;
  490. (define-os-with-source (%separate-store-os %separate-store-os-source)
  491. ;; The OS we want to install.
  492. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  493. (operating-system
  494. (host-name "liberigilo")
  495. (timezone "Europe/Paris")
  496. (locale "en_US.UTF-8")
  497. (bootloader (bootloader-configuration
  498. (bootloader grub-bootloader)
  499. (targets (list "/dev/vdb"))))
  500. (kernel-arguments '("console=ttyS0"))
  501. (file-systems (cons* (file-system
  502. (device (file-system-label "root-fs"))
  503. (mount-point "/")
  504. (type "ext4"))
  505. (file-system
  506. (device (file-system-label "store-fs"))
  507. (mount-point "/gnu")
  508. (type "ext4"))
  509. %base-file-systems))
  510. (users %base-user-accounts)
  511. (services (cons (service marionette-service-type
  512. (marionette-configuration
  513. (imported-modules '((gnu services herd)
  514. (guix combinators)))))
  515. %base-services))))
  516. (define %separate-store-installation-script
  517. ;; Installation with a separate /gnu partition.
  518. "\
  519. . /etc/profile
  520. set -e -x
  521. guix --version
  522. export GUIX_BUILD_OPTIONS=--no-grafts
  523. guix build isc-dhcp
  524. parted --script /dev/vdb mklabel gpt \\
  525. mkpart primary ext2 1M 3M \\
  526. mkpart primary ext2 3M 400M \\
  527. mkpart primary ext2 400M 2.1G \\
  528. set 1 boot on \\
  529. set 1 bios_grub on
  530. mkfs.ext4 -L root-fs /dev/vdb2
  531. mkfs.ext4 -L store-fs /dev/vdb3
  532. mount /dev/vdb2 /mnt
  533. mkdir /mnt/gnu
  534. mount /dev/vdb3 /mnt/gnu
  535. df -h /mnt
  536. df -h /mnt/gnu
  537. herd start cow-store /mnt
  538. mkdir /mnt/etc
  539. cp /etc/target-config.scm /mnt/etc/config.scm
  540. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  541. sync
  542. reboot\n")
  543. (define %test-separate-store-os
  544. (system-test
  545. (name "separate-store-os")
  546. (description
  547. "Test basic functionality of an OS installed like one would do by hand,
  548. where /gnu lives on a separate partition.")
  549. (value
  550. (mlet* %store-monad ((image (run-install %separate-store-os
  551. %separate-store-os-source
  552. #:script
  553. %separate-store-installation-script))
  554. (command (qemu-command/writable-image image)))
  555. (run-basic-test %separate-store-os command "separate-store-os")))))
  556. ;;;
  557. ;;; RAID root device.
  558. ;;;
  559. (define-os-with-source (%raid-root-os %raid-root-os-source)
  560. ;; An OS whose root partition is a RAID partition.
  561. (use-modules (gnu) (gnu tests))
  562. (operating-system
  563. (host-name "raidified")
  564. (timezone "Europe/Paris")
  565. (locale "en_US.utf8")
  566. (bootloader (bootloader-configuration
  567. (bootloader grub-bootloader)
  568. (targets (list "/dev/vdb"))))
  569. (kernel-arguments '("console=ttyS0"))
  570. ;; Add a kernel module for RAID-1 (aka. "mirror").
  571. (initrd-modules (cons "raid1" %base-initrd-modules))
  572. (mapped-devices (list (mapped-device
  573. (source (list "/dev/vda2" "/dev/vda3"))
  574. (target "/dev/md0")
  575. (type raid-device-mapping))))
  576. (file-systems (cons (file-system
  577. (device (file-system-label "root-fs"))
  578. (mount-point "/")
  579. (type "ext4")
  580. (dependencies mapped-devices))
  581. %base-file-systems))
  582. (users %base-user-accounts)
  583. (services (cons (service marionette-service-type
  584. (marionette-configuration
  585. (imported-modules '((gnu services herd)
  586. (guix combinators)))))
  587. %base-services))))
  588. (define %raid-root-installation-script
  589. ;; Installation with a separate /gnu partition. See
  590. ;; <https://raid.wiki.kernel.org/index.php/RAID_setup> for more on RAID and
  591. ;; mdadm.
  592. "\
  593. . /etc/profile
  594. set -e -x
  595. guix --version
  596. export GUIX_BUILD_OPTIONS=--no-grafts
  597. parted --script /dev/vdb mklabel gpt \\
  598. mkpart primary ext2 1M 3M \\
  599. mkpart primary ext2 3M 1.6G \\
  600. mkpart primary ext2 1.6G 3.2G \\
  601. set 1 boot on \\
  602. set 1 bios_grub on
  603. yes | mdadm --create /dev/md0 --verbose --level=mirror --raid-devices=2 \\
  604. /dev/vdb2 /dev/vdb3
  605. mkfs.ext4 -L root-fs /dev/md0
  606. mount /dev/md0 /mnt
  607. df -h /mnt
  608. herd start cow-store /mnt
  609. mkdir /mnt/etc
  610. cp /etc/target-config.scm /mnt/etc/config.scm
  611. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  612. sync
  613. reboot\n")
  614. (define %test-raid-root-os
  615. (system-test
  616. (name "raid-root-os")
  617. (description
  618. "Test functionality of an OS installed with a RAID root partition managed
  619. by 'mdadm'.")
  620. (value
  621. (mlet* %store-monad ((image (run-install %raid-root-os
  622. %raid-root-os-source
  623. #:script
  624. %raid-root-installation-script
  625. #:target-size (* 3200 MiB)))
  626. (command (qemu-command/writable-image image)))
  627. (run-basic-test %raid-root-os
  628. `(,@command) "raid-root-os")))))
  629. ;;;
  630. ;;; LUKS-encrypted root file system.
  631. ;;;
  632. (define-os-with-source (%encrypted-root-os %encrypted-root-os-source)
  633. ;; The OS we want to install.
  634. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  635. (operating-system
  636. (host-name "liberigilo")
  637. (timezone "Europe/Paris")
  638. (locale "en_US.UTF-8")
  639. (bootloader (bootloader-configuration
  640. (bootloader grub-bootloader)
  641. (targets '("/dev/vdb"))))
  642. ;; Note: Do not pass "console=ttyS0" so we can use our passphrase prompt
  643. ;; detection logic in 'enter-luks-passphrase'.
  644. (mapped-devices (list (mapped-device
  645. (source (uuid "12345678-1234-1234-1234-123456789abc"))
  646. (target "the-root-device")
  647. (type luks-device-mapping))))
  648. (file-systems (cons (file-system
  649. (device "/dev/mapper/the-root-device")
  650. (mount-point "/")
  651. (type "ext4"))
  652. %base-file-systems))
  653. (users (cons (user-account
  654. (name "charlie")
  655. (group "users")
  656. (supplementary-groups '("wheel" "audio" "video")))
  657. %base-user-accounts))
  658. (services (cons (service marionette-service-type
  659. (marionette-configuration
  660. (imported-modules '((gnu services herd)
  661. (guix combinators)))))
  662. %base-services))))
  663. (define %luks-passphrase
  664. ;; LUKS encryption passphrase used in tests.
  665. "thepassphrase")
  666. (define %encrypted-root-installation-script
  667. ;; Shell script of a simple installation.
  668. (string-append "\
  669. . /etc/profile
  670. set -e -x
  671. guix --version
  672. export GUIX_BUILD_OPTIONS=--no-grafts
  673. ls -l /run/current-system/gc-roots
  674. parted --script /dev/vdb mklabel gpt \\
  675. mkpart primary ext2 1M 3M \\
  676. mkpart primary ext2 3M 1.6G \\
  677. set 1 boot on \\
  678. set 1 bios_grub on
  679. echo -n " %luks-passphrase " | \\
  680. cryptsetup luksFormat --uuid=12345678-1234-1234-1234-123456789abc -q /dev/vdb2 -
  681. echo -n " %luks-passphrase " | \\
  682. cryptsetup open --type luks --key-file - /dev/vdb2 the-root-device
  683. mkfs.ext4 -L my-root /dev/mapper/the-root-device
  684. mount LABEL=my-root /mnt
  685. herd start cow-store /mnt
  686. mkdir /mnt/etc
  687. cp /etc/target-config.scm /mnt/etc/config.scm
  688. guix system build /mnt/etc/config.scm
  689. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  690. sync
  691. reboot\n"))
  692. (define (enter-luks-passphrase marionette)
  693. "Return a gexp to be inserted in the basic system test running on MARIONETTE
  694. to enter the LUKS passphrase."
  695. (let ((ocrad (file-append ocrad "/bin/ocrad")))
  696. #~(begin
  697. (define (passphrase-prompt? text)
  698. (string-contains (pk 'screen-text text) "Enter pass"))
  699. (define (bios-boot-screen? text)
  700. ;; Return true if TEXT corresponds to the boot screen, before GRUB's
  701. ;; menu.
  702. (string-prefix? "SeaBIOS" text))
  703. (test-assert "enter LUKS passphrase for GRUB"
  704. (begin
  705. ;; At this point we have no choice but to use OCR to determine
  706. ;; when the passphrase should be entered.
  707. (wait-for-screen-text #$marionette passphrase-prompt?
  708. #:ocrad #$ocrad)
  709. (marionette-type #$(string-append %luks-passphrase "\n")
  710. #$marionette)
  711. ;; Now wait until we leave the boot screen. This is necessary so
  712. ;; we can then be sure we match the "Enter passphrase" prompt from
  713. ;; 'cryptsetup', in the initrd.
  714. (wait-for-screen-text #$marionette (negate bios-boot-screen?)
  715. #:ocrad #$ocrad
  716. #:timeout 20)))
  717. (test-assert "enter LUKS passphrase for the initrd"
  718. (begin
  719. ;; XXX: Here we use OCR as well but we could instead use QEMU
  720. ;; '-serial stdio' and run it in an input pipe,
  721. (wait-for-screen-text #$marionette passphrase-prompt?
  722. #:ocrad #$ocrad
  723. #:timeout 60)
  724. (marionette-type #$(string-append %luks-passphrase "\n")
  725. #$marionette)
  726. ;; Take a screenshot for debugging purposes.
  727. (marionette-control (string-append "screendump " #$output
  728. "/post-initrd-passphrase.ppm")
  729. #$marionette))))))
  730. (define %test-encrypted-root-os
  731. (system-test
  732. (name "encrypted-root-os")
  733. (description
  734. "Test basic functionality of an OS installed like one would do by hand.
  735. This test is expensive in terms of CPU and storage usage since we need to
  736. build (current-guix) and then store a couple of full system images.")
  737. (value
  738. (mlet* %store-monad ((image (run-install %encrypted-root-os
  739. %encrypted-root-os-source
  740. #:script
  741. %encrypted-root-installation-script))
  742. (command (qemu-command/writable-image image)))
  743. (run-basic-test %encrypted-root-os command "encrypted-root-os"
  744. #:initialization enter-luks-passphrase)))))
  745. ;;;
  746. ;;; Separate /home on LVM
  747. ;;;
  748. ;; Since LVM support in guix currently doesn't allow root-on-LVM we use /home on LVM
  749. (define-os-with-source (%lvm-separate-home-os %lvm-separate-home-os-source)
  750. (use-modules (gnu) (gnu tests))
  751. (operating-system
  752. (host-name "separate-home-on-lvm")
  753. (timezone "Europe/Paris")
  754. (locale "en_US.utf8")
  755. (bootloader (bootloader-configuration
  756. (bootloader grub-bootloader)
  757. (targets (list "/dev/vdb"))))
  758. (kernel-arguments '("console=ttyS0"))
  759. (mapped-devices (list (mapped-device
  760. (source "vg0")
  761. (target "vg0-home")
  762. (type lvm-device-mapping))))
  763. (file-systems (cons* (file-system
  764. (device (file-system-label "root-fs"))
  765. (mount-point "/")
  766. (type "ext4"))
  767. (file-system
  768. (device "/dev/mapper/vg0-home")
  769. (mount-point "/home")
  770. (type "ext4")
  771. (dependencies mapped-devices))
  772. %base-file-systems))
  773. (users %base-user-accounts)
  774. (services (cons (service marionette-service-type
  775. (marionette-configuration
  776. (imported-modules '((gnu services herd)
  777. (guix combinators)))))
  778. %base-services))))
  779. (define %lvm-separate-home-installation-script
  780. "\
  781. . /etc/profile
  782. set -e -x
  783. guix --version
  784. export GUIX_BUILD_OPTIONS=--no-grafts
  785. parted --script /dev/vdb mklabel gpt \\
  786. mkpart primary ext2 1M 3M \\
  787. mkpart primary ext2 3M 1.6G \\
  788. mkpart primary 1.6G 3.2G \\
  789. set 1 boot on \\
  790. set 1 bios_grub on
  791. pvcreate /dev/vdb3
  792. vgcreate vg0 /dev/vdb3
  793. lvcreate -L 1.6G -n home vg0
  794. vgchange -ay
  795. mkfs.ext4 -L root-fs /dev/vdb2
  796. mkfs.ext4 /dev/mapper/vg0-home
  797. mount /dev/vdb2 /mnt
  798. mkdir /mnt/home
  799. mount /dev/mapper/vg0-home /mnt/home
  800. df -h /mnt /mnt/home
  801. herd start cow-store /mnt
  802. mkdir /mnt/etc
  803. cp /etc/target-config.scm /mnt/etc/config.scm
  804. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  805. sync
  806. reboot\n")
  807. (define %test-lvm-separate-home-os
  808. (system-test
  809. (name "lvm-separate-home-os")
  810. (description
  811. "Test functionality of an OS installed with a LVM /home partition")
  812. (value
  813. (mlet* %store-monad ((image (run-install %lvm-separate-home-os
  814. %lvm-separate-home-os-source
  815. #:script
  816. %lvm-separate-home-installation-script
  817. #:packages (list lvm2-static)
  818. #:target-size (* 3200 MiB)))
  819. (command (qemu-command/writable-image image)))
  820. (run-basic-test %lvm-separate-home-os
  821. `(,@command) "lvm-separate-home-os")))))
  822. ;;;
  823. ;;; LUKS-encrypted root file system and /boot in a non-encrypted partition.
  824. ;;;
  825. (define-os-with-source (%encrypted-root-not-boot-os
  826. %encrypted-root-not-boot-os-source)
  827. ;; The OS we want to install.
  828. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  829. (operating-system
  830. (host-name "bootroot")
  831. (timezone "Europe/Paris")
  832. (locale "en_US.UTF-8")
  833. (bootloader (bootloader-configuration
  834. (bootloader grub-bootloader)
  835. (targets (list "/dev/vdb"))))
  836. (mapped-devices (list (mapped-device
  837. (source
  838. (uuid "12345678-1234-1234-1234-123456789abc"))
  839. (target "root")
  840. (type luks-device-mapping))))
  841. (file-systems (cons* (file-system
  842. (device (file-system-label "my-boot"))
  843. (mount-point "/boot")
  844. (type "ext4"))
  845. (file-system
  846. (device "/dev/mapper/root")
  847. (mount-point "/")
  848. (type "ext4"))
  849. %base-file-systems))
  850. (users (cons (user-account
  851. (name "alice")
  852. (group "users")
  853. (supplementary-groups '("wheel" "audio" "video")))
  854. %base-user-accounts))
  855. (services (cons (service marionette-service-type
  856. (marionette-configuration
  857. (imported-modules '((gnu services herd)
  858. (guix combinators)))))
  859. %base-services))))
  860. (define %encrypted-root-not-boot-installation-script
  861. ;; Shell script for an installation with boot not encrypted but root
  862. ;; encrypted.
  863. (format #f "\
  864. . /etc/profile
  865. set -e -x
  866. guix --version
  867. export GUIX_BUILD_OPTIONS=--no-grafts
  868. ls -l /run/current-system/gc-roots
  869. parted --script /dev/vdb mklabel gpt \\
  870. mkpart primary ext2 1M 3M \\
  871. mkpart primary ext2 3M 50M \\
  872. mkpart primary ext2 50M 1.6G \\
  873. set 1 boot on \\
  874. set 1 bios_grub on
  875. echo -n \"~a\" | cryptsetup luksFormat --uuid=\"~a\" -q /dev/vdb3 -
  876. echo -n \"~a\" | cryptsetup open --type luks --key-file - /dev/vdb3 root
  877. mkfs.ext4 -L my-root /dev/mapper/root
  878. mkfs.ext4 -L my-boot /dev/vdb2
  879. mount LABEL=my-root /mnt
  880. mkdir /mnt/boot
  881. mount LABEL=my-boot /mnt/boot
  882. echo \"Checking mounts\"
  883. mount
  884. herd start cow-store /mnt
  885. mkdir /mnt/etc
  886. cp /etc/target-config.scm /mnt/etc/config.scm
  887. guix system build /mnt/etc/config.scm
  888. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  889. sync
  890. echo \"Debugging info\"
  891. blkid
  892. cat /mnt/boot/grub/grub.cfg
  893. reboot\n"
  894. %luks-passphrase "12345678-1234-1234-1234-123456789abc"
  895. %luks-passphrase))
  896. (define %test-encrypted-root-not-boot-os
  897. (system-test
  898. (name "encrypted-root-not-boot-os")
  899. (description
  900. "Test the manual installation on an OS with / in an encrypted partition
  901. but /boot on a different, non-encrypted partition. This test is expensive in
  902. terms of CPU and storage usage since we need to build (current-guix) and then
  903. store a couple of full system images.")
  904. (value
  905. (mlet* %store-monad
  906. ((image (run-install %encrypted-root-not-boot-os
  907. %encrypted-root-not-boot-os-source
  908. #:script
  909. %encrypted-root-not-boot-installation-script))
  910. (command (qemu-command/writable-image image)))
  911. (run-basic-test %encrypted-root-not-boot-os command
  912. "encrypted-root-not-boot-os"
  913. #:initialization enter-luks-passphrase)))))
  914. ;;;
  915. ;;; Btrfs root file system.
  916. ;;;
  917. (define-os-with-source (%btrfs-root-os %btrfs-root-os-source)
  918. ;; The OS we want to install.
  919. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  920. (operating-system
  921. (host-name "liberigilo")
  922. (timezone "Europe/Paris")
  923. (locale "en_US.UTF-8")
  924. (bootloader (bootloader-configuration
  925. (bootloader grub-bootloader)
  926. (targets (list "/dev/vdb"))))
  927. (kernel-arguments '("console=ttyS0"))
  928. (file-systems (cons (file-system
  929. (device (file-system-label "my-root"))
  930. (mount-point "/")
  931. (type "btrfs"))
  932. %base-file-systems))
  933. (users (cons (user-account
  934. (name "charlie")
  935. (group "users")
  936. (supplementary-groups '("wheel" "audio" "video")))
  937. %base-user-accounts))
  938. (services (cons (service marionette-service-type
  939. (marionette-configuration
  940. (imported-modules '((gnu services herd)
  941. (guix combinators)))))
  942. %base-services))))
  943. (define %btrfs-root-installation-script
  944. ;; Shell script of a simple installation.
  945. "\
  946. . /etc/profile
  947. set -e -x
  948. guix --version
  949. export GUIX_BUILD_OPTIONS=--no-grafts
  950. ls -l /run/current-system/gc-roots
  951. parted --script /dev/vdb mklabel gpt \\
  952. mkpart primary ext2 1M 3M \\
  953. mkpart primary ext2 3M 2G \\
  954. set 1 boot on \\
  955. set 1 bios_grub on
  956. mkfs.btrfs -L my-root /dev/vdb2
  957. mount /dev/vdb2 /mnt
  958. btrfs subvolume create /mnt/home
  959. herd start cow-store /mnt
  960. mkdir /mnt/etc
  961. cp /etc/target-config.scm /mnt/etc/config.scm
  962. guix system build /mnt/etc/config.scm
  963. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  964. sync
  965. reboot\n")
  966. (define %test-btrfs-root-os
  967. (system-test
  968. (name "btrfs-root-os")
  969. (description
  970. "Test basic functionality of an OS installed like one would do by hand.
  971. This test is expensive in terms of CPU and storage usage since we need to
  972. build (current-guix) and then store a couple of full system images.")
  973. (value
  974. (mlet* %store-monad ((image (run-install %btrfs-root-os
  975. %btrfs-root-os-source
  976. #:script
  977. %btrfs-root-installation-script))
  978. (command (qemu-command/writable-image image)))
  979. (run-basic-test %btrfs-root-os command "btrfs-root-os")))))
  980. ;;;
  981. ;;; Btrfs RAID-0 root file system.
  982. ;;;
  983. (define-os-with-source (%btrfs-raid-root-os %btrfs-raid-root-os-source)
  984. ;; An OS whose root partition is a RAID partition.
  985. (use-modules (gnu) (gnu tests))
  986. (operating-system
  987. (host-name "liberigilo")
  988. (timezone "Europe/Paris")
  989. (locale "en_US.utf8")
  990. (bootloader (bootloader-configuration
  991. (bootloader grub-bootloader)
  992. (targets (list "/dev/vdb"))))
  993. (kernel-arguments '("console=ttyS0"))
  994. (file-systems (cons (file-system
  995. (device (file-system-label "root-fs"))
  996. (mount-point "/")
  997. (type "btrfs"))
  998. %base-file-systems))
  999. (users %base-user-accounts)
  1000. (services (cons (service marionette-service-type
  1001. (marionette-configuration
  1002. (imported-modules '((gnu services herd)
  1003. (guix combinators)))))
  1004. %base-services))))
  1005. (define %btrfs-raid-root-installation-script
  1006. "\
  1007. . /etc/profile
  1008. set -e -x
  1009. guix --version
  1010. export GUIX_BUILD_OPTIONS=--no-grafts
  1011. parted --script /dev/vdb mklabel gpt \\
  1012. mkpart primary ext2 1M 3M \\
  1013. mkpart primary ext2 3M 1.4G \\
  1014. mkpart primary ext2 1.4G 2.8G \\
  1015. set 1 boot on \\
  1016. set 1 bios_grub on
  1017. mkfs.btrfs -L root-fs -d raid0 -m raid0 /dev/vdb2 /dev/vdb3
  1018. mount /dev/vdb2 /mnt
  1019. df -h /mnt
  1020. herd start cow-store /mnt
  1021. mkdir /mnt/etc
  1022. cp /etc/target-config.scm /mnt/etc/config.scm
  1023. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  1024. sync
  1025. reboot\n")
  1026. (define %test-btrfs-raid-root-os
  1027. (system-test
  1028. (name "btrfs-raid-root-os")
  1029. (description "Test functionality of an OS installed with a Btrfs
  1030. RAID-0 (stripe) root partition.")
  1031. (value
  1032. (mlet* %store-monad
  1033. ((image (run-install %btrfs-raid-root-os
  1034. %btrfs-raid-root-os-source
  1035. #:script %btrfs-raid-root-installation-script
  1036. #:target-size (* 2800 MiB)))
  1037. (command (qemu-command/writable-image image)))
  1038. (run-basic-test %btrfs-raid-root-os `(,@command) "btrfs-raid-root-os")))))
  1039. ;;;
  1040. ;;; Btrfs root file system on a subvolume.
  1041. ;;;
  1042. (define-os-with-source (%btrfs-root-on-subvolume-os
  1043. %btrfs-root-on-subvolume-os-source)
  1044. ;; The OS we want to install.
  1045. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  1046. (operating-system
  1047. (host-name "hurd")
  1048. (timezone "Europe/Paris")
  1049. (locale "en_US.UTF-8")
  1050. (bootloader (bootloader-configuration
  1051. (bootloader grub-bootloader)
  1052. (targets (list "/dev/vdb"))))
  1053. (kernel-arguments '("console=ttyS0"))
  1054. (file-systems (cons* (file-system
  1055. (device (file-system-label "btrfs-pool"))
  1056. (mount-point "/")
  1057. (options "subvol=rootfs,compress=zstd")
  1058. (type "btrfs"))
  1059. (file-system
  1060. (device (file-system-label "btrfs-pool"))
  1061. (mount-point "/home")
  1062. (options "subvol=homefs,compress=lzo")
  1063. (type "btrfs"))
  1064. %base-file-systems))
  1065. (users (cons (user-account
  1066. (name "charlie")
  1067. (group "users")
  1068. (supplementary-groups '("wheel" "audio" "video")))
  1069. %base-user-accounts))
  1070. (services (cons (service marionette-service-type
  1071. (marionette-configuration
  1072. (imported-modules '((gnu services herd)
  1073. (guix combinators)))))
  1074. %base-services))))
  1075. (define %btrfs-root-on-subvolume-installation-script
  1076. ;; Shell script of a simple installation.
  1077. "\
  1078. . /etc/profile
  1079. set -e -x
  1080. guix --version
  1081. export GUIX_BUILD_OPTIONS=--no-grafts
  1082. ls -l /run/current-system/gc-roots
  1083. parted --script /dev/vdb mklabel gpt \\
  1084. mkpart primary ext2 1M 3M \\
  1085. mkpart primary ext2 3M 2G \\
  1086. set 1 boot on \\
  1087. set 1 bios_grub on
  1088. # Setup the top level Btrfs file system with its subvolume.
  1089. mkfs.btrfs -L btrfs-pool /dev/vdb2
  1090. mount /dev/vdb2 /mnt
  1091. btrfs subvolume create /mnt/rootfs
  1092. btrfs subvolume create /mnt/homefs
  1093. umount /dev/vdb2
  1094. # Mount the subvolumes, ready for installation.
  1095. mount LABEL=btrfs-pool -o 'subvol=rootfs,compress=zstd' /mnt
  1096. mkdir /mnt/home
  1097. mount LABEL=btrfs-pool -o 'subvol=homefs,compress=zstd' /mnt/home
  1098. herd start cow-store /mnt
  1099. mkdir /mnt/etc
  1100. cp /etc/target-config.scm /mnt/etc/config.scm
  1101. guix system build /mnt/etc/config.scm
  1102. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  1103. sync
  1104. reboot\n")
  1105. (define %test-btrfs-root-on-subvolume-os
  1106. (system-test
  1107. (name "btrfs-root-on-subvolume-os")
  1108. (description
  1109. "Test basic functionality of an OS installed like one would do by hand.
  1110. This test is expensive in terms of CPU and storage usage since we need to
  1111. build (current-guix) and then store a couple of full system images.")
  1112. (value
  1113. (mlet* %store-monad
  1114. ((image
  1115. (run-install %btrfs-root-on-subvolume-os
  1116. %btrfs-root-on-subvolume-os-source
  1117. #:script
  1118. %btrfs-root-on-subvolume-installation-script))
  1119. (command (qemu-command/writable-image image)))
  1120. (run-basic-test %btrfs-root-on-subvolume-os command
  1121. "btrfs-root-on-subvolume-os")))))
  1122. ;;;
  1123. ;;; JFS root file system.
  1124. ;;;
  1125. (define-os-with-source (%jfs-root-os %jfs-root-os-source)
  1126. ;; The OS we want to install.
  1127. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  1128. (operating-system
  1129. (host-name "liberigilo")
  1130. (timezone "Europe/Paris")
  1131. (locale "en_US.UTF-8")
  1132. (bootloader (bootloader-configuration
  1133. (bootloader grub-bootloader)
  1134. (targets (list "/dev/vdb"))))
  1135. (kernel-arguments '("console=ttyS0"))
  1136. (file-systems (cons (file-system
  1137. (device (file-system-label "my-root"))
  1138. (mount-point "/")
  1139. (type "jfs"))
  1140. %base-file-systems))
  1141. (users (cons (user-account
  1142. (name "charlie")
  1143. (group "users")
  1144. (supplementary-groups '("wheel" "audio" "video")))
  1145. %base-user-accounts))
  1146. (services (cons (service marionette-service-type
  1147. (marionette-configuration
  1148. (imported-modules '((gnu services herd)
  1149. (guix combinators)))))
  1150. %base-services))))
  1151. (define %jfs-root-installation-script
  1152. ;; Shell script of a simple installation.
  1153. "\
  1154. . /etc/profile
  1155. set -e -x
  1156. guix --version
  1157. export GUIX_BUILD_OPTIONS=--no-grafts
  1158. ls -l /run/current-system/gc-roots
  1159. parted --script /dev/vdb mklabel gpt \\
  1160. mkpart primary ext2 1M 3M \\
  1161. mkpart primary ext2 3M 2G \\
  1162. set 1 boot on \\
  1163. set 1 bios_grub on
  1164. jfs_mkfs -L my-root -q /dev/vdb2
  1165. mount /dev/vdb2 /mnt
  1166. herd start cow-store /mnt
  1167. mkdir /mnt/etc
  1168. cp /etc/target-config.scm /mnt/etc/config.scm
  1169. guix system build /mnt/etc/config.scm
  1170. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  1171. sync
  1172. reboot\n")
  1173. (define %test-jfs-root-os
  1174. (system-test
  1175. (name "jfs-root-os")
  1176. (description
  1177. "Test basic functionality of an OS installed like one would do by hand.
  1178. This test is expensive in terms of CPU and storage usage since we need to
  1179. build (current-guix) and then store a couple of full system images.")
  1180. (value
  1181. (mlet* %store-monad ((image (run-install %jfs-root-os
  1182. %jfs-root-os-source
  1183. #:script
  1184. %jfs-root-installation-script))
  1185. (command (qemu-command/writable-image image)))
  1186. (run-basic-test %jfs-root-os command "jfs-root-os")))))
  1187. ;;;
  1188. ;;; F2FS root file system.
  1189. ;;;
  1190. (define-os-with-source (%f2fs-root-os %f2fs-root-os-source)
  1191. ;; The OS we want to install.
  1192. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  1193. (operating-system
  1194. (host-name "liberigilo")
  1195. (timezone "Europe/Paris")
  1196. (locale "en_US.UTF-8")
  1197. (bootloader (bootloader-configuration
  1198. (bootloader grub-bootloader)
  1199. (targets (list "/dev/vdb"))))
  1200. (kernel-arguments '("console=ttyS0"))
  1201. (file-systems (cons (file-system
  1202. (device (file-system-label "my-root"))
  1203. (mount-point "/")
  1204. (type "f2fs"))
  1205. %base-file-systems))
  1206. (users (cons (user-account
  1207. (name "charlie")
  1208. (group "users")
  1209. (supplementary-groups '("wheel" "audio" "video")))
  1210. %base-user-accounts))
  1211. (services (cons (service marionette-service-type
  1212. (marionette-configuration
  1213. (imported-modules '((gnu services herd)
  1214. (guix combinators)))))
  1215. %base-services))))
  1216. (define %f2fs-root-installation-script
  1217. ;; Shell script of a simple installation.
  1218. "\
  1219. . /etc/profile
  1220. set -e -x
  1221. guix --version
  1222. export GUIX_BUILD_OPTIONS=--no-grafts
  1223. ls -l /run/current-system/gc-roots
  1224. parted --script /dev/vdb mklabel gpt \\
  1225. mkpart primary ext2 1M 3M \\
  1226. mkpart primary ext2 3M 2G \\
  1227. set 1 boot on \\
  1228. set 1 bios_grub on
  1229. mkfs.f2fs -l my-root -q /dev/vdb2
  1230. mount /dev/vdb2 /mnt
  1231. herd start cow-store /mnt
  1232. mkdir /mnt/etc
  1233. cp /etc/target-config.scm /mnt/etc/config.scm
  1234. guix system build /mnt/etc/config.scm
  1235. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  1236. sync
  1237. reboot\n")
  1238. (define %test-f2fs-root-os
  1239. (system-test
  1240. (name "f2fs-root-os")
  1241. (description
  1242. "Test basic functionality of an OS installed like one would do by hand.
  1243. This test is expensive in terms of CPU and storage usage since we need to
  1244. build (current-guix) and then store a couple of full system images.")
  1245. (value
  1246. (mlet* %store-monad ((image (run-install %f2fs-root-os
  1247. %f2fs-root-os-source
  1248. #:script
  1249. %f2fs-root-installation-script))
  1250. (command (qemu-command/writable-image image)))
  1251. (run-basic-test %f2fs-root-os command "f2fs-root-os")))))
  1252. ;;;
  1253. ;;; XFS root file system.
  1254. ;;;
  1255. (define-os-with-source (%xfs-root-os %xfs-root-os-source)
  1256. ;; The OS we want to install.
  1257. (use-modules (gnu) (gnu tests) (srfi srfi-1))
  1258. (operating-system
  1259. (host-name "liberigilo")
  1260. (timezone "Europe/Paris")
  1261. (locale "en_US.UTF-8")
  1262. (bootloader (bootloader-configuration
  1263. (bootloader grub-bootloader)
  1264. (targets (list "/dev/vdb"))))
  1265. (kernel-arguments '("console=ttyS0"))
  1266. (file-systems (cons (file-system
  1267. (device (file-system-label "my-root"))
  1268. (mount-point "/")
  1269. (type "xfs"))
  1270. %base-file-systems))
  1271. (users (cons (user-account
  1272. (name "charlie")
  1273. (group "users")
  1274. (supplementary-groups '("wheel" "audio" "video")))
  1275. %base-user-accounts))
  1276. (services (cons (service marionette-service-type
  1277. (marionette-configuration
  1278. (imported-modules '((gnu services herd)
  1279. (guix combinators)))))
  1280. %base-services))))
  1281. (define %xfs-root-installation-script
  1282. ;; Shell script of a simple installation.
  1283. "\
  1284. . /etc/profile
  1285. set -e -x
  1286. guix --version
  1287. export GUIX_BUILD_OPTIONS=--no-grafts
  1288. ls -l /run/current-system/gc-roots
  1289. parted --script /dev/vdb mklabel gpt \\
  1290. mkpart primary ext2 1M 3M \\
  1291. mkpart primary ext2 3M 2G \\
  1292. set 1 boot on \\
  1293. set 1 bios_grub on
  1294. mkfs.xfs -L my-root -q /dev/vdb2
  1295. mount /dev/vdb2 /mnt
  1296. herd start cow-store /mnt
  1297. mkdir /mnt/etc
  1298. cp /etc/target-config.scm /mnt/etc/config.scm
  1299. guix system build /mnt/etc/config.scm
  1300. guix system init /mnt/etc/config.scm /mnt --no-substitutes
  1301. sync
  1302. reboot\n")
  1303. (define %test-xfs-root-os
  1304. (system-test
  1305. (name "xfs-root-os")
  1306. (description
  1307. "Test basic functionality of an OS installed like one would do by hand.
  1308. This test is expensive in terms of CPU and storage usage since we need to
  1309. build (current-guix) and then store a couple of full system images.")
  1310. (value
  1311. (mlet* %store-monad ((image (run-install %xfs-root-os
  1312. %xfs-root-os-source
  1313. #:script
  1314. %xfs-root-installation-script))
  1315. (command (qemu-command/writable-image image)))
  1316. (run-basic-test %xfs-root-os command "xfs-root-os")))))
  1317. ;;;
  1318. ;;; Installation through the graphical interface.
  1319. ;;;
  1320. (define %syslog-conf
  1321. ;; Syslog configuration that dumps to /dev/console, so we can see the
  1322. ;; installer's messages during the test.
  1323. (computed-file "syslog.conf"
  1324. #~(begin
  1325. (copy-file #$%default-syslog.conf #$output)
  1326. (chmod #$output #o644)
  1327. (let ((port (open-file #$output "a")))
  1328. (display "\n*.info /dev/console\n" port)
  1329. #t))))
  1330. (define (operating-system-with-console-syslog os)
  1331. "Return OS with a syslog service that writes to /dev/console."
  1332. (operating-system
  1333. (inherit os)
  1334. (services (modify-services (operating-system-user-services os)
  1335. (syslog-service-type config
  1336. =>
  1337. (syslog-configuration
  1338. (inherit config)
  1339. (config-file %syslog-conf)))))))
  1340. (define %root-password "foo")
  1341. (define* (gui-test-program marionette
  1342. #:key
  1343. (desktop? #f)
  1344. (encrypted? #f)
  1345. (uefi-support? #f)
  1346. (system (%current-system)))
  1347. #~(let ()
  1348. (define (screenshot file)
  1349. (marionette-control (string-append "screendump " file)
  1350. #$marionette))
  1351. (define-syntax-rule (marionette-eval* exp marionette)
  1352. (or (marionette-eval exp marionette)
  1353. (throw 'marionette-eval-failure 'exp)))
  1354. (setvbuf (current-output-port) 'none)
  1355. (setvbuf (current-error-port) 'none)
  1356. (marionette-eval* '(use-modules (gnu installer tests))
  1357. #$marionette)
  1358. ;; Arrange so that 'converse' prints debugging output to the console.
  1359. (marionette-eval* '(let ((console (open-output-file "/dev/console")))
  1360. (setvbuf console 'none)
  1361. (conversation-log-port console))
  1362. #$marionette)
  1363. ;; Tell the installer to not wait for the Connman "online" status.
  1364. (marionette-eval* '(call-with-output-file "/tmp/installer-assume-online"
  1365. (const #t))
  1366. #$marionette)
  1367. ;; Run 'guix system init' with '--no-grafts', to cope with the lack of
  1368. ;; network access.
  1369. (marionette-eval* '(call-with-output-file
  1370. "/tmp/installer-system-init-options"
  1371. (lambda (port)
  1372. (write '("--no-grafts" "--no-substitutes")
  1373. port)))
  1374. #$marionette)
  1375. (marionette-eval* '(define installer-socket
  1376. (open-installer-socket))
  1377. #$marionette)
  1378. (screenshot "installer-start.ppm")
  1379. (marionette-eval* '(choose-locale+keyboard installer-socket)
  1380. #$marionette)
  1381. (screenshot "installer-locale.ppm")
  1382. ;; Choose the host name that the "basic" test expects.
  1383. (marionette-eval* '(enter-host-name+passwords installer-socket
  1384. #:host-name "liberigilo"
  1385. #:root-password
  1386. #$%root-password
  1387. #:users
  1388. '(("alice" "pass1")
  1389. ("bob" "pass2")))
  1390. #$marionette)
  1391. (screenshot "installer-services.ppm")
  1392. (marionette-eval* '(choose-services installer-socket
  1393. #:choose-desktop-environment?
  1394. (const #$desktop?)
  1395. #:choose-network-service?
  1396. (const #f))
  1397. #$marionette)
  1398. (screenshot "installer-partitioning.ppm")
  1399. (marionette-eval* '(choose-partitioning installer-socket
  1400. #:encrypted? #$encrypted?
  1401. #:passphrase #$%luks-passphrase
  1402. #:uefi-support? #$uefi-support?)
  1403. #$marionette)
  1404. (screenshot "installer-run.ppm")
  1405. (unless #$encrypted?
  1406. ;; At this point, user partitions are formatted and the installer is
  1407. ;; waiting for us to start the final step: generating the
  1408. ;; configuration file, etc. Set a fixed UUID on the swap partition
  1409. ;; that matches what 'installation-target-os-for-gui-tests' expects.
  1410. (marionette-eval* '(invoke #$(file-append util-linux "/sbin/swaplabel")
  1411. "-U" "11111111-2222-3333-4444-123456789abc"
  1412. "/dev/vda2")
  1413. #$marionette))
  1414. (marionette-eval* '(start-installation installer-socket)
  1415. #$marionette)
  1416. ;; XXX: The grub-install process uses efibootmgr to add an UEFI Guix
  1417. ;; boot entry. The corresponding UEFI variable is stored in RAM, and
  1418. ;; possibly saved persistently on QEMU reboot in a NvVars file, see:
  1419. ;; https://lists.gnu.org/archive/html/qemu-discuss/2018-04/msg00045.html.
  1420. ;;
  1421. ;; As we are running QEMU with the no-reboot flag, this variable is
  1422. ;; never saved persistently, QEMU fails to boot the installed system and
  1423. ;; an UEFI shell is displayed instead.
  1424. ;;
  1425. ;; To make the installed UEFI system bootable, register Grub as the
  1426. ;; default UEFI boot entry, in the same way as if grub-install was
  1427. ;; invoked with the --removable option.
  1428. (when #$uefi-support?
  1429. (marionette-eval*
  1430. '(begin
  1431. (use-modules (ice-9 match))
  1432. (let ((targets (cond
  1433. ((string-prefix? "x86_64" #$system)
  1434. '("grubx64.efi" "BOOTX64.EFI"))
  1435. ((string-prefix? "i686" #$system)
  1436. '("grubia32.efi" "BOOTIA32.EFI"))
  1437. (else #f))))
  1438. (match targets
  1439. ((src dest)
  1440. (rename-file "/mnt/boot/efi/EFI/Guix"
  1441. "/mnt/boot/efi/EFI/BOOT")
  1442. (rename-file
  1443. (string-append "/mnt/boot/efi/EFI/BOOT/" src)
  1444. (string-append "/mnt/boot/efi/EFI/BOOT/" dest)))
  1445. (_ #f))))
  1446. #$marionette))
  1447. (marionette-eval* '(complete-installation installer-socket)
  1448. #$marionette)
  1449. (sync)
  1450. #t))
  1451. (define %extra-packages
  1452. ;; Packages needed when installing with an encrypted root.
  1453. (list isc-dhcp
  1454. lvm2-static cryptsetup-static e2fsck/static
  1455. loadkeys-static grub-efi fatfsck/static dosfstools))
  1456. (define installation-os-for-gui-tests
  1457. ;; Operating system that contains all of %EXTRA-PACKAGES, needed for the
  1458. ;; target OS, as well as syslog output redirected to the console so we can
  1459. ;; see what the installer is up to.
  1460. (marionette-operating-system
  1461. (operating-system
  1462. (inherit (operating-system-with-console-syslog
  1463. (operating-system-add-packages
  1464. (operating-system-with-current-guix
  1465. installation-os)
  1466. %extra-packages)))
  1467. (kernel-arguments '("console=ttyS0")))
  1468. #:imported-modules '((gnu services herd)
  1469. (gnu installer tests)
  1470. (guix combinators))))
  1471. (define* (installation-target-os-for-gui-tests
  1472. #:key
  1473. (encrypted? #f)
  1474. (uefi-support? #f))
  1475. (operating-system
  1476. (inherit %minimal-os-on-vda)
  1477. (file-systems `(,(file-system
  1478. (device (file-system-label "my-root"))
  1479. (mount-point "/")
  1480. (type "ext4"))
  1481. ,@(if uefi-support?
  1482. (list (file-system
  1483. (device (uuid "1234-ABCD" 'fat))
  1484. (mount-point "/boot/efi")
  1485. (type "vfat")))
  1486. '())
  1487. ,@%base-file-systems))
  1488. (users (append (list (user-account
  1489. (name "alice")
  1490. (comment "Bob's sister")
  1491. (group "users")
  1492. (supplementary-groups
  1493. '("wheel" "audio" "video")))
  1494. (user-account
  1495. (name "bob")
  1496. (comment "Alice's brother")
  1497. (group "users")
  1498. (supplementary-groups
  1499. '("wheel" "audio" "video"))))
  1500. %base-user-accounts))
  1501. ;; The installer does not create a swap device in guided mode with
  1502. ;; encryption support. The installer produces a UUID for the partition;
  1503. ;; this "UUID" is explicitly set in 'gui-test-program' to the value shown
  1504. ;; below.
  1505. (swap-devices
  1506. (if encrypted?
  1507. '()
  1508. (list
  1509. (swap-space
  1510. (target (uuid "11111111-2222-3333-4444-123456789abc"))))))
  1511. (services (cons* (service dhcp-client-service-type)
  1512. (service ntp-service-type)
  1513. (operating-system-user-services %minimal-os-on-vda)))))
  1514. (define* (installation-target-desktop-os-for-gui-tests
  1515. #:key (encrypted? #f))
  1516. (operating-system
  1517. (inherit (installation-target-os-for-gui-tests
  1518. #:encrypted? encrypted?))
  1519. (keyboard-layout (keyboard-layout "us" "altgr-intl"))
  1520. ;; Make sure that all the packages and services that may be used by the
  1521. ;; graphical installer are available.
  1522. (packages (append
  1523. (list openbox awesome i3-wm i3status
  1524. dmenu st ratpoison xterm
  1525. emacs emacs-exwm emacs-desktop-environment)
  1526. %base-packages))
  1527. (services
  1528. (append
  1529. (list (service gnome-desktop-service-type)
  1530. (service xfce-desktop-service-type)
  1531. (service mate-desktop-service-type)
  1532. (service enlightenment-desktop-service-type)
  1533. (set-xorg-configuration
  1534. (xorg-configuration
  1535. (keyboard-layout keyboard-layout)))
  1536. (service marionette-service-type
  1537. (marionette-configuration
  1538. (imported-modules '((gnu services herd)
  1539. (guix build utils)
  1540. (guix combinators))))))
  1541. %desktop-services))))
  1542. (define* (guided-installation-test name
  1543. #:key
  1544. (desktop? #f)
  1545. (encrypted? #f)
  1546. (uefi-support? #f)
  1547. target-os
  1548. (install-size 'guess)
  1549. (target-size (* 2200 MiB)))
  1550. (system-test
  1551. (name name)
  1552. (description
  1553. "Install an OS using the graphical installer and test it.")
  1554. (value
  1555. (mlet* %store-monad
  1556. ((image (run-install target-os '(this is unused)
  1557. #:script #f
  1558. #:os installation-os-for-gui-tests
  1559. #:uefi-support? uefi-support?
  1560. #:install-size install-size
  1561. #:target-size target-size
  1562. #:installation-image-type
  1563. 'uncompressed-iso9660
  1564. #:gui-test
  1565. (lambda (marionette)
  1566. (gui-test-program
  1567. marionette
  1568. #:desktop? desktop?
  1569. #:encrypted? encrypted?
  1570. #:uefi-support? uefi-support?))))
  1571. (command (qemu-command/writable-image image
  1572. #:uefi-support? uefi-support?
  1573. #:memory-size 512)))
  1574. (run-basic-test target-os command name
  1575. #:initialization (and encrypted? enter-luks-passphrase)
  1576. #:root-password %root-password
  1577. #:desktop? desktop?)))))
  1578. (define %test-gui-installed-os
  1579. (guided-installation-test
  1580. "gui-installed-os"
  1581. #:target-os (installation-target-os-for-gui-tests)))
  1582. ;; Test the UEFI installation of Guix System using the graphical installer.
  1583. (define %test-gui-uefi-installed-os
  1584. (guided-installation-test
  1585. "gui-uefi-installed-os"
  1586. #:uefi-support? #t
  1587. #:target-os (installation-target-os-for-gui-tests
  1588. #:uefi-support? #t)
  1589. #:target-size (* 3200 MiB)))
  1590. (define %test-gui-installed-os-encrypted
  1591. (guided-installation-test
  1592. "gui-installed-os-encrypted"
  1593. #:encrypted? #t
  1594. #:target-os (installation-target-os-for-gui-tests
  1595. #:encrypted? #t)))
  1596. ;; Building a desktop image is very time and space consuming. Install all
  1597. ;; desktop environments in a single test to reduce the overhead.
  1598. (define %test-gui-installed-desktop-os-encrypted
  1599. (guided-installation-test "gui-installed-desktop-os-encrypted"
  1600. #:desktop? #t
  1601. #:encrypted? #t
  1602. #:target-os
  1603. (installation-target-desktop-os-for-gui-tests
  1604. #:encrypted? #t)
  1605. ;; XXX: The disk-image size guess is too low. Use
  1606. ;; a constant value until this is fixed.
  1607. #:install-size (* 8000 MiB)
  1608. #:target-size (* 9000 MiB)))
  1609. ;;; install.scm ends here