Merge branch 'master' into staging
[jackhill/guix/guix.git] / gnu / tests / ganeti.scm
CommitLineData
9a622827
MB
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2020 Marius Bakke <marius@gnu.org>.
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (gnu tests ganeti)
20 #:use-module (gnu)
21 #:use-module (gnu tests)
22 #:use-module (gnu system vm)
23 #:use-module (gnu services)
24 #:use-module (gnu services ganeti)
25 #:use-module (gnu services networking)
26 #:use-module (gnu services ssh)
27 #:use-module (gnu packages virtualization)
28 #:use-module (guix gexp)
29 #:use-module (ice-9 format)
30 #:export (%test-ganeti-kvm %test-ganeti-lxc))
31
32(define %ganeti-os
33 (operating-system
34 (host-name "gnt1")
35 (timezone "Etc/UTC")
36 (locale "en_US.UTF-8")
37
38 (bootloader (bootloader-configuration
39 (bootloader grub-bootloader)
40 (target "/dev/vda")))
41 (file-systems (cons (file-system
42 (device (file-system-label "my-root"))
43 (mount-point "/")
44 (type "ext4"))
45 %base-file-systems))
46 (firmware '())
47
48 ;; The hosts file must contain a nonlocal IP for host-name.
49 ;; In addition, the cluster name must resolve to an IP address that
50 ;; is not currently provisioned.
51 (hosts-file (plain-file "hosts" (format #f "
52127.0.0.1 localhost
53::1 localhost
5410.0.2.2 gnt1.example.com gnt1
55192.168.254.254 ganeti.example.com
56")))
57
58 (packages (append (list ganeti-instance-debootstrap ganeti-instance-guix)
59 %base-packages))
60 (services
61 (append (list (static-networking-service "eth0" "10.0.2.2"
62 #:netmask "255.255.255.0"
63 #:gateway "10.0.2.1"
64 #:name-servers '("10.0.2.1"))
65
66 (service openssh-service-type
67 (openssh-configuration
68 (permit-root-login 'without-password)))
69
70 (service ganeti-service-type
71 (ganeti-configuration
72 (file-storage-paths '("/srv/ganeti/file-storage"))
41daf128
MB
73 (rapi-configuration
74 (ganeti-rapi-configuration
75 ;; Disable TLS so we can test the RAPI without
76 ;; pulling in GnuTLS.
77 (ssl? #f)))
9a622827
MB
78 (os %default-ganeti-os))))
79 %base-services))))
80
81(define* (run-ganeti-test hypervisor #:key
82 (master-netdev "eth0")
83 (hvparams '())
84 (extra-packages '())
85 (rapi-port 5080)
86 (noded-port 1811))
87 "Run tests in %GANETI-OS."
88 (define os
89 (marionette-operating-system
90 (operating-system
91 (inherit %ganeti-os)
92 (packages (append extra-packages
93 (operating-system-packages %ganeti-os))))
94 #:imported-modules '((gnu services herd)
95 (guix combinators))))
96
97 (define %forwarded-rapi-port 5080)
98 (define %forwarded-noded-port 1811)
99
100 (define vm
101 (virtual-machine
102 (operating-system os)
103 ;; Some of the daemons are fairly memory-hungry.
104 (memory-size 512)
105 ;; Forward HTTP ports so we can access them from the "outside".
106 (port-forwardings `((,%forwarded-rapi-port . ,rapi-port)
107 (,%forwarded-noded-port . ,noded-port)))))
108
109 (define test
110 (with-imported-modules '((gnu build marionette))
111 #~(begin
112 (use-modules (srfi srfi-11) (srfi srfi-64)
113 (web uri) (web client) (web response)
114 (gnu build marionette))
115
116 (define marionette
117 (make-marionette (list #$vm)))
118
119 (mkdir #$output)
120 (chdir #$output)
121
122 (test-begin "ganeti")
123
124 ;; Ganeti uses the Shepherd to start/stop daemons, so make sure
125 ;; it is ready before we begin. It takes a while because all
126 ;; Ganeti daemons fail to start initially.
127 (test-assert "shepherd is ready"
128 (wait-for-unix-socket "/var/run/shepherd/socket" marionette))
129
130 (test-eq "gnt-cluster init"
131 0
132 (marionette-eval
133 '(begin
134 (setenv
135 "PATH"
136 ;; Init needs to run 'ssh-keygen', 'ip', etc.
137 "/run/current-system/profile/sbin:/run/current-system/profile/bin")
138 (system* #$(file-append ganeti "/sbin/gnt-cluster") "init"
139 (string-append "--master-netdev=" #$master-netdev)
140 ;; TODO: Enable more disk backends.
141 "--enabled-disk-templates=file"
142 (string-append "--enabled-hypervisors="
143 #$hypervisor)
144 (string-append "--hypervisor-parameters="
145 #$hypervisor ":"
146 (string-join '#$hvparams "\n"))
147 ;; Set the default NIC mode to 'routed' to avoid having to
148 ;; configure a full bridge to placate 'gnt-cluster verify'.
149 "--nic-parameters=mode=routed,link=eth0"
150 "ganeti.example.com"))
151 marionette))
152
153 ;; Disable the watcher while doing daemon tests to prevent interference.
154 (test-eq "watcher pause"
155 0
156 (marionette-eval
157 '(begin
158 (system* #$(file-append ganeti "/sbin/gnt-cluster")
159 "watcher" "pause" "1h"))
160 marionette))
161
162 (test-assert "force-start wconfd"
163 ;; Check that the 'force-start' Shepherd action works, used in a
164 ;; master-failover scenario.
165 (marionette-eval
166 '(begin
167 (setenv "PATH" "/run/current-system/profile/bin")
168 (invoke "herd" "stop" "ganeti-wconfd")
169 (invoke "herd" "disable" "ganeti-wconfd")
170 (invoke "herd" "force-start" "ganeti-wconfd"))
171 marionette))
172
173 ;; Verify that the cluster is healthy.
174 (test-eq "gnt-cluster verify 1"
175 0
176 (marionette-eval
177 '(begin
178 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
179 marionette))
180
181 ;; Try stopping and starting daemons with daemon-util like
182 ;; 'gnt-node add', 'gnt-cluster init', etc.
183 (test-eq "daemon-util stop-all"
184 0
185 (marionette-eval
186 '(begin
187 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
188 "stop-all"))
189 marionette))
190
191 (test-eq "daemon-util start-all"
192 0
193 (marionette-eval
194 '(begin
195 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
196 "start-all"))
197 marionette))
198
199 ;; Check that the cluster is still healthy after the daemon restarts.
200 (test-eq "gnt-cluster verify 2"
201 0
202 (marionette-eval
203 '(begin
204 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
205 marionette))
206
207 (test-eq "watcher continue"
208 0
209 (marionette-eval
210 '(begin
211 (system* #$(file-append ganeti "/sbin/gnt-cluster")
212 "watcher" "continue"))
213 marionette))
214
215 ;; Try accessing the RAPI. This causes an expected failure:
216 ;; https://github.com/ganeti/ganeti/issues/1502
217 ;; Run it anyway for easy testing of potential fixes.
218 (test-equal "http-get RAPI version"
219 '(200 "2")
220 (let-values
221 (((response text)
222 (http-get #$(simple-format
223 #f "http://localhost:~A/version"
224 %forwarded-rapi-port)
225 #:decode-body? #t)))
226 (list (response-code response) text)))
227
228 (test-equal "gnt-os list"
229 "debootstrap+default\nguix+default\n"
230 (marionette-eval
231 '(begin
232 (use-modules (ice-9 popen))
233 (let* ((port (open-pipe*
234 OPEN_READ
235 #$(file-append ganeti "/sbin/gnt-os")
236 "list" "--no-headers"))
237 (output (get-string-all port)))
238 (close-pipe port)
239 output))
240 marionette))
241
242 (test-eq "gnt-cluster destroy"
243 0
244 (marionette-eval
245 '(begin
246 (system* #$(file-append ganeti "/sbin/gnt-cluster")
247 "destroy" "--yes-do-it"))
248 marionette))
249
250 (test-end)
251 (exit (= (test-runner-fail-count (test-runner-current)) 1)))))
252
253 (gexp->derivation (string-append "ganeti-" hypervisor "-test") test))
254
255(define %test-ganeti-kvm
256 (system-test
257 (name "ganeti-kvm")
258 (description "Provision a Ganeti cluster using the KVM hypervisor.")
259 (value (run-ganeti-test "kvm"
260 ;; Set kernel_path to an empty string to prevent
261 ;; 'gnt-cluster verify' from testing for its presence.
262 #:hvparams '("kernel_path=")
263 #:extra-packages (list qemu)))))
264
265(define %test-ganeti-lxc
266 (system-test
267 (name "ganeti-lxc")
268 (description "Provision a Ganeti cluster using LXC as the hypervisor.")
269 (value (run-ganeti-test "lxc"
270 #:extra-packages (list lxc)))))