gnu: ardour: Update to 7.0
[jackhill/guix/guix.git] / gnu / tests / ganeti.scm
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>
4 ;;;
5 ;;; This file is part of GNU Guix.
6 ;;;
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
11 ;;;
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;;; GNU General Public License for more details.
16 ;;;
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
20 (define-module (gnu tests ganeti)
21 #:use-module (gnu)
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))
32
33 (define %ganeti-os
34 (operating-system
35 (host-name "gnt1")
36 (timezone "Etc/UTC")
37 (locale "en_US.UTF-8")
38
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"))
44 (mount-point "/")
45 (type "ext4"))
46 %base-file-systems))
47 (firmware '())
48
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 "
53 127.0.0.1 localhost
54 ::1 localhost
55 10.0.2.15 gnt1.example.com gnt1
56 192.168.254.254 ganeti.example.com
57 ")))
58
59 (packages (append (list ganeti-instance-debootstrap ganeti-instance-guix)
60 %base-packages))
61 (services
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)))
67
68 (service ganeti-service-type
69 (ganeti-configuration
70 (file-storage-paths '("/srv/ganeti/file-storage"))
71 (rapi-configuration
72 (ganeti-rapi-configuration
73 ;; Disable TLS so we can test the RAPI without
74 ;; pulling in GnuTLS.
75 (ssl? #f)))
76 (os %default-ganeti-os))))
77 %base-services))))
78
79 (define* (run-ganeti-test hypervisor #:key
80 (master-netdev "eth0")
81 (hvparams '())
82 (extra-packages '())
83 (rapi-port 5080))
84 "Run tests in %GANETI-OS."
85 (define os
86 (marionette-operating-system
87 (operating-system
88 (inherit %ganeti-os)
89 (packages (append extra-packages
90 (operating-system-packages %ganeti-os))))
91 #:imported-modules '((gnu services herd)
92 (guix combinators))))
93
94 (define %forwarded-rapi-port 5080)
95
96 (define vm
97 (virtual-machine
98 (operating-system os)
99 ;; Some of the daemons are fairly memory-hungry.
100 (memory-size 512)
101 ;; Forward HTTP ports so we can access them from the "outside".
102 (port-forwardings `((,%forwarded-rapi-port . ,rapi-port)))))
103
104 (define test
105 (with-imported-modules '((gnu build marionette))
106 #~(begin
107 (use-modules (srfi srfi-11) (srfi srfi-64)
108 (web uri) (web client) (web response)
109 (ice-9 iconv)
110 (gnu build marionette))
111
112 (define marionette
113 (make-marionette (list #$vm)))
114
115 (test-runner-current (system-test-runner #$output))
116 (test-begin "ganeti")
117
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))
123
124 (test-eq "gnt-cluster init"
125 0
126 (marionette-eval
127 '(begin
128 (setenv
129 "PATH"
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="
137 #$hypervisor)
138 (string-append "--hypervisor-parameters="
139 #$hypervisor ":"
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"))
145 marionette))
146
147 ;; Disable the watcher while doing daemon tests to prevent interference.
148 (test-eq "watcher pause"
149 0
150 (marionette-eval
151 '(begin
152 (system* #$(file-append ganeti "/sbin/gnt-cluster")
153 "watcher" "pause" "1h"))
154 marionette))
155
156 (test-assert "force-start wconfd"
157 ;; Check that the 'force-start' Shepherd action works, used in a
158 ;; master-failover scenario.
159 (marionette-eval
160 '(begin
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"))
165 marionette))
166
167 ;; Verify that the cluster is healthy.
168 (test-eq "gnt-cluster verify 1"
169 0
170 (marionette-eval
171 '(begin
172 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
173 marionette))
174
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"
178 0
179 (marionette-eval
180 '(begin
181 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
182 "stop-all"))
183 marionette))
184
185 (test-eq "daemon-util start-all"
186 0
187 (marionette-eval
188 '(begin
189 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
190 "start-all"))
191 marionette))
192
193 ;; Check that the cluster is still healthy after the daemon restarts.
194 (test-eq "gnt-cluster verify 2"
195 0
196 (marionette-eval
197 '(begin
198 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
199 marionette))
200
201 (test-eq "watcher continue"
202 0
203 (marionette-eval
204 '(begin
205 (system* #$(file-append ganeti "/sbin/gnt-cluster")
206 "watcher" "continue"))
207 marionette))
208
209 ;; Try accessing the RAPI.
210 (test-equal "http-get RAPI version"
211 '(200 "2\n")
212 (let-values
213 (((response text)
214 (http-get #$(simple-format
215 #f "http://localhost:~A/version"
216 %forwarded-rapi-port)
217 #:decode-body? #f)))
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"))))
222
223 (test-equal "gnt-os list"
224 "debootstrap+default\nguix+default\n"
225 (marionette-eval
226 '(begin
227 (use-modules (ice-9 popen))
228 (let* ((port (open-pipe*
229 OPEN_READ
230 #$(file-append ganeti "/sbin/gnt-os")
231 "list" "--no-headers"))
232 (output (get-string-all port)))
233 (close-pipe port)
234 output))
235 marionette))
236
237 (test-eq "gnt-cluster destroy"
238 0
239 (marionette-eval
240 '(begin
241 (system* #$(file-append ganeti "/sbin/gnt-cluster")
242 "destroy" "--yes-do-it"))
243 marionette))
244
245 (test-end))))
246
247 (gexp->derivation (string-append "ganeti-" hypervisor "-test") test))
248
249 (define %test-ganeti-kvm
250 (system-test
251 (name "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)))))
258
259 (define %test-ganeti-lxc
260 (system-test
261 (name "ganeti-lxc")
262 (description "Provision a Ganeti cluster using LXC as the hypervisor.")
263 (value (run-ganeti-test "lxc"
264 #:extra-packages (list lxc)))))