1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2020, 2021 Marius Bakke <marius@gnu.org>
3 ;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
5 ;;; This file is part of GNU Guix.
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;;; GNU General Public License for more details.
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20 (define-module (gnu tests ganeti)
22 #:use-module (gnu tests)
23 #:use-module (gnu system vm)
24 #:use-module (gnu services)
25 #:use-module (gnu services ganeti)
26 #:use-module (gnu services networking)
27 #:use-module (gnu services ssh)
28 #:use-module (gnu packages virtualization)
29 #:use-module (guix gexp)
30 #:use-module (ice-9 format)
31 #:export (%test-ganeti-kvm %test-ganeti-lxc))
37 (locale "en_US.UTF-8")
39 (bootloader (bootloader-configuration
40 (bootloader grub-bootloader)
41 (targets '("/dev/vda"))))
42 (file-systems (cons (file-system
43 (device (file-system-label "my-root"))
49 ;; The hosts file must contain a nonlocal IP for host-name.
50 ;; In addition, the cluster name must resolve to an IP address that
51 ;; is not currently provisioned.
52 (hosts-file (plain-file "hosts" (format #f "
55 10.0.2.15 gnt1.example.com gnt1
56 192.168.254.254 ganeti.example.com
59 (packages (append (list ganeti-instance-debootstrap ganeti-instance-guix)
62 (append (list (service static-networking-service-type
63 (list %qemu-static-networking))
64 (service openssh-service-type
65 (openssh-configuration
66 (permit-root-login 'prohibit-password)))
68 (service ganeti-service-type
70 (file-storage-paths '("/srv/ganeti/file-storage"))
72 (ganeti-rapi-configuration
73 ;; Disable TLS so we can test the RAPI without
76 (os %default-ganeti-os))))
79 (define* (run-ganeti-test hypervisor #:key
80 (master-netdev "eth0")
84 "Run tests in %GANETI-OS."
86 (marionette-operating-system
89 (packages (append extra-packages
90 (operating-system-packages %ganeti-os))))
91 #:imported-modules '((gnu services herd)
94 (define %forwarded-rapi-port 5080)
99 ;; Some of the daemons are fairly memory-hungry.
101 ;; Forward HTTP ports so we can access them from the "outside".
102 (port-forwardings `((,%forwarded-rapi-port . ,rapi-port)))))
105 (with-imported-modules '((gnu build marionette))
107 (use-modules (srfi srfi-11) (srfi srfi-64)
108 (web uri) (web client) (web response)
110 (gnu build marionette))
113 (make-marionette (list #$vm)))
115 (test-runner-current (system-test-runner #$output))
116 (test-begin "ganeti")
118 ;; Ganeti uses the Shepherd to start/stop daemons, so make sure
119 ;; it is ready before we begin. It takes a while because all
120 ;; Ganeti daemons fail to start initially.
121 (test-assert "shepherd is ready"
122 (wait-for-unix-socket "/var/run/shepherd/socket" marionette))
124 (test-eq "gnt-cluster init"
130 ;; Init needs to run 'ssh-keygen', 'ip', etc.
131 "/run/current-system/profile/sbin:/run/current-system/profile/bin")
132 (system* #$(file-append ganeti "/sbin/gnt-cluster") "init"
133 (string-append "--master-netdev=" #$master-netdev)
134 ;; TODO: Enable more disk backends.
135 "--enabled-disk-templates=file"
136 (string-append "--enabled-hypervisors="
138 (string-append "--hypervisor-parameters="
140 (string-join '#$hvparams "\n"))
141 ;; Set the default NIC mode to 'routed' to avoid having to
142 ;; configure a full bridge to placate 'gnt-cluster verify'.
143 "--nic-parameters=mode=routed,link=eth0"
144 "ganeti.example.com"))
147 ;; Disable the watcher while doing daemon tests to prevent interference.
148 (test-eq "watcher pause"
152 (system* #$(file-append ganeti "/sbin/gnt-cluster")
153 "watcher" "pause" "1h"))
156 (test-assert "force-start wconfd"
157 ;; Check that the 'force-start' Shepherd action works, used in a
158 ;; master-failover scenario.
161 (setenv "PATH" "/run/current-system/profile/bin")
162 (invoke "herd" "stop" "ganeti-wconfd")
163 (invoke "herd" "disable" "ganeti-wconfd")
164 (invoke "herd" "force-start" "ganeti-wconfd"))
167 ;; Verify that the cluster is healthy.
168 (test-eq "gnt-cluster verify 1"
172 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
175 ;; Try stopping and starting daemons with daemon-util like
176 ;; 'gnt-node add', 'gnt-cluster init', etc.
177 (test-eq "daemon-util stop-all"
181 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
185 (test-eq "daemon-util start-all"
189 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
193 ;; Check that the cluster is still healthy after the daemon restarts.
194 (test-eq "gnt-cluster verify 2"
198 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
201 (test-eq "watcher continue"
205 (system* #$(file-append ganeti "/sbin/gnt-cluster")
206 "watcher" "continue"))
209 ;; Try accessing the RAPI.
210 (test-equal "http-get RAPI version"
214 (http-get #$(simple-format
215 #f "http://localhost:~A/version"
216 %forwarded-rapi-port)
218 (list (response-code response)
219 ;; The API response lacks a content-type, so
220 ;; (http-client) won't decode it for us.
221 (bytevector->string text "UTF-8"))))
223 (test-equal "gnt-os list"
224 "debootstrap+default\nguix+default\n"
227 (use-modules (ice-9 popen))
228 (let* ((port (open-pipe*
230 #$(file-append ganeti "/sbin/gnt-os")
231 "list" "--no-headers"))
232 (output (get-string-all port)))
237 (test-eq "gnt-cluster destroy"
241 (system* #$(file-append ganeti "/sbin/gnt-cluster")
242 "destroy" "--yes-do-it"))
247 (gexp->derivation (string-append "ganeti-" hypervisor "-test") test))
249 (define %test-ganeti-kvm
252 (description "Provision a Ganeti cluster using the KVM hypervisor.")
253 (value (run-ganeti-test "kvm"
254 ;; Set kernel_path to an empty string to prevent
255 ;; 'gnt-cluster verify' from testing for its presence.
256 #:hvparams '("kernel_path=")
257 #:extra-packages (list qemu)))))
259 (define %test-ganeti-lxc
262 (description "Provision a Ganeti cluster using LXC as the hypervisor.")
263 (value (run-ganeti-test "lxc"
264 #:extra-packages (list lxc)))))