aboutsummaryrefslogtreecommitdiff
path: root/gnu/tests
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/tests')
-rw-r--r--gnu/tests/ganeti.scm265
1 files changed, 265 insertions, 0 deletions
diff --git a/gnu/tests/ganeti.scm b/gnu/tests/ganeti.scm
new file mode 100644
index 0000000000..0615edcde4
--- /dev/null
+++ b/gnu/tests/ganeti.scm
@@ -0,0 +1,265 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2020 Marius Bakke <marius@gnu.org>.
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu tests ganeti)
+ #:use-module (gnu)
+ #:use-module (gnu tests)
+ #:use-module (gnu system vm)
+ #:use-module (gnu services)
+ #:use-module (gnu services ganeti)
+ #:use-module (gnu services networking)
+ #:use-module (gnu services ssh)
+ #:use-module (gnu packages virtualization)
+ #:use-module (guix gexp)
+ #:use-module (ice-9 format)
+ #:export (%test-ganeti-kvm %test-ganeti-lxc))
+
+(define %ganeti-os
+ (operating-system
+ (host-name "gnt1")
+ (timezone "Etc/UTC")
+ (locale "en_US.UTF-8")
+
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vda")))
+ (file-systems (cons (file-system
+ (device (file-system-label "my-root"))
+ (mount-point "/")
+ (type "ext4"))
+ %base-file-systems))
+ (firmware '())
+
+ ;; The hosts file must contain a nonlocal IP for host-name.
+ ;; In addition, the cluster name must resolve to an IP address that
+ ;; is not currently provisioned.
+ (hosts-file (plain-file "hosts" (format #f "
+127.0.0.1 localhost
+::1 localhost
+10.0.2.2 gnt1.example.com gnt1
+192.168.254.254 ganeti.example.com
+")))
+
+ (packages (append (list ganeti-instance-debootstrap ganeti-instance-guix)
+ %base-packages))
+ (services
+ (append (list (static-networking-service "eth0" "10.0.2.2"
+ #:netmask "255.255.255.0"
+ #:gateway "10.0.2.1"
+ #:name-servers '("10.0.2.1"))
+
+ (service openssh-service-type
+ (openssh-configuration
+ (permit-root-login 'without-password)))
+
+ (service ganeti-service-type
+ (ganeti-configuration
+ (file-storage-paths '("/srv/ganeti/file-storage"))
+ (os %default-ganeti-os))))
+ %base-services))))
+
+(define* (run-ganeti-test hypervisor #:key
+ (master-netdev "eth0")
+ (hvparams '())
+ (extra-packages '())
+ (rapi-port 5080)
+ (noded-port 1811))
+ "Run tests in %GANETI-OS."
+ (define os
+ (marionette-operating-system
+ (operating-system
+ (inherit %ganeti-os)
+ (packages (append extra-packages
+ (operating-system-packages %ganeti-os))))
+ #:imported-modules '((gnu services herd)
+ (guix combinators))))
+
+ (define %forwarded-rapi-port 5080)
+ (define %forwarded-noded-port 1811)
+
+ (define vm
+ (virtual-machine
+ (operating-system os)
+ ;; Some of the daemons are fairly memory-hungry.
+ (memory-size 512)
+ ;; Forward HTTP ports so we can access them from the "outside".
+ (port-forwardings `((,%forwarded-rapi-port . ,rapi-port)
+ (,%forwarded-noded-port . ,noded-port)))))
+
+ (define test
+ (with-imported-modules '((gnu build marionette))
+ #~(begin
+ (use-modules (srfi srfi-11) (srfi srfi-64)
+ (web uri) (web client) (web response)
+ (gnu build marionette))
+
+ (define marionette
+ (make-marionette (list #$vm)))
+
+ (mkdir #$output)
+ (chdir #$output)
+
+ (test-begin "ganeti")
+
+ ;; Ganeti uses the Shepherd to start/stop daemons, so make sure
+ ;; it is ready before we begin. It takes a while because all
+ ;; Ganeti daemons fail to start initially.
+ (test-assert "shepherd is ready"
+ (wait-for-unix-socket "/var/run/shepherd/socket" marionette))
+
+ (test-eq "gnt-cluster init"
+ 0
+ (marionette-eval
+ '(begin
+ (setenv
+ "PATH"
+ ;; Init needs to run 'ssh-keygen', 'ip', etc.
+ "/run/current-system/profile/sbin:/run/current-system/profile/bin")
+ (system* #$(file-append ganeti "/sbin/gnt-cluster") "init"
+ (string-append "--master-netdev=" #$master-netdev)
+ ;; TODO: Enable more disk backends.
+ "--enabled-disk-templates=file"
+ (string-append "--enabled-hypervisors="
+ #$hypervisor)
+ (string-append "--hypervisor-parameters="
+ #$hypervisor ":"
+ (string-join '#$hvparams "\n"))
+ ;; Set the default NIC mode to 'routed' to avoid having to
+ ;; configure a full bridge to placate 'gnt-cluster verify'.
+ "--nic-parameters=mode=routed,link=eth0"
+ "ganeti.example.com"))
+ marionette))
+
+ ;; Disable the watcher while doing daemon tests to prevent interference.
+ (test-eq "watcher pause"
+ 0
+ (marionette-eval
+ '(begin
+ (system* #$(file-append ganeti "/sbin/gnt-cluster")
+ "watcher" "pause" "1h"))
+ marionette))
+
+ (test-assert "force-start wconfd"
+ ;; Check that the 'force-start' Shepherd action works, used in a
+ ;; master-failover scenario.
+ (marionette-eval
+ '(begin
+ (setenv "PATH" "/run/current-system/profile/bin")
+ (invoke "herd" "stop" "ganeti-wconfd")
+ (invoke "herd" "disable" "ganeti-wconfd")
+ (invoke "herd" "force-start" "ganeti-wconfd"))
+ marionette))
+
+ ;; Verify that the cluster is healthy.
+ (test-eq "gnt-cluster verify 1"
+ 0
+ (marionette-eval
+ '(begin
+ (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
+ marionette))
+
+ ;; Try stopping and starting daemons with daemon-util like
+ ;; 'gnt-node add', 'gnt-cluster init', etc.
+ (test-eq "daemon-util stop-all"
+ 0
+ (marionette-eval
+ '(begin
+ (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
+ "stop-all"))
+ marionette))
+
+ (test-eq "daemon-util start-all"
+ 0
+ (marionette-eval
+ '(begin
+ (system* #$(file-append ganeti "/lib/ganeti/daemon-util")
+ "start-all"))
+ marionette))
+
+ ;; Check that the cluster is still healthy after the daemon restarts.
+ (test-eq "gnt-cluster verify 2"
+ 0
+ (marionette-eval
+ '(begin
+ (system* #$(file-append ganeti "/sbin/gnt-cluster") "verify"))
+ marionette))
+
+ (test-eq "watcher continue"
+ 0
+ (marionette-eval
+ '(begin
+ (system* #$(file-append ganeti "/sbin/gnt-cluster")
+ "watcher" "continue"))
+ marionette))
+
+ ;; Try accessing the RAPI. This causes an expected failure:
+ ;; https://github.com/ganeti/ganeti/issues/1502
+ ;; Run it anyway for easy testing of potential fixes.
+ (test-equal "http-get RAPI version"
+ '(200 "2")
+ (let-values
+ (((response text)
+ (http-get #$(simple-format
+ #f "http://localhost:~A/version"
+ %forwarded-rapi-port)
+ #:decode-body? #t)))
+ (list (response-code response) text)))
+
+ (test-equal "gnt-os list"
+ "debootstrap+default\nguix+default\n"
+ (marionette-eval
+ '(begin
+ (use-modules (ice-9 popen))
+ (let* ((port (open-pipe*
+ OPEN_READ
+ #$(file-append ganeti "/sbin/gnt-os")
+ "list" "--no-headers"))
+ (output (get-string-all port)))
+ (close-pipe port)
+ output))
+ marionette))
+
+ (test-eq "gnt-cluster destroy"
+ 0
+ (marionette-eval
+ '(begin
+ (system* #$(file-append ganeti "/sbin/gnt-cluster")
+ "destroy" "--yes-do-it"))
+ marionette))
+
+ (test-end)
+ (exit (= (test-runner-fail-count (test-runner-current)) 1)))))
+
+ (gexp->derivation (string-append "ganeti-" hypervisor "-test") test))
+
+(define %test-ganeti-kvm
+ (system-test
+ (name "ganeti-kvm")
+ (description "Provision a Ganeti cluster using the KVM hypervisor.")
+ (value (run-ganeti-test "kvm"
+ ;; Set kernel_path to an empty string to prevent
+ ;; 'gnt-cluster verify' from testing for its presence.
+ #:hvparams '("kernel_path=")
+ #:extra-packages (list qemu)))))
+
+(define %test-ganeti-lxc
+ (system-test
+ (name "ganeti-lxc")
+ (description "Provision a Ganeti cluster using LXC as the hypervisor.")
+ (value (run-ganeti-test "lxc"
+ #:extra-packages (list lxc)))))