install.scm 64 KB

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