1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2020 Marius Bakke <marius@gnu.org>.
4 ;;; This file is part of GNU Guix.
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.
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.
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/>.
19 (define-module (gnu tests ganeti)
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))
36 (locale "en_US.UTF-8")
38 (bootloader (bootloader-configuration
39 (bootloader grub-bootloader)
41 (file-systems (cons (file-system
42 (device (file-system-label "my-root"))
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 "
54 10.0.2.2 gnt1.example.com gnt1
55 192.168.254.254 ganeti.example.com
58 (packages (append (list ganeti-instance-debootstrap ganeti-instance-guix)
61 (append (list (static-networking-service "eth0" "10.0.2.2"
62 #:netmask "255.255.255.0"
64 #:name-servers '("10.0.2.1"))
66 (service openssh-service-type
67 (openssh-configuration
68 (permit-root-login 'without-password)))
70 (service ganeti-service-type
72 (file-storage-paths '("/srv/ganeti/file-storage"))
74 (ganeti-rapi-configuration
75 ;; Disable TLS so we can test the RAPI without
78 (os %default-ganeti-os))))
81 (define* (run-ganeti-test hypervisor #:key
82 (master-netdev "eth0")
87 "Run tests in %GANETI-OS."
89 (marionette-operating-system
92 (packages (append extra-packages
93 (operating-system-packages %ganeti-os))))
94 #:imported-modules '((gnu services herd)
97 (define %forwarded-rapi-port 5080)
98 (define %forwarded-noded-port 1811)
102 (operating-system os)
103 ;; Some of the daemons are fairly memory-hungry.
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)))))
110 (with-imported-modules '((gnu build marionette))
112 (use-modules (srfi srfi-11) (srfi srfi-64)
113 (web uri) (web client) (web response)
114 (gnu build marionette))
117 (make-marionette (list #$vm)))
122 (test-begin "ganeti")
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))
130 (test-eq "gnt-cluster init"
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="
144 (string-append "--hypervisor-parameters="
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"))
153 ;; Disable the watcher while doing daemon tests to prevent interference.
154 (test-eq "watcher pause"
158 (system* #$(file-append ganeti "/sbin/gnt-cluster")
159 "watcher" "pause" "1h"))
162 (test-assert "force-start wconfd"
163 ;; Check that the 'force-start' Shepherd action works, used in a
164 ;; master-failover scenario.
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"))
173 ;; Verify that the cluster is healthy.
174 (test-eq "gnt-cluster verify 1"
178 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
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"
187 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
191 (test-eq "daemon-util start-all"
195 (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
199 ;; Check that the cluster is still healthy after the daemon restarts.
200 (test-eq "gnt-cluster verify 2"
204 (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
207 (test-eq "watcher continue"
211 (system* #$(file-append ganeti "/sbin/gnt-cluster")
212 "watcher" "continue"))
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"
222 (http-get #$(simple-format
223 #f "http://localhost:~A/version"
224 %forwarded-rapi-port)
226 (list (response-code response) text)))
228 (test-equal "gnt-os list"
229 "debootstrap+default\nguix+default\n"
232 (use-modules (ice-9 popen))
233 (let* ((port (open-pipe*
235 #$(file-append ganeti "/sbin/gnt-os")
236 "list" "--no-headers"))
237 (output (get-string-all port)))
242 (test-eq "gnt-cluster destroy"
246 (system* #$(file-append ganeti "/sbin/gnt-cluster")
247 "destroy" "--yes-do-it"))
251 (exit (= (test-runner-fail-count (test-runner-current)) 1)))))
253 (gexp->derivation (string-append "ganeti-" hypervisor "-test") test))
255 (define %test-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)))))
265 (define %test-ganeti-lxc
268 (description "Provision a Ganeti cluster using LXC as the hypervisor.")
269 (value (run-ganeti-test "lxc"
270 #:extra-packages (list lxc)))))