[PATCH 0/4] Add Ganeti

  • Done
  • quality assurance status badge
Details
2 participants
  • Ludovic Courtès
  • Marius Bakke
Owner
unassigned
Submitted by
Marius Bakke
Severity
normal
M
M
Marius Bakke wrote on 8 Jul 2020 12:08
(address . guix-patches@gnu.org)
20200708100826.3114-1-marius@gnu.org
Here it comes! The much-rumoured Ganeti service, along with a draft
blog post (sent as patch 5/4).

Before pushing I'm going to update Ganeti to get rid of some patches,
and publish an improved ganeti-instance-guix. I will also try to
provision a cluster from scratch using the blog post instructions.

Note: the 'ganeti-shepherd-master-failover' patch relies on a Shepherd
service that has since been removed. I intend to replace it with a
"force-start" action on the ganeti-wconfd service, that passes the
required command-line arguments via environment variables, but other
ideas to temporarily start a daemon with special parameters welcome.

I have a lot going on currently and might not be able to finish this
until next week. Meanwhile, feedback appreciated as always.

Marius Bakke (4):
gnu: Add ganeti.
gnu: Add ganeti-instance-guix.
gnu: Add ganeti-instance-debootstrap.
services: Add ganeti.

doc/guix.texi | 560 +++++++++++
gnu/local.mk | 8 +
gnu/packages/patches/ganeti-copy-hmac.patch | 83 ++
.../ganeti-disable-version-symlinks.patch | 136 +++
gnu/packages/patches/ganeti-drbd-compat.patch | 168 ++++
.../patches/ganeti-haskell-pythondir.patch | 66 ++
.../ganeti-openvswitch-may-exist.patch | 25 +
.../patches/ganeti-preserve-PYTHONPATH.patch | 21 +
.../ganeti-shepherd-master-failover.patch | 26 +
.../patches/ganeti-shepherd-support.patch | 87 ++
gnu/packages/virtualization.scm | 500 ++++++++++
gnu/services/virtualization.scm | 906 +++++++++++++++++-
gnu/tests/virtualization.scm | 175 +++-
13 files changed, 2759 insertions(+), 2 deletions(-)
create mode 100644 gnu/packages/patches/ganeti-copy-hmac.patch
create mode 100644 gnu/packages/patches/ganeti-disable-version-symlinks.patch
create mode 100644 gnu/packages/patches/ganeti-drbd-compat.patch
create mode 100644 gnu/packages/patches/ganeti-haskell-pythondir.patch
create mode 100644 gnu/packages/patches/ganeti-openvswitch-may-exist.patch
create mode 100644 gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch
create mode 100644 gnu/packages/patches/ganeti-shepherd-master-failover.patch
create mode 100644 gnu/packages/patches/ganeti-shepherd-support.patch

--
2.27.0
M
M
Marius Bakke wrote on 8 Jul 2020 12:11
[PATCH 2/4] gnu: Add ganeti-instance-guix.
(address . 42261@debbugs.gnu.org)
20200708101118.3579-2-marius@gnu.org
* gnu/packages/virtualization.scm (ganeti-instance-guix): New public variable.
---
gnu/packages/virtualization.scm | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)

Toggle diff (40 lines)
diff --git a/gnu/packages/virtualization.scm b/gnu/packages/virtualization.scm
index 3ef9b8470a..3e3e8e3505 100644
--- a/gnu/packages/virtualization.scm
+++ b/gnu/packages/virtualization.scm
@@ -727,6 +727,33 @@ to provide fast and simple recovery after physical failures, using
commodity hardware.")
(license license:bsd-2)))
+(define-public ganeti-instance-guix
+ (package
+ (name "ganeti-instance-guix")
+ (version "0.3.1")
+ (home-page "https://github.com/mbakke/ganeti-instance-guix")
+ (source (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/mbakke/ganeti-instance-guix"
+ "/releases/download/" version
+ "/ganeti-instance-guix-" version ".tar.lz"))
+ (sha256
+ (base32
+ "0zvy143k7hp63nc5njbn2cvdhfcmsvqsaj0q2jzax8bibag2s2a8"))))
+ (build-system gnu-build-system)
+ (arguments
+ '(#:configure-flags '("--localstatedir=/var")))
+ (native-inputs
+ `(("lzip" ,lzip)))
+ (inputs
+ `(("util-linux" ,util-linux)
+ ("qemu-img" ,qemu-minimal)))
+ (synopsis "Guix OS integration for Ganeti")
+ (description
+ "This package provides a guest OS definition for Ganeti that can
+create virtual machines using Guix and an optional configuration file.")
+ (license license:gpl3+)))
+
(define-public libosinfo
(package
(name "libosinfo")
--
2.27.0
M
M
Marius Bakke wrote on 8 Jul 2020 12:11
[PATCH 3/4] gnu: Add ganeti-instance-debootstrap.
(address . 42261@debbugs.gnu.org)
20200708101118.3579-3-marius@gnu.org
* gnu/packages/virtualization.scm (ganeti-instance-debootstrap): New public variable.
---
gnu/packages/virtualization.scm | 95 +++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)

Toggle diff (115 lines)
diff --git a/gnu/packages/virtualization.scm b/gnu/packages/virtualization.scm
index 3e3e8e3505..5a32577d91 100644
--- a/gnu/packages/virtualization.scm
+++ b/gnu/packages/virtualization.scm
@@ -46,6 +46,7 @@
#:use-module (gnu packages cross-base)
#:use-module (gnu packages curl)
#:use-module (gnu packages cyrus-sasl)
+ #:use-module (gnu packages debian)
#:use-module (gnu packages disk)
#:use-module (gnu packages dns)
#:use-module (gnu packages docbook)
@@ -754,6 +755,100 @@ commodity hardware.")
create virtual machines using Guix and an optional configuration file.")
(license license:gpl3+)))
+(define-public ganeti-instance-debootstrap
+ (package
+ (name "ganeti-instance-debootstrap")
+ ;; We need two commits on top of the latest release for compatibility
+ ;; with newer sfdisk, as well as gnt-network integration.
+ (version "0.16-2-ge145396")
+ (home-page "https://github.com/ganeti/instance-debootstrap")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference (url home-page) (commit version)))
+ (sha256
+ (base32
+ "0f2isw9d8lawzj21rrq1q9xhq8xfa65rqbhqmrn59z201x9q1336"))))
+ (build-system gnu-build-system)
+ (arguments
+ '(#:configure-flags '("--sysconfdir=/etc" "--localstatedir=/var")
+ #:phases (modify-phases %standard-phases
+ (add-after 'unpack 'add-absolute-references
+ (lambda _
+ (substitute* "common.sh.in"
+ (("/sbin/blkid") (which "blkid"))
+ (("kpartx -")
+ (string-append (which "kpartx") " -")))
+ (substitute* "import"
+ (("restore -r")
+ (string-append (which "restore") " -r")))
+ (substitute* "export"
+ (("dump -0")
+ (string-append (which "dump") " -0")))
+ (substitute* "create"
+ (("debootstrap") (which "debootstrap"))
+ (("`which run-parts`") (which "run-parts"))
+ ;; Here we actually need to hard code /bin/passwd
+ ;; because it's called via chroot, which fails if
+ ;; "/bin" is not in PATH.
+ (("passwd") "/bin/passwd"))
+ #t))
+ (add-after 'unpack 'set-dpkg-arch
+ (lambda* (#:key system #:allow-other-keys)
+ ;; The create script passes --arch to debootstrap,
+ ;; and defaults to `dpkg --print-architecture` when
+ ;; ARCH is not set in variant.conf. Hard code the
+ ;; build-time architecture to avoid the dpkg dependency.
+ (let ((dpkg-arch
+ (cond ((string-prefix? "x86_64" system)
+ "amd64")
+ ((string-prefix? "i686" system)
+ "i386")
+ ((string-prefix? "aarch64" system)
+ "arm64")
+ (else (car (string-split system #\-))))))
+ (substitute* "create"
+ (("`dpkg --print-architecture`")
+ dpkg-arch))
+ #t)))
+ (add-after 'configure 'adjust-Makefile
+ (lambda _
+ ;; Do not attempt to create /etc/ganeti/instance-debootstrap
+ ;; and /etc/default/ganeti-instance-debootstrap during install.
+ ;; They are created by the Ganeti service.
+ (substitute* "Makefile"
+ (("\\$\\(variantsdir\\)")
+ "$(prefix)/etc/ganeti/instance-debootstrap/variants")
+ (("\\$\\(defaultsdir\\)")
+ "$(prefix)/etc/default/ganeti-instance-debootstrap"))
+ #t))
+ (add-after 'install 'make-variants.list-symlink
+ (lambda* (#:key outputs #:allow-other-keys)
+ ;; The Ganeti OS API mandates a variants.list file that
+ ;; describes all supported "variants" of this OS.
+ ;; Guix generates this file, so make the original file
+ ;; a symlink to it.
+ (with-directory-excursion (string-append
+ (assoc-ref outputs "out")
+ "/share/ganeti/os/debootstrap")
+ (delete-file "variants.list")
+ (symlink "/etc/ganeti/instance-debootstrap/variants/variants.list"
+ "variants.list"))
+ #t)))))
+ (native-inputs
+ `(("autoconf" ,autoconf)
+ ("automake" ,automake)))
+ (inputs
+ `(("debianutils" ,debianutils)
+ ("debootstrap" ,debootstrap)
+ ("dump" ,dump)
+ ("kpartx" ,multipath-tools)
+ ("util-linux" ,util-linux)))
+ (synopsis "Debian OS integration for Ganeti")
+ (description
+ "This package provides a guest OS definition for Ganeti. It installs
+Debian or a derivative using @command{debootstrap}.")
+ (license license:gpl2+)))
+
(define-public libosinfo
(package
(name "libosinfo")
--
2.27.0
M
M
Marius Bakke wrote on 8 Jul 2020 12:11
[PATCH 1/4] gnu: Add ganeti.
(address . 42261@debbugs.gnu.org)
20200708101118.3579-1-marius@gnu.org
* gnu/packages/virtualization.scm (system->qemu-target, ganeti): New variables.
* gnu/packages/patches/ganeti-copy-hmac.patch,
gnu/packages/patches/ganeti-disable-version-symlinks.patch,
gnu/packages/patches/ganeti-drbd-compat.patch,
gnu/packages/patches/ganeti-haskell-pythondir.patch,
gnu/packages/patches/ganeti-openvswitch-may-exist.patch,
gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch,
gnu/packages/patches/ganeti-shepherd-master-failover.patch,
gnu/packages/patches/ganeti-shepherd-support.patch: New files.
* gnu/local.mk (dist_patch_DATA): Adjust accordingly.
---
gnu/local.mk | 8 +
gnu/packages/patches/ganeti-copy-hmac.patch | 83 ++++
.../ganeti-disable-version-symlinks.patch | 136 +++++++
gnu/packages/patches/ganeti-drbd-compat.patch | 168 ++++++++
.../patches/ganeti-haskell-pythondir.patch | 66 +++
.../ganeti-openvswitch-may-exist.patch | 25 ++
.../patches/ganeti-preserve-PYTHONPATH.patch | 21 +
.../ganeti-shepherd-master-failover.patch | 26 ++
.../patches/ganeti-shepherd-support.patch | 87 ++++
gnu/packages/virtualization.scm | 378 ++++++++++++++++++
10 files changed, 998 insertions(+)
create mode 100644 gnu/packages/patches/ganeti-copy-hmac.patch
create mode 100644 gnu/packages/patches/ganeti-disable-version-symlinks.patch
create mode 100644 gnu/packages/patches/ganeti-drbd-compat.patch
create mode 100644 gnu/packages/patches/ganeti-haskell-pythondir.patch
create mode 100644 gnu/packages/patches/ganeti-openvswitch-may-exist.patch
create mode 100644 gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch
create mode 100644 gnu/packages/patches/ganeti-shepherd-master-failover.patch
create mode 100644 gnu/packages/patches/ganeti-shepherd-support.patch

Toggle diff (454 lines)
diff --git a/gnu/local.mk b/gnu/local.mk
index a277e63fa4..143aae2bea 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -944,6 +944,14 @@ dist_patch_DATA = \
%D%/packages/patches/fontconfig-hurd-path-max.patch \
%D%/packages/patches/freeimage-unbundle.patch \
%D%/packages/patches/fuse-overlapping-headers.patch \
+ %D%/packages/patches/ganeti-copy-hmac.patch \
+ %D%/packages/patches/ganeti-drbd-compat.patch \
+ %D%/packages/patches/ganeti-disable-version-symlinks.patch \
+ %D%/packages/patches/ganeti-haskell-pythondir.patch \
+ %D%/packages/patches/ganeti-openvswitch-may-exist.patch \
+ %D%/packages/patches/ganeti-preserve-PYTHONPATH.patch \
+ %D%/packages/patches/ganeti-shepherd-master-failover.patch \
+ %D%/packages/patches/ganeti-shepherd-support.patch \
%D%/packages/patches/gash-utils-ls-test.patch \
%D%/packages/patches/gawk-shell.patch \
%D%/packages/patches/gcc-arm-bug-71399.patch \
diff --git a/gnu/packages/patches/ganeti-copy-hmac.patch b/gnu/packages/patches/ganeti-copy-hmac.patch
new file mode 100644
index 0000000000..c1a758afe9
--- /dev/null
+++ b/gnu/packages/patches/ganeti-copy-hmac.patch
@@ -0,0 +1,83 @@
+This is a cherry-pick of three upstream commits that got lost in the
+transition when Ganeti was donated to the community.
+
+Submitted upstream: <https://github.com/ganeti/ganeti/pull/1494>.
+
+diff --git a/lib/bootstrap.py b/lib/bootstrap.py
+--- a/lib/bootstrap.py
++++ b/lib/bootstrap.py
+@@ -934,6 +934,8 @@ def SetupNodeDaemon(opts, cluster_name, node, ssh_port):
+ constants.NDS_CLUSTER_NAME: cluster_name,
+ constants.NDS_NODE_DAEMON_CERTIFICATE:
+ utils.ReadFile(pathutils.NODED_CERT_FILE),
++ constants.NDS_HMAC:
++ utils.ReadFile(pathutils.CONFD_HMAC_KEY),
+ constants.NDS_SSCONF: ssconf.SimpleStore().ReadAll(),
+ constants.NDS_START_NODE_DAEMON: True,
+ constants.NDS_NODE_NAME: node,
+diff --git a/lib/tools/common.py b/lib/tools/common.py
+--- a/lib/tools/common.py
++++ b/lib/tools/common.py
+@@ -184,6 +184,19 @@ def VerifyClusterName(data, error_fn, cluster_name_constant,
+ return name
+
+
++def VerifyHmac(data, error_fn):
++ """Verifies the presence of the hmac secret.
++
++ @type data: dict
++
++ """
++ hmac = data.get(constants.NDS_HMAC)
++ if not hmac:
++ raise error_fn("Hmac key must be provided")
++
++ return hmac
++
++
+ def LoadData(raw, data_check):
+ """Parses and verifies input data.
+
+diff --git a/lib/tools/node_daemon_setup.py b/lib/tools/node_daemon_setup.py
+--- a/lib/tools/node_daemon_setup.py
++++ b/lib/tools/node_daemon_setup.py
+@@ -51,6 +51,7 @@ from ganeti.tools import common
+ _DATA_CHECK = ht.TStrictDict(False, True, {
+ constants.NDS_CLUSTER_NAME: ht.TNonEmptyString,
+ constants.NDS_NODE_DAEMON_CERTIFICATE: ht.TNonEmptyString,
++ constants.NDS_HMAC: ht.TNonEmptyString,
+ constants.NDS_SSCONF: ht.TDictOf(ht.TNonEmptyString, ht.TString),
+ constants.NDS_START_NODE_DAEMON: ht.TBool,
+ constants.NDS_NODE_NAME: ht.TString,
+@@ -127,11 +128,18 @@ def Main():
+ cluster_name = common.VerifyClusterName(data, SetupError,
+ constants.NDS_CLUSTER_NAME)
+ cert_pem = common.VerifyCertificateStrong(data, SetupError)
++ hmac_key = common.VerifyHmac(data, SetupError)
+ ssdata = VerifySsconf(data, cluster_name)
+
+ logging.info("Writing ssconf files ...")
+ ssconf.WriteSsconfFiles(ssdata, dry_run=opts.dry_run)
+
++ logging.info("Writing hmac.key ...")
++ utils.WriteFile(pathutils.CONFD_HMAC_KEY, data=hmac_key,
++ mode=pathutils.NODED_CERT_MODE,
++ uid=getent.masterd_uid, gid=getent.masterd_gid,
++ dry_run=opts.dry_run)
++
+ logging.info("Writing node daemon certificate ...")
+ utils.WriteFile(pathutils.NODED_CERT_FILE, data=cert_pem,
+ mode=pathutils.NODED_CERT_MODE,
+diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
+--- a/src/Ganeti/Constants.hs
++++ b/src/Ganeti/Constants.hs
+@@ -4833,6 +4833,9 @@ ndsNodeDaemonCertificate = "node_daemon_certificate"
+ ndsSsconf :: String
+ ndsSsconf = "ssconf"
+
++ndsHmac :: String
++ndsHmac = "hmac_key"
++
+ ndsStartNodeDaemon :: String
+ ndsStartNodeDaemon = "start_node_daemon"
+
diff --git a/gnu/packages/patches/ganeti-disable-version-symlinks.patch b/gnu/packages/patches/ganeti-disable-version-symlinks.patch
new file mode 100644
index 0000000000..a5f347cfc6
--- /dev/null
+++ b/gnu/packages/patches/ganeti-disable-version-symlinks.patch
@@ -0,0 +1,136 @@
+This patch adds a new "--disable-version-links" configuration option
+that allows installing to the standard GNU installation directories
+instead of having to add symlinks in /etc/ganeti/{lib,share} that
+points to the right $ganeti/{lib,share}/$version. Mainly to reduce
+service complexity, and because Guix users can install as many versions
+of Ganeti they can muster without resorting to such hacks.
+
+diff --git a/Makefile.am b/Makefile.am
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -66,11 +66,16 @@ SHELL_ENV_INIT = autotools/shell-env-init
+ # so, if some currently architecture-independent executable is replaced by an
+ # architecture-dependent one (and hence has to go under $(versiondir)), add a link
+ # under $(versionedsharedir) but do not change the external links.
++#
++# As of Ganeti 3.0, it is possible to disable this behavior by passing
++# --disable-version-links, in which case the standard GNU installation
++# directories are used.
+ if USE_VERSION_FULL
+ DIRVERSION=$(VERSION_FULL)
+ else
+ DIRVERSION=$(VERSION_MAJOR).$(VERSION_MINOR)
+ endif
++if USE_VERSION_LINKS
+ versiondir = $(libdir)/ganeti/$(DIRVERSION)
+ defaultversiondir = $(libdir)/ganeti/default
+ versionedsharedir = $(prefix)/share/ganeti/$(DIRVERSION)
+@@ -90,6 +95,18 @@ gntpythondir = $(versionedsharedir)
+ pkgpython_bindir = $(versionedsharedir)
+ gnt_python_sbindir = $(versionedsharedir)
+ tools_pythondir = $(versionedsharedir)
++else
++myexeclibdir = $(pkglibdir)
++pkgpython_rpc_stubdir = $(pkgpythondir)/rpc/stub
++gntpythondir = $(sbindir)
++pkgpython_bindir = $(pkglibdir)
++gnt_python_sbindir = $(sbindir)
++tools_pythondir = $(pkglibdir)
++versionedsharedir = $(pkglibdir)
++# This is a hack but works because the only user does $(versiondir)$(datadir).
++versiondir =
++endif !USE_VERSION_LINKS
++
+
+ clientdir = $(pkgpythondir)/client
+ cmdlibdir = $(pkgpythondir)/cmdlib
+@@ -2356,6 +2373,7 @@ src/AutoConf.hs: Makefile src/AutoConf.hs.in $(PRINT_PY_CONSTANTS) \
+ -DVERSION_SUFFIX="$(VERSION_SUFFIX)" \
+ -DVERSION_FULL="$(VERSION_FULL)" \
+ -DDIRVERSION="$(DIRVERSION)" \
++ -DUSE_VERSION_LINKS="$(USE_VERSION_LINKS)" \
+ -DLOCALSTATEDIR="$(localstatedir)" \
+ -DSYSCONFDIR="$(sysconfdir)" \
+ -DSSH_CONFIG_DIR="$(SSH_CONFIG_DIR)" \
+@@ -2857,6 +2875,7 @@ install-exec-local:
+ @mkdir_p@ "$(DESTDIR)${localstatedir}/lib/ganeti" \
+ "$(DESTDIR)${localstatedir}/log/ganeti" \
+ "$(DESTDIR)${localstatedir}/run/ganeti"
++if USE_VERSION_LINKS
+ for dir in $(SYMLINK_TARGET_DIRS); do \
+ @mkdir_p@ $(DESTDIR)$$dir; \
+ done
+@@ -2892,7 +2911,8 @@ install-exec-local:
+ if INSTALL_SYMLINKS
+ $(LN_S) -f $(versionedsharedir) $(DESTDIR)$(sysconfdir)/ganeti/share
+ $(LN_S) -f $(versiondir) $(DESTDIR)$(sysconfdir)/ganeti/lib
+-endif
++endif INSTALL_SYMLINKS
++endif USE_VERSION_LINKS
+
+ .PHONY: apidoc
+ if WANT_HSAPIDOC
+diff --git a/configure.ac b/configure.ac
+--- a/configure.ac
++++ b/configure.ac
+@@ -29,6 +29,23 @@ AC_SUBST([BINDIR], $bindir)
+ AC_SUBST([SBINDIR], $sbindir)
+ AC_SUBST([MANDIR], $mandir)
+
++# --enable-version-links
++AC_ARG_ENABLE([version-links],
++ [AS_HELP_STRING([--enable-version-links],
++ m4_normalize([install ganeti to version-specific
++ subdirectories to allow installing multiple versions
++ in parallel (default: enabled)]))],
++ [[if test "$enableval" != no; then
++ USE_VERSION_LINKS=True
++ else
++ USE_VERSION_LINKS=False
++ fi
++ ]],
++ [USE_VERSION_LINKS=True
++ ])
++AC_SUBST(USE_VERSION_LINKS, $USE_VERSION_LINKS)
++AM_CONDITIONAL([USE_VERSION_LINKS], [test "$USE_VERSION_LINKS" = True])
++
+ # --enable-versionfull
+ AC_ARG_ENABLE([versionfull],
+ [AS_HELP_STRING([--enable-versionfull],
+diff --git a/lib/bootstrap.py b/lib/bootstrap.py
+--- a/lib/bootstrap.py
++++ b/lib/bootstrap.py
+@@ -944,7 +944,7 @@ def SetupNodeDaemon(opts, cluster_name, node, ssh_port):
+ debug=opts.debug, verbose=opts.verbose,
+ use_cluster_key=True, ask_key=opts.ssh_key_check,
+ strict_host_check=opts.ssh_key_check,
+- ensure_version=True)
++ ensure_version=constants.USE_VERSION_LINKS)
+
+ _WaitForSshDaemon(node, ssh_port)
+ _WaitForNodeDaemon(node)
+diff --git a/src/AutoConf.hs.in b/src/AutoConf.hs.in
+--- a/src/AutoConf.hs.in
++++ b/src/AutoConf.hs.in
+@@ -64,6 +64,9 @@ versionFull = "VERSION_FULL"
+ dirVersion :: String
+ dirVersion = "DIRVERSION"
+
++useVersionLinks :: Bool
++useVersionLinks = USE_VERSION_LINKS
++
+ localstatedir :: String
+ localstatedir = "LOCALSTATEDIR"
+
+diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
+--- a/src/Ganeti/Constants.hs
++++ b/src/Ganeti/Constants.hs
+@@ -164,5 +164,8 @@ versionRevision = AutoConf.versionRevision
+ dirVersion :: String
+ dirVersion = AutoConf.dirVersion
+
++useVersionLinks :: Bool
++useVersionLinks = AutoConf.useVersionLinks
++
+ osApiV10 :: Int
+ osApiV10 = 10
diff --git a/gnu/packages/patches/ganeti-drbd-compat.patch b/gnu/packages/patches/ganeti-drbd-compat.patch
new file mode 100644
index 0000000000..e06e04c5ef
--- /dev/null
+++ b/gnu/packages/patches/ganeti-drbd-compat.patch
@@ -0,0 +1,168 @@
+This patch adds support for newer versions of DRBD.
+
+Submitted upstream: <https://github.com/ganeti/ganeti/pull/1496>.
+
+diff --git a/lib/storage/drbd.py b/lib/storage/drbd.py
+--- a/lib/storage/drbd.py
++++ b/lib/storage/drbd.py
+@@ -315,6 +315,13 @@ class DRBD8Dev(base.BlockDev):
+ """
+ return self._show_info_cls.GetDevInfo(self._GetShowData(minor))
+
++ @staticmethod
++ def _NeedsLocalSyncerParams():
++ # For DRBD >= 8.4, syncer init must be done after local, not in net.
++ info = DRBD8.GetProcInfo()
++ version = info.GetVersion()
++ return version["k_minor"] >= 4
++
+ def _MatchesLocal(self, info):
+ """Test if our local config matches with an existing device.
+
+@@ -397,6 +404,22 @@ class DRBD8Dev(base.BlockDev):
+ base.ThrowError("drbd%d: can't attach local disk: %s",
+ minor, result.output)
+
++ def _WaitForMinorSyncParams():
++ """Call _SetMinorSyncParams and raise RetryAgain on errors.
++ """
++ if self._SetMinorSyncParams(minor, self.params):
++ raise utils.RetryAgain()
++ else:
++ return []
++
++ if self._NeedsLocalSyncerParams():
++ # Retry because disk config for DRBD resource may be still uninitialized.
++ try:
++ utils.Retry(_WaitForMinorSyncParams, 1.0, 5.0)
++ except utils.RetryTimeout:
++ base.ThrowError("drbd%d: can't set the synchronization parameters: %s" %
++ (minor, utils.CommaJoin(sync_errors)))
++
+ def _AssembleNet(self, minor, net_info, dual_pri=False, hmac=None,
+ secret=None):
+ """Configure the network part of the device.
+@@ -432,21 +455,24 @@ class DRBD8Dev(base.BlockDev):
+ # sync speed only after setting up both sides can race with DRBD
+ # connecting, hence we set it here before telling DRBD anything
+ # about its peer.
+- sync_errors = self._SetMinorSyncParams(minor, self.params)
+- if sync_errors:
+- base.ThrowError("drbd%d: can't set the synchronization parameters: %s" %
+- (minor, utils.CommaJoin(sync_errors)))
++
++ if not self._NeedsLocalSyncerParams():
++ sync_errors = self._SetMinorSyncParams(minor, self.params)
++ if sync_errors:
++ base.ThrowError("drbd%d: can't set the synchronization parameters: %s" %
++ (minor, utils.CommaJoin(sync_errors)))
+
+ family = self._GetNetFamily(minor, lhost, rhost)
+
+- cmd = self._cmd_gen.GenNetInitCmd(minor, family, lhost, lport,
++ cmds = self._cmd_gen.GenNetInitCmds(minor, family, lhost, lport,
+ rhost, rport, protocol,
+ dual_pri, hmac, secret, self.params)
+
+- result = utils.RunCmd(cmd)
+- if result.failed:
+- base.ThrowError("drbd%d: can't setup network: %s - %s",
+- minor, result.fail_reason, result.output)
++ for cmd in cmds:
++ result = utils.RunCmd(cmd)
++ if result.failed:
++ base.ThrowError("drbd%d: can't setup network: %s - %s",
++ minor, result.fail_reason, result.output)
+
+ def _CheckNetworkConfig():
+ info = self._GetShowInfo(minor)
+@@ -463,19 +489,20 @@ class DRBD8Dev(base.BlockDev):
+ base.ThrowError("drbd%d: timeout while configuring network", minor)
+
+ # Once the assembly is over, try to set the synchronization parameters
+- try:
+- # The minor may not have been set yet, requiring us to set it at least
+- # temporarily
+- old_minor = self.minor
+- self._SetFromMinor(minor)
+- sync_errors = self.SetSyncParams(self.params)
+- if sync_errors:
+- base.ThrowError("drbd%d: can't set the synchronization parameters: %s" %
+- (self.minor, utils.CommaJoin(sync_errors)))
+- finally:
+- # Undo the change, regardless of whether it will have to be done again
+- # soon
+- self._SetFromMinor(old_minor)
++ if not self._NeedsLocalSyncerParams():
++ try:
++ # The minor may not have been set yet, requiring us to set it at least
++ # temporarily
++ old_minor = self.minor
++ self._SetFromMinor(minor)
++ sync_errors = self.SetSyncParams(self.params)
++ if sync_errors:
++ base.ThrowError("drbd%d: can't set the synchronization parameters: %s" %
++ (self.minor, utils.CommaJoin(sync_errors)))
++ finally:
++ # Undo the change, regardless of whether it will have to be done again
++ # soon
++ self._SetFromMinor(old_minor)
+
+ @staticmethod
+ def _GetNetFamily(minor, lhost, rhost):
+diff --git a/lib/storage/drbd_cmdgen.py b/lib/storage/drbd_cmdgen.py
+--- a/lib/storage/drbd_cmdgen.py
++++ b/lib/storage/drbd_cmdgen.py
+@@ -56,7 +56,7 @@ class BaseDRBDCmdGenerator(object):
+ def GenLocalInitCmds(self, minor, data_dev, meta_dev, size_mb, params):
+ raise NotImplementedError
+
+- def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
++ def GenNetInitCmds(self, minor, family, lhost, lport, rhost, rport, protocol,
+ dual_pri, hmac, secret, params):
+ raise NotImplementedError
+
+@@ -138,7 +138,7 @@ class DRBD83CmdGenerator(BaseDRBDCmdGenerator):
+
+ return [args]
+
+- def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
++ def GenNetInitCmds(self, minor, family, lhost, lport, rhost, rport, protocol,
+ dual_pri, hmac, secret, params):
+ args = ["drbdsetup", self._DevPath(minor), "net",
+ "%s:%s:%s" % (family, lhost, lport),
+@@ -155,7 +155,7 @@ class DRBD83CmdGenerator(BaseDRBDCmdGenerator):
+ if params[constants.LDP_NET_CUSTOM]:
+ args.extend(shlex.split(params[constants.LDP_NET_CUSTOM]))
+
+- return args
++ return [args]
+
+ def GenSyncParamsCmd(self, minor, params):
+ args = ["drbdsetup", self._DevPath(minor), "syncer"]
+@@ -345,8 +345,14 @@ class DRBD84CmdGenerator(BaseDRBDCmdGenerator):
+
+ return cmds
+
+- def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
++ def GenNetInitCmds(self, minor, family, lhost, lport, rhost, rport, protocol,
+ dual_pri, hmac, secret, params):
++ cmds = []
++
++ cmds.append(["drbdsetup", "new-resource", self._GetResource(minor)])
++ cmds.append(["drbdsetup", "new-minor", self._GetResource(minor),
++ str(minor), "0"])
++
+ args = ["drbdsetup", "connect", self._GetResource(minor),
+ "%s:%s:%s" % (family, lhost, lport),
+ "%s:%s:%s" % (family, rhost, rport),
+@@ -362,7 +368,8 @@ class DRBD84CmdGenerator(BaseDRBDCmdGenerator):
+ if params[constants.LDP_NET_CUSTOM]:
+ args.extend(shlex.split(params[constants.LDP_NET_CUSTOM]))
+
+- return args
++ cmds.append(args)
++ return cmds
+
+ def GenSyncParamsCmd(self, minor, params):
+ args = ["drbdsetup", "disk-options", minor]
diff --git a/gnu/packages/patches/ganeti-haskell-pythondir.patch b/gnu/packages/patches/ganeti-haskell-pythondir.patch
new file mode 100644
index 0000000000..fa77771839
--- /dev/null
+++ b/gnu/packages/patches/ganeti-haskell-pythondir.patch
@@ -0,0 +1,66 @@
+This patch allows the Haskell daemons to locate Python libraries
+installed to a non-standard pythondir. It is necessary because Guix
+does not use versionedsharedir (see related patch that disables it).
+
+diff --git a/Makefile.am b/Makefile.am
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -83,6 +83,7 @@ myexeclibdir = $(pkglibdir)
+ bindir = $(versiondir)/$(BINDIR)
+ sbindir = $(versiondir)$(SBINDIR)
+ mandir = $(versionedsharedir)/root$(MANDIR)
++pythondir = $(versionedsharedir)
+ pkgpythondir = $(versionedsharedir)/ganeti
+ pkgpython_rpc_stubdir = $(versionedsharedir)/ganeti/rpc/stub
+ gntpythondir = $(versionedsharedir)
+@@ -2386,6 +2387,7 @@ src/AutoConf.hs: Makefile src/AutoConf.hs.in $(PRINT_PY_CONSTANTS) \
+ -DPKGLIBDIR="$(libdir)/ganeti" \
+ -DSHAREDIR="$(prefix)/share/ganeti" \
+ -DVERSIONEDSHAREDIR="$(versionedsharedir)" \
++ -DPYTHONDIR="$(pythondir)" \
+ -DDRBD_BARRIERS="$(DRBD_BARRIERS)" \
+ -DDRBD_NO_META_FLUSH="$(DRBD_NO_META_FLUSH)" \
+ -DSYSLOG_USAGE="$(SYSLOG_USAGE)" \
+diff --git a/src/AutoConf.hs.in b/s
This message was truncated. Download the full message here.
M
M
Marius Bakke wrote on 8 Jul 2020 12:11
[PATCH 4/4] services: Add ganeti.
(address . 42261@debbugs.gnu.org)
20200708101118.3579-4-marius@gnu.org
* gnu/services/virtualization.scm (<ganeti-noded-configuration>,
<ganeti-confd-configuration>, <ganeti-wconfd-configuration>,
<ganeti-luxid-configuration>, <ganeti-rapi-configuration>,
<ganeti-kvmd-configuration>, <ganeti-mond-configuration>),
<ganeti-metad-configuration>, <ganeti-watcher-configuration>,
<ganeti-cleaner-configuration>, <ganeti-configuration>, <ganeti-os>,
<ganeti-os-variant>, <debootstrap-configuration>): New record types.
(%default-ganeti-environment-variables, ganeti-noded-service,
ganeti-noded-service-type, ganeti-confd-service, ganeti-confd-service-type,
ganeti-wconfd-service, ganeti-wconfd-service-type, ganeti-luxid-service,
ganeti-luxid-service-type, ganeti-rapi-service, ganeti-rapi-service-type,
ganeti-kvmd-service, ganeti-kvmd-service-type, ganeti-mond-service,
ganeti-mond-service-type, ganeti-metad-service, ganeti-metad-service-type,
ganeti-watcher-command, ganeti-watcher-jobs, ganeti-watcher-service-type,
ganeti-cleaner-jobs, ganeti-cleaner-service-type, ganeti-activation,
ganeti-shepherd-services, ganeti-mcron-jobs, ganeti-service-type,
hooks->directory, debootstrap-configuration-compiler, debootstrap-variant,
ganeti-os-variant->configuration, ganeti-os->directory, ganeti-directory,
file-storage-file, ganeti-etc-service, ganeti-service-type): New variables.
* gnu/tests/virtualization.scm (%debootstrap-hooks, %ganeti-os,
run-ganeti-test, %test-ganeti-kvm, %test-ganeti-lxc): New variables.
* doc/guix.texi (Virtualization Services): Document accordingly.
---
doc/guix.texi | 560 ++++++++++++++++++++
gnu/services/virtualization.scm | 906 +++++++++++++++++++++++++++++++-
gnu/tests/virtualization.scm | 175 +++++-
3 files changed, 1639 insertions(+), 2 deletions(-)

Toggle diff (473 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 992bc303bb..d5cfc23297 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -24898,6 +24898,566 @@ the @code{--snapshot} flag using something along these lines:
(options '("--hda"))))
@end lisp
+@subsubheading Ganeti
+
+@cindex ganeti
+
+@quotation Note
+This service currently offered as a tech preview. Configuration options may
+be changed in a backwards-incompatible manner, and not all features have been
+thorougly tested. Users of this service are encouraged to share their
+experience at @email{guix-devel@@gnu.org}.
+@end quotation
+
+Ganeti is a cluster-based virtual machine management system. It consists
+of multiple services which are described later in this section. In addition
+to the Ganeti service, you will need the OpenSSH service
+(@pxref{Networking Services, @code{openssh-service-type}}), and update the
+@file{/etc/hosts} file (@pxref{operating-system Reference, @code{hosts-file}})
+with the cluster name and address (or use a DNS server). Here is an example
+configuration for a Ganeti cluster node:
+
+@lisp
+(operating-system
+ ...
+ (host-name "node1")
+ (hosts-file (plain-file "hosts" (format #f "
+127.0.0.1 localhost
+::1 localhost
+
+192.168.1.100 ganeti.example.com
+192.168.1.101 node1.example.com node1
+192.168.1.102 node2.example.com node2
+")))
+
+ ;; Install QEMU so we can use KVM-based instances, and LVM, DRBD and Ceph
+ ;; in order to use the "plain", "drbd" and "rbd" storage backends.
+ (packages (append (map specification->package
+ '("qemu" "lvm2" "drbd-utils" "ceph"
+ "ganeti-instance-guix" "ganeti-instance-debootstrap"))
+ %base-packages))
+ (services
+ (append (list (static-networking-service "eth0" "192.168.1.101"
+ #:netmask "255.255.255.0"
+ #:gateway "192.168.1.254"
+ #:name-servers '("192.168.1.252"
+ "192.168.1.253"))
+
+ ;; Ganeti uses SSH to communicate between nodes.
+ (service openssh-service-type
+ (openssh-configuration
+ (permit-root-login 'without-password)))
+
+ (service ganeti-service-type
+ (ganeti-configuration
+ ;; This file specifies allowed file system paths
+ ;; for storing virtual machine images.
+ (file-storage-paths '("/srv/ganeti/file-storage")))))
+ %base-services)))
+@end lisp
+
+Users are advised to read the
+@url{http://docs.ganeti.org/ganeti/master/html/admin.html,Ganeti
+administrators guide} to learn about the various cluster options and
+day-to-day operations.
+
+There is also a
+@url{https://guix.gnu.org/blog/2020/ganeti-cluster-on-guix/,blog post}
+describing how to configure a small cluster.
+
+The rest of this section documents each of the various services and their
+configuration options.
+
+@defvr {Scheme Variable} ganeti-service-type
+This is a service type that includes all the various services that Ganeti
+nodes should run.
+
+Its value is a @code{ganeti-configuration} object that defines the package
+to use for CLI operations, as well as configuration for the various daemons.
+
+@end defvr
+
+@deftp {Data Type} ganeti-configuration
+The @code{ganeti} service takes the following configuration options:
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use. It will be installed to the system profile
+and make @command{gnt-cluster}, @command{gnt-instance}, etc available. Note
+that the value specified here does not affect the other services as each refer
+to a specific @code{ganeti} package (see below).
+
+@item @code{noded-configuration} (default: @code{(ganeti-noded-configuration)})
+@item @code{confd-configuration} (default: @code{(ganeti-confd-configuration)})
+@item @code{wconfd-configuration} (default: @code{(ganeti-wconfd-configuration)})
+@item @code{luxid-configuration} (default: @code{(ganeti-luxid-configuration)})
+@item @code{rapi-configuration} (default: @code{(ganeti-rapi-configuration)})
+@item @code{kvmd-configuration} (default: @code{(ganeti-kvmd-configuration)})
+@item @code{mond-configuration} (default: @code{(ganeti-mond-configuration)})
+@item @code{watcher-configuration} (default: @code{(ganeti-watcher-configuration)})
+@item @code{cleaner-configuration} (default: @code{(ganeti-cleaner-configuration)})
+
+These options control the various daemons and cron jobs that are distributed
+with Ganeti. The possible values for these are described in detail below.
+To override a setting, you must use the configuration type for that service:
+
+@lisp
+(service ganeti-service-type
+ (ganeti-configuration
+ (rapi-configuration
+ (ganeti-rapi-configuration
+ (interface "eth1"))))
+ (watcher-configuration
+ (ganeti-watcher-configuration
+ (rapi-ip "10.0.0.1"))))
+@end lisp
+
+@item @code{file-storage-paths} (default: @code{'()})
+List of allowed directories for file storage backend.
+
+@item @code{os} (default: @code{'()})
+List if @code{<ganeti-os>} records. This currently only works with the
+@code{debootstrap} OS plugin.
+@end table
+
+In essence @code{ganeti-service-type} is shorthand for declaring each service
+individually:
+
+@lisp
+(service ganeti-noded-service-type)
+(service ganeti-confd-service-type)
+(service ganeti-wconfd-service-type)
+(service ganeti-luxid-service-type)
+(service ganeti-kvmd-service-type)
+(service ganeti-mond-service-type)
+(service ganeti-watcher-service-type)
+(service ganeti-cleaner-service-type)
+@end lisp
+
+The @file{/etc/ganeti} directory would need to be managed by other means however.
+
+@end deftp
+
+@deftp {Scheme Variable} ganeti-os
+This data type is suitable for passing to the @code{os} configuration of
+Ganeti. It takes the following parameters:
+
+@table @asis
+@item @code{name}
+The name for this OS. It is only used to specify where the variant configuration
+ends up. Setting it to "debootstrap" will create
+@file{/etc/ganeti/instance-debootstrap}.
+
+@item @code{variants} (default: @code{'()})
+List of @code{ganeti-os-variant} objects for this OS.
+
+@end table
+@end deftp
+
+@deftp {Scheme Variable} ganeti-os-variant
+This is the data type for a Ganeti OS variant.
+
+@table @asis
+@item @code{name}
+The name of this variant.
+
+@item @code{configuration}
+A configuration for this variant. Currently only @code{debootstrap-configuration}
+is supported.
+
+@end table
+@end deftp
+
+@deftp {Scheme Variable} debootstrap-configuration
+
+@table @asis
+@item @code{hooks} (default: @code{#f})
+If set, this must be a G-expression that specifies a directory with scripts
+that will run when the OS is installed. It can also be a list of
+@code{(name . file-like)} pairs. For example:
+
+@lisp
+
+`((10-testing . ,(plain-file "#!/bin/sh\necho Hello, World")))
+
+@end lisp
+
+That will create a directory with one executable and run it every time this
+variant is installed.
+@item @code{proxy} (default: @code{#f})
+HTTP proxy to use, if any.
+@item @code{mirror} (default: @var{#f})
+The Debian mirror. Typically something like
+@code{http://ftp.no.debian.org/debian}. The default varies depending on
+the distribution.
+@item @code{arch} (default: @code{#f})
+The dpkg architecture. Set to @code{armhf} to debootstrap an ARMv7 instance
+on an AArch64 host. Default is to use the current system architecture.
+@item @code{suite} (default: @code{"stable"})
+When not #f, must be a Debian distribution suite such as @code{buster} or
+@code{focal}.
+@item @code{extra-pkgs} (default: @var{%default-debootstrap-extra-pkgs})
+List of extra packages that will get installed by dpkg in addition
+to the minimal system.
+@item @code{components} (default: @code{#f})
+When set, must be a list of Debian repository ``components''. For example
+@code{'("main" "contrib")}.
+@item @code{generate-cache?} (default: @code{#t})
+Whether to automatically cache the generated debootstrap archive.
+@item @code{clean-cache} (default: @code{14})
+Discard the cache after this amount of days. Use @code{#f} to never
+clear the cache.
+@item @code{partition-style} (default: @code{'msdos})
+The type of partition to create. When set, it must be one of
+@code{'msdos}, @code{'none} or a string.
+@item @code{partition-alignment} (default: @code{2048})
+Alignment of the partition in sectors.
+@end table
+@end deftp
+
+@defvr {Scheme Variable} debootstrap-variant
+This is a helper procedure to create @code{ganeti-os-variant} records. It
+takes two arguments: a name and an optional @code{debootstrap-configuration}
+for this variant.
+@end defvr
+
+@defvr {Scheme Variable} ganeti-noded-service-type
+@command{ganeti-noded} is the daemon responsible for node-specific functions
+within the Ganeti system. The value of this service must be a
+@code{ganeti-noded-configuration} object.
+
+@end defvr
+
+@deftp {Data Type} ganeti-noded-configuration
+This is the configuration for the @code{ganeti-noded} service.
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use for this service.
+
+@item @code{port} (default: @code{1811})
+The TCP port on which the node daemon listens for network requests.
+
+@item @code{address} (default: @code{"0.0.0.0"})
+The network address that the daemon will bind to. The default address means
+bind to all available addresses.
+
+@item @code{interface} (default: @code{#f})
+When this is set, it must be a specific network interface (e.g.@: @code{eth0})
+that the daemon will bind to.
+
+@item @code{max-clients} (default: @code{20})
+This sets a limit on the maximum number of simultaneous client connections
+that the daemon will handle. Connections above this count are accepted, but
+no responses will be sent until enough connections have closed.
+
+@item @code{ssl?} (default: @code{#t})
+Whether to use SSL/TLS to encrypt network communications. The certificate
+is automatically provisioned by the cluster and can be rotated with
+@command{gnt-cluster renew-crypto}.
+
+@item @code{ssl-key} (default: @file{"/var/lib/ganeti/server.pem"})
+This can be used to provide a specific encryption key for TLS communications.
+
+@item @code{ssl-cert} (default: @file{"/var/lib/ganeti/server.pem"})
+This can be used to provide a specific certificate for TLS communications.
+
+@item @code{debug?} (default: @code{#f})
+When true, the daemon performs additional logging for debugging purposes.
+Note that this @emph{will} leak encryption details to the log files, use
+with care.
+
+@end table
+@end deftp
+
+@defvr {Scheme Variable} ganeti-confd-service-type
+@command{ganeti-confd} answers queries related to the configuration of a
+Ganeti cluster. The purpose of this daemon is to have a highly available
+and fast way to query cluster configuration values. It is automatically
+active on all @dfn{master candidates}. The value of this service must be a
+@code{ganeti-confd-configuration} object.
+
+@end defvr
+
+@deftp {Data Type} ganeti-confd-configuration
+This is the configuration for the @code{ganeti-confd} service.
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use for this service.
+
+@item @code{port} (default: @code{1814})
+The UDP port on which to listen for network requests.
+
+@item @code{address} (default: @code{"0.0.0.0"})
+Network address that the daemon will bind to.
+
+@item @code{debug?} (default: @code{#f})
+When true, the daemon performs additional logging for debugging purposes.
+
+@end table
+@end deftp
+
+@defvr {Scheme Variable} ganeti-wconfd-service-type
+@command{ganeti-wconfd} is the daemon that has authoritative knowledge
+about the cluster configuration and is the only entity that can accept
+changes to it. All jobs that need to modify the configuration will do so
+by sending appropriate requests to this daemon. It only runs on the
+@dfn{master node} and will automatically disable itself on other nodes.
+
+The value of this service must be a
+@code{ganeti-wconfd-configuration} object.
+@end defvr
+
+@deftp {Data Type} ganeti-wconfd-configuration
+This is the configuration for the @code{ganeti-wconfd} service.
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use for this service.
+
+@item @code{no-voting?} (default: @code{#f})
+The daemon will refuse to start if the majority of cluster nodes does not
+agree that it is running on the master node. Set to @code{#t} to start
+even if a quorum can not be reached (dangerous, use with caution).
+
+@item @code{debug?} (default: @code{#f})
+When true, the daemon performs additional logging for debugging purposes.
+
+@end table
+@end deftp
+
+@defvr {Scheme Variable} ganeti-luxid-service-type
+@command{ganeti-luxid} is a daemon used to answer queries related to the
+configuration and the current live state of a Ganeti cluster. Additionally,
+it is the authorative daemon for the Ganeti job queue. Jobs can be
+submitted via this daemon and it schedules and starts them.
+
+It takes a @code{ganeti-luxid-configuration} object.
+@end defvr
+
+@deftp {Data Type} ganeti-luxid-configuration
+This is the configuration for the @code{ganeti-wconfd} service.
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use for this service.
+
+@item @code{no-voting?} (default: @code{#f})
+The daemon will refuse to start if it cannot verify that the majority of
+cluster nodes believes that it is running on the master node. Set to
+@code{#t} to ignore such checks and start anyway (this can be dangerous).
+
+@item @code{debug?} (default: @code{#f})
+When true, the daemon performs additional logging for debugging purposes.
+
+@end table
+@end deftp
+
+@defvr {Scheme Variable} ganeti-rapi-service-type
+@command{ganeti-rapi} provides a remote API for Ganeti clusters. It runs on
+the master node and can be used to perform cluster actions programmatically
+via a JSON-based RPC protocol.
+
+Most query operations are allowed without authentication (unless
+@var{require-authentication?} is set), whereas write operations require
+explicit authorization via the @file{/var/lib/ganeti/rapi/users} file. See
+the @url{http://docs.ganeti.org/ganeti/master/html/rapi.html, Ganeti Remote
+API documentation} for more information.
+
+The value of this service must be a @code{ganeti-rapi-configuration} object.
+@end defvr
+
+@deftp {Data Type} ganeti-rapi-configuration
+This is the configuration for the @code{ganeti-rapi} service.
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use for this service.
+
+@item @code{require-authentication?} (default: @code{#f})
+Whether to require authentication even for read-only operations.
+
+@item @code{port} (default: @code{5080})
+The TCP port on which to listen to API requests.
+
+@item @code{address} (default: @code{"0.0.0.0"})
+The network address that the service will bind to. By default it listens
+on all configured addresses.
+
+@item @code{interface} (default: @code{#f})
+When set, it must specify a specific network interface such as @code{eth0}
+that the daemon will bind to.
+
+@item @code{max-clients} (default: @code{20})
+The maximum number of simultaneous client requests to handle. Further
+connections are allowed, but no responses are sent until enough connections
+have closed.
+
+@item @code{ssl-key} (default: @file{"/var/lib/ganeti/server.pem"})
+This can be used to provide a specific encryption key for TLS communications.
+
+@item @code{ssl-cert} (default: @file{"/var/lib/ganeti/server.pem"})
+This can be used to provide a specific certificate for TLS communications.
+
+@item @code{debug?} (default: @code{#f})
+When true, the daemon performs additional logging for debugging purposes.
+Note that this @emph{will} leak encryption details to the log files, use
+with caution.
+
+@end table
+@end deftp
+
+@defvr {Scheme Variable} ganeti-kvmd-service-type
+@command{ganeti-kvmd} is responsible for determining whether a given KVM
+instance was shut down by an administrator or a user. Normally Ganeti will
+restart an instance that was not stopped through Ganeti itself. If the
+cluster option @code{user_shutdown} is true, this daemon monitors the
+@code{QMP} socket provided by QEMU and listens for shutdown events, and
+marks the instance as @dfn{USER_down} instead of @dfn{ERROR_down} when
+it shuts down gracefully by itself.
+
+It takes a @code{ganeti-kvmd-configuration} object.
+@end defvr
+
+@deftp {Data Type} ganeti-kvmd-configuration
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use for this service.
+
+@item @code{debug?} (default: @code{#f})
+When true, the daemon performs additional logging for debugging purposes.
+
+@end table
+@end deftp
+
+@defvr {Scheme Variable} ganeti-mond-service-type
+@command{ganeti-mond} is an optional daemon that provides Ganeti monitoring
+functionality. It is responsible for running data collectors and publish the
+collected information through a HTTP interface.
+
+It takes a @code{ganeti-mond-configuration} object.
+@end defvr
+
+@deftp {Data Type} ganeti-mond-configuration
+
+@table @asis
+@item @code{ganeti} (default: @code{ganeti})
+The @code{ganeti} package to use for this service.
+
+@item @code{port} (default: @code{1815})
+The port on which the daemon will listen.
+
+@item @code{address} (default: @code{"0.0.0.0"})
+The network address that the daemon will bind to. By default it binds to all
+available interfaces.
+
+@item @code{debug?} (default: @code{#f})
+When true, the daemon performs additional logging for debugging purposes.
+
+@end table
+@end deftp
+
+@defvr {Scheme Variable} ganeti-metad-service-type
+@command{ganeti-metad} is an optional daemon that can be used to provide
+information about the cluster to instances or OS install scripts. It is
+not included in @code{ganeti-service-ty
This message was truncated. Download the full message here.
M
M
Marius Bakke wrote on 8 Jul 2020 12:11
[PATCH] website: Add draft of a Ganeti cluster post.
(address . 42261@debbugs.gnu.org)(name . Marius Bakke)(address . mbakke@fastmail.com)
20200708101118.3579-5-marius@gnu.org
From: Marius Bakke <mbakke@fastmail.com>

* website/drafts/ganeti-cluster-on-guix.md: New file.
---
website/drafts/ganeti-cluster-on-guix.md | 414 +++++++++++++++++++++++
1 file changed, 414 insertions(+)
create mode 100644 website/drafts/ganeti-cluster-on-guix.md

Toggle diff (422 lines)
diff --git a/website/drafts/ganeti-cluster-on-guix.md b/website/drafts/ganeti-cluster-on-guix.md
new file mode 100644
index 0000000..253681b
--- /dev/null
+++ b/website/drafts/ganeti-cluster-on-guix.md
@@ -0,0 +1,414 @@
+title: Running a Ganeti cluster on Guix
+date: 2020-07-10 12:00
+author: Marius Bakke
+tags: Virtualization, Ganeti
+---
+The latest addition to Guix's ever-growing list of services is a little-known
+virtualization toolkit called [Ganeti](http://www.ganeti.org/). Ganeti is
+designed to keep virtual machines running on a cluster of servers even in the
+event of hardware failures, and to make maintenance and recovery tasks easy.
+
+It is comparable to tools such as
+[Proxmox](https://www.proxmox.com/en/proxmox-ve) or
+[oVirt](https://www.ovirt.org/), but has some distinctive features. One is
+that there is no GUI: [third](https://github.com/osuosl/ganeti_webmgr)
+[party](https://github.com/grnet/ganetimgr)
+[ones](https://github.com/sipgate/ganeti-control-center) exist, but are not
+currently packaged in Guix, so you are left with a rich command-line client
+and a fully featured
+[remote API](http://docs.ganeti.org/ganeti/master/html/rapi.html).
+
+Another interesting feature is that installing Ganeti on its own leaves you
+no way to actually deploy any virtual machines. That probably sounds crazy,
+but stems from the fact that Ganeti is designed to be API-driven and automated,
+thus it comes with a
+[OS API](http://docs.ganeti.org/ganeti/master/html/man-ganeti-os-interface.html)
+and users need to install one or more *OS providers* in addition to Ganeti.
+OS providers offer a declarative way to deploy virtual machine variants and
+should feel natural to Guix users. At the time of writing, the providers
+available in Guix are [debootstrap](https://github.com/ganeti/instance-debootstrap)
+for provisioning Debian- and Ubuntu-based VMs, and of course a
+[Guix](https://github.com/mbakke/ganeti-instance-guix) provider.
+
+Finally Ganeti comes with a sophisticated scheduler that efficiently packs
+virtual machines across a cluster while maintaining N+1 redundancy in case
+of a failover scenario. It can also make informed scheduling decisions
+based on various cluster tags, such as ensuring primary and secondary nodes
+are on different power distribution lines.
+
+(Note: if you are looking for a way to run just a few virtual machines on
+your local computer, you are probably better off using
+[libvirt](https://guix.gnu.org/manual/en/guix.html#index-libvirt) or even
+a [Childhurd](https://guix.gnu.org/manual/devel/en/guix.html#index-hurd_002dvm_002dservice_002dtype), as Ganeti is fairly heavyweight and requires a complicated networking
+setup.)
+
+
+# Preparing the configuration
+
+With introductions out of the way, let's see how we can deploy a Ganeti
+cluster using Guix. For this tutorial we will create a two-node cluster
+and connect instances to the local network using an
+[Open vSwitch](https://www.openvswitch.org/) bridge with no VLANs. We assume
+that each node has a single network interface named `eth0` connected to the
+same network, and that a dedicated partition `/dev/sdz3` is available for
+virtual machine storage. It is possible to store VMs on a number of other
+storage backends, but a dedicated drive (or rather LVM volume group) is
+necessary to use the [DRBD](https://www.linbit.com/drbd/) integration to
+replicate VM disks.
+
+We'll start off by defining a few helper services to create the Open vSwitch
+bridge and ensure the physical network interface is in the "up" state. Since
+Open vSwich stores the configuration in a database, you might as well run the
+equivalent `ovs-vsctl` commands on the host once and be done with it, but we
+do it through the configuration system to ensure we don't forget it in the
+future when adding or reinstalling nodes.
+
+```
+(define (start-interface if)
+ #~(let ((ip (string-append #$iproute "/sbin/ip")))
+ (invoke/quiet ip "link" "set" #$if "up")))
+
+(define (stop-interface if)
+ #~(let ((ip (string-append #$iproute "/sbin/ip")))
+ (invoke/quiet ip "link" "set" #$if "down")))
+
+;; This service is necessary to ensure eth0 is in the "up" state on boot
+;; since it is otherwise unmanaged from Guix PoV.
+(define (ifup-service if)
+ (let ((name (string-append "ifup-" if)))
+ (simple-service name shepherd-root-service-type
+ (list (shepherd-service
+ (provision (list (string->symbol name)))
+ (start #~(lambda ()
+ #$(start-interface if)))
+ (stop #~(lambda ()
+ #$(stop-interface if)))
+ (respawn? #f))))))
+
+(define* (create-openvswitch-bridge bridge uplink
+ #:key (vlan-mode #f))
+ #~(let ((ovs-vsctl (lambda (cmd)
+ (apply invoke/quiet
+ #$(file-append openvswitch "/bin/ovs-vsctl")
+ (string-tokenize cmd)))))
+ (and (ovs-vsctl (string-append "--may-exist add-br " #$bridge))
+ (ovs-vsctl (string-append "--may-exist add-port " #$bridge " "
+ #$uplink
+ (if #$vlan_mode
+ (format #f " vlan_mode=~a " #$vlan-mode)
+ ""))))))
+
+(define* (create-openvswitch-internal-port bridge port
+ #:key (vlan-mode #f))
+ #~(invoke/quiet #$(file-append openvswitch "/bin/ovs-vsctl")
+ "--may-exist" "add-port" #$bridge #$port
+ (if #$vlan_mode
+ (string-append "vlan_mode=" #$vlan-mode)
+ "")
+ "--" "set" "Interface" #$port "type=internal"))
+
+(define %openvswitch-configuration-service
+ (simple-service 'openvswitch-configuration shepherd-root-service-type
+ (list (shepherd-service
+ (provision '(openvswitch-configuration))
+ (requirement '(vswitchd))
+ (start #~(lambda ()
+ #$(create-openvswitch-bridge
+ "br0" "eth0"
+ #:vlan_mode "native-untagged")
+ #$(create-openvswitch-internal-port
+ "br0" "gnt0"
+ #:vlan_mode "native-untagged")))
+ (respawn? #f)))))
+```
+
+This defines a `openvswitch-configuration` service object that creates a
+logical switch `br0`, connects `eth0` as the "uplink", and creates a logical
+port `gnt0` that we will use later as the main network interface for this
+system. We also create an `ifup` service that can bring network interfaces
+up and down. By themselves these variables do nothing, we also have to add
+them to our `operating-system` configuration below.
+
+A configuration like this might be suitable for a small home network. In most
+"real world" deployments you would use tagged VLANs, and maybe a traditional
+Linux bridge instead of Open vSwitch. You can also forego bridging altogether
+with a `routed` networking setup, or do any combination of the three.
+
+With this in place, we can start creating the `operating-system` configuration
+that we will use for the Ganeti servers:
+
+```
+(operating-system
+ (host-name "node1")
+ [...]
+ ;; Ganeti requires that each node and the cluster address resolves to an
+ ;; IP address. The easiest way to achieve this is by adding everything
+ ;; to the hosts file.
+ (hosts-file (plain-file "hosts" (format #f "\
+127.0.0.1 localhost
+::1 localhost
+
+192.168.1.101 node1
+192.168.1.102 node2
+192.168.1.254 ganeti.lan
+")))
+ (kernel-arguments
+ (append %default-kernel-arguments
+ '(;; Disable DRBDs usermode helper, as Ganeti
+ ;; is the only thing that should manage DRBD.
+ "drbd.usermode_helper=/run/current-system/profile/bin/true")))
+
+ (packages (append (map specification->package
+ '("qemu" "drbd-utils" "lvm2"
+ "ganeti-instance-guix"
+ "ganeti-instance-debootstrap"))
+ %base-packages))
+
+ (services (cons* (service ganeti-service-type
+ (ganeti-configuration
+ (file-storage-paths '("/srv/ganeti/file-storage"))
+ (os
+ (list (ganeti-os
+ (name "debootstrap")
+ (variants
+ (list (debootstrap-variant
+ "buster"
+ (debootstrap-configuration
+ (hooks
+ (local-file
+ "debootstrap-hooks"
+ #:recursive? #t))))
+ (debootstrap-variant
+ "testing+contrib"
+ (debootstrap-configuration
+ (suite "testing")
+ (components '("main" "contrib")))))))))))
+
+ ;; Create a static IP on the "gnt0" Open vSwitch interface.
+ (service openvswitch-service-type)
+ %openvswitch-configuration-service
+ (ifup-service "eth0")
+ (static-networking-service "gnt0" "192.168.1.101"
+ #:netmask "255.255.255.0"
+ #:gateway "192.168.1.1"
+ #:requirement '(openvswitch-configuration)
+ #:name-servers '("192.168.1.1"))
+
+ ;; Ganeti needs SSH to communicate between nodes.
+ (service openssh-service-type
+ (openssh-configuration
+ (permit-root-login 'without-password)))
+ %base-services)))
+```
+
+Debootstrap variants rely on a set of scripts (known as "hooks") in the
+installation process to do things like configure networking, install bootloader,
+create users, etc. In the example above, the "buster" variant will use a local
+directory next to the configuration file named "debootstrap-hooks" (it is copied
+into the final system closure), whereas the "testing+contrib" variant has no hooks
+defined and will use `/etc/ganeti/instance-debootstrap/hooks` if it exists.
+
+Ganeti veterans may be surprised that each OS variant has its own hooks. All
+Ganeti clusters I know of use a single set of hooks for all variants, sometimes
+with additional logic inside the script based on the variant. Guix offers a
+powerful abstraction that makes it trivial to create per-variant hooks, obsoleting
+the need for a big `/etc/ganeti/instance-debootstrap/hooks` directory. Of course
+you can still create it using `extra-special-file` and leave the `hooks` property
+of the variants as `#f`.
+
+Not all Ganeti options are exposed in the configuration system yet. If you
+find it limiting, you can add custom files using `extra-special-file`, or
+ideally extend the `<ganeti-configuration>` data type to suite your needs.
+Of course you can use `gnt-cluster copyfile` and `gnt-cluster command`
+to distribute files or run executables, but beware that undeclared changes
+in `/etc` may be lost on the next reboot or reconfigure.
+
+
+# Initializing a cluster
+
+At this stage, you should run `guix system reconfigure` with the new
+configuration on all nodes that will participate in the cluster. If you
+do this over SSH or with
+[guix deploy](https://guix.gnu.org/blog/2019/managing-servers-with-gnu-guix-a-tutorial/),
+beware that `eth0` will lose network connectivity once it is "plugged in to"
+the virtual switch, and you need to add any IP configuration to `gnt0`.
+
+The Guix configuration system does not currently support declaring LVM
+volume groups, so we will create these manually on each node. We could
+write our own declarative configuration like the `ifup-service`, but for
+brevity and safety reasons we'll do it "by hand":
+
+```
+pvcreate /dev/sdz3
+vgcreate ganetivg /dev/sdz3
+```
+
+On the node that will act as the "master node", run the init command:
+
+```
+gnt-cluster init \
+ --master-netdev=gnt0 \
+ --vg-name=ganetivg \
+ --enabled-disk-templates=file,plain,drbd \
+ --drbd-usermode-helper=/run/current-system/profile/bin/true \
+ --enabled-hypervisors=kvm \
+ --no-etc-hosts \
+ --no-ssh-init \
+ ganeti.lan
+```
+
+If you are okay with Ganeti taking control over SSH `authorized_keys` and
+`known_hosts`, remove the `--no-ssh-init` option. Guix users might prefer
+to manage the relevant files using `openssh-configuration`. All nodes in
+the cluster must be able to reach each other over SSH as the root user.
+
+Similarly, Ganeti can update the `/etc/hosts` file when nodes are added or
+removed, but it makes little sense on Guix as it is recreated every reboot.
+
+If all goes well, the command returns no output and you should have the
+`ganeti.lan` IP address visible on `gnt0`. You can run `gnt-cluster verify`
+to check that the cluster is in good shape. Most likely it complains about
+something:
+
+```
+# TODO
+```
+
+Use `gnt-cluster modify` to change the running state of the cluster:
+
+```
+gnt-cluster modify -H kvm:kernel_path=
+```
+
+The command above removes the warning about the default KVM kernel being
+missing, making `gnt-cluster verify` happy. For this tutorial we only use
+fully virtualized instances, but users might want to set `kernel_path` to a
+suitable VM kernel.
+
+Now let's add our other machine to the cluster:
+
+```
+gnt-node add node2
+```
+
+Ganeti will log into the node, copy the cluster configuration and start the
+relevant Shepherd services. No output means the command succeeded. Run
+`gnt-cluster verify` again to check that everything is in order:
+
+```
+gnt-cluster verify
+```
+
+If you get warnings about SSH authorizations here, you should fix those
+before proceeding. If you used `--no-ssh-init` earlier you may need to
+update `/var/lib/ganeti/known_hosts` with the new node information, either
+with `gnt-cluster copyfile` or by adding it to the OS configuration.
+
+The above configuration will make three operating systems available:
+
+```
+# gnt-os list
+Name
+guix
+debootstrap+buster
+debootstrap+testing+contrib
+```
+
+Let's try them out. But first we'll make Ganeti aware of our network
+so it can choose a static IP for the virtual machines.
+
+```
+# gnt-network add --network=192.168.1.0/24 --gateway=192.168.1.1 lan
+# gnt-network connect -N mode=openvswitch,link=br0 lan
+```
+
+Now we can add an instance:
+
+```
+gnt-instance add --no-name-check --no-ip-check -o debootstrap+buster \
+ -t drbd --disk 0:size=5G -B memory=256m,vcpus=2 \
+ --net 0:network=lan,ip=pool bustervm1
+```
+
+Ganeti will automatically select the optimal primary and secondary node
+for this VM based on available cluster resources. You can manually
+specify primary and secondary nodes with the `-n` and `-s` options.
+
+By default Ganeti assumes that the new instance is already configured in DNS,
+so we need `--no-name-check` and `--no-ip-check` to bypass some sanity tests.
+
+Try adding another instance, now using the Guix OS provider:
+
+```
+gnt-instance add --no-name-check --no-ip-check -o guix \
+ -t plain --disk 0:size=5G -B memory=1G,vcpus=4 \
+ --net 0:network=lan,ip=pool guix1
+```
+
+The Guix OS has a built-in configuration that starts an SSH server and authorizes
+the hosts SSH key, and configures static networking based on information from
+Ganeti. It is possible to specify a custom configuration file, and even a
+specific Guix commit:
+
+```
+gnt-instance add --no-name-check --no-ip-check -o guix \
+ -t file --file-storage-dir=/srv/ganeti/file-storage \
+ --disk 0:size=20G -B memory=4G,vpus=3 \
+ --net 0:network=lan,ip=pool \
+ -O "config=$(base64 /the/config/file.scm),commit=<commit>" \
+ custom-guix
+```
+
+That's it for this tutorial! If you are new to Ganeti, you should
+familiarize yourself with the `gnt-` family commands. Fun stuff to
+do include `gnt-instance migrate` to move VMs between hosts,
+`gnt-node evacuate` to migrate _all_ VMs off a node, and
+`gnt-cluster master-failover` to move the master role to a different node.
+
+
+# Final remarks
+
+Like most services in Guix, Ganeti comes with a
+[system test](https://guix.gnu.org/blog/2016/guixsd-system-tests/)
+that [runs in a VM](FIXME) and ensures that things like initializing a cluster
+work. The continuous integration system
+[runs this automatically](https://ci.guix.gnu.org/search?query=ganeti), and
+users can run it locally with `make check-system TESTS=ganeti`. Such
+tests give us confidence that both the package and configuration system work,
+and allows rapid testing of the configuration API. Currently it does little
+more than `gnt-cluster verify`, but it can be extended to provision a real
+cluster inside Ganeti and try things like live migration.
+
+The author had a lot of fun creating
+[native data types](FIXME manual link)
+in the Guix configuration system for the Ganeti OS specification. The API
+went through at least three major revisions during the writing of this blog
+post. There is still room for improvement, but I decided I had to stop
+tweaking it and instead focus on shipping the thing. Feedback welcome!
+
+Having OS support in the configuration system lets us benefit from Guix's
+provenance tracking and we can easily `guix system roll-back` any breaking
+changes. Ganeti is usually coupled with tools such as Puppet or SaltStack to
+keep things in sync between nodes, but that should not be necessary here.
+
+So far only the `KVM` hypervisor has been tested. If you use LXC or Xen with
+Ganeti, please reach out to `guix-devel@gnu.org` and share your experience.
+
+#### About GNU Guix
+
+[GNU Guix](https://guix.gnu.org) is a transactional package
+manager and an advanced distribution of the GNU system that [respects
+user
+freedom](https://www.gnu.org/distros/free-system-distribution-guidelines.html).
+Guix can be used on top of any system running the kernel Linux, or it
+can be used as a standalone operating system distribution for i686,
+x86_64, ARMv7, and AArch64 machines.
+
+In addition to standard package management features, Guix supports
+transactional upgrades and roll-backs, unprivileged package management,
+per-user profiles, and garbage collection. When used as a standalone
+GNU/Linux distribution, Guix offers a declarative, stateless approach to
+operating system configuration management. Guix is highly customizable
+and hackable through [Guile](https://www.gnu.org/software/guile)
+programming interfaces and extensions to the
+[Scheme](http://schemers.org) language.
--
2.27.0
L
L
Ludovic Courtès wrote on 10 Jul 2020 22:58
Re: [bug#42261] [PATCH 4/4] services: Add ganeti.
(name . Marius Bakke)(address . marius@gnu.org)(address . 42261@debbugs.gnu.org)
871rljytmy.fsf@gnu.org
Hello!

Marius Bakke <marius@gnu.org> skribis:

Toggle quote (23 lines)
> * gnu/services/virtualization.scm (<ganeti-noded-configuration>,
> <ganeti-confd-configuration>, <ganeti-wconfd-configuration>,
> <ganeti-luxid-configuration>, <ganeti-rapi-configuration>,
> <ganeti-kvmd-configuration>, <ganeti-mond-configuration>),
> <ganeti-metad-configuration>, <ganeti-watcher-configuration>,
> <ganeti-cleaner-configuration>, <ganeti-configuration>, <ganeti-os>,
> <ganeti-os-variant>, <debootstrap-configuration>): New record types.
> (%default-ganeti-environment-variables, ganeti-noded-service,
> ganeti-noded-service-type, ganeti-confd-service, ganeti-confd-service-type,
> ganeti-wconfd-service, ganeti-wconfd-service-type, ganeti-luxid-service,
> ganeti-luxid-service-type, ganeti-rapi-service, ganeti-rapi-service-type,
> ganeti-kvmd-service, ganeti-kvmd-service-type, ganeti-mond-service,
> ganeti-mond-service-type, ganeti-metad-service, ganeti-metad-service-type,
> ganeti-watcher-command, ganeti-watcher-jobs, ganeti-watcher-service-type,
> ganeti-cleaner-jobs, ganeti-cleaner-service-type, ganeti-activation,
> ganeti-shepherd-services, ganeti-mcron-jobs, ganeti-service-type,
> hooks->directory, debootstrap-configuration-compiler, debootstrap-variant,
> ganeti-os-variant->configuration, ganeti-os->directory, ganeti-directory,
> file-storage-file, ganeti-etc-service, ganeti-service-type): New variables.
> * gnu/tests/virtualization.scm (%debootstrap-hooks, %ganeti-os,
> run-ganeti-test, %test-ganeti-kvm, %test-ganeti-lxc): New variables.
> * doc/guix.texi (Virtualization Services): Document accordingly.

Since it’s a big chunk, perhaps it could live in (gnu services ganeti)?

Toggle quote (1 lines)
> +Ganeti is a cluster-based virtual machine management system. It consists
^
Maybe add one more sentence to give an idea of what it does or what
features it provides.

Toggle quote (6 lines)
> +of multiple services which are described later in this section. In addition
> +to the Ganeti service, you will need the OpenSSH service
> +(@pxref{Networking Services, @code{openssh-service-type}}), and update the
> +@file{/etc/hosts} file (@pxref{operating-system Reference, @code{hosts-file}})
> +with the cluster name and address (or use a DNS server). Here is an example
> +configuration for a Ganeti cluster node:
^
Add “that does X and Y”, or “with X nodes running Y”, something like
that. :-)

Toggle quote (4 lines)
> +There is also a
> +@url{https://guix.gnu.org/blog/2020/ganeti-cluster-on-guix/,blog post}
> +describing how to configure a small cluster.

It’d be great to see if part of the examples in the post (which I
haven’t read yet) can be folded in the manual.

Toggle quote (17 lines)
> +@table @asis
> +@item @code{ganeti} (default: @code{ganeti})
> +The @code{ganeti} package to use. It will be installed to the system profile
> +and make @command{gnt-cluster}, @command{gnt-instance}, etc available. Note
> +that the value specified here does not affect the other services as each refer
> +to a specific @code{ganeti} package (see below).
> +
> +@item @code{noded-configuration} (default: @code{(ganeti-noded-configuration)})
> +@item @code{confd-configuration} (default: @code{(ganeti-confd-configuration)})
> +@item @code{wconfd-configuration} (default: @code{(ganeti-wconfd-configuration)})
> +@item @code{luxid-configuration} (default: @code{(ganeti-luxid-configuration)})
> +@item @code{rapi-configuration} (default: @code{(ganeti-rapi-configuration)})
> +@item @code{kvmd-configuration} (default: @code{(ganeti-kvmd-configuration)})
> +@item @code{mond-configuration} (default: @code{(ganeti-mond-configuration)})
> +@item @code{watcher-configuration} (default: @code{(ganeti-watcher-configuration)})
> +@item @code{cleaner-configuration} (default: @code{(ganeti-cleaner-configuration)})

You need @itemx for all but the first one.

Anyway, that looks very nice!

Ludo’.
L
L
Ludovic Courtès wrote on 10 Jul 2020 23:00
Re: [bug#42261] [PATCH 1/4] gnu: Add ganeti.
(name . Marius Bakke)(address . marius@gnu.org)(address . 42261@debbugs.gnu.org)
87wo3bxeyv.fsf@gnu.org
Marius Bakke <marius@gnu.org> skribis:

Toggle quote (23 lines)
> * gnu/packages/virtualization.scm (system->qemu-target, ganeti): New variables.
> * gnu/packages/patches/ganeti-copy-hmac.patch,
> gnu/packages/patches/ganeti-disable-version-symlinks.patch,
> gnu/packages/patches/ganeti-drbd-compat.patch,
> gnu/packages/patches/ganeti-haskell-pythondir.patch,
> gnu/packages/patches/ganeti-openvswitch-may-exist.patch,
> gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch,
> gnu/packages/patches/ganeti-shepherd-master-failover.patch,
> gnu/packages/patches/ganeti-shepherd-support.patch: New files.
> * gnu/local.mk (dist_patch_DATA): Adjust accordingly.
> ---
> gnu/local.mk | 8 +
> gnu/packages/patches/ganeti-copy-hmac.patch | 83 ++++
> .../ganeti-disable-version-symlinks.patch | 136 +++++++
> gnu/packages/patches/ganeti-drbd-compat.patch | 168 ++++++++
> .../patches/ganeti-haskell-pythondir.patch | 66 +++
> .../ganeti-openvswitch-may-exist.patch | 25 ++
> .../patches/ganeti-preserve-PYTHONPATH.patch | 21 +
> .../ganeti-shepherd-master-failover.patch | 26 ++
> .../patches/ganeti-shepherd-support.patch | 87 ++++
> gnu/packages/virtualization.scm | 378 ++++++++++++++++++
> 10 files changed, 998 insertions(+)

The patches are quite big, but maybe that’s unavoidable.

Apart from that, on a cursory look it LGTM!

Ludo’.
L
L
Ludovic Courtès wrote on 10 Jul 2020 23:05
Re: [bug#42261] [PATCH] website: Add draft of a Ganeti cluster post.
(name . Marius Bakke)(address . marius@gnu.org)
87r1tjxeqg.fsf@gnu.org
Hey!

Marius Bakke <marius@gnu.org> skribis:

Toggle quote (4 lines)
> From: Marius Bakke <mbakke@fastmail.com>
>
> * website/drafts/ganeti-cluster-on-guix.md: New file.

Very nice! There’s a couple of FIXME/TODO links that you’ll have to
address, but other than that I found it interesting and pleasant to
read.

Toggle quote (6 lines)
> +(Note: if you are looking for a way to run just a few virtual machines on
> +your local computer, you are probably better off using
> +[libvirt](https://guix.gnu.org/manual/en/guix.html#index-libvirt) or even
> +a [Childhurd](https://guix.gnu.org/manual/devel/en/guix.html#index-hurd_002dvm_002dservice_002dtype), as Ganeti is fairly heavyweight and requires a complicated networking
> +setup.)

Thumbs up for the Hurd plug. :-)

Ludo’.
M
M
Marius Bakke wrote on 11 Jul 2020 23:54
Re: [bug#42261] [PATCH 4/4] services: Add ganeti.
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42261@debbugs.gnu.org)
87imetd8fe.fsf@gnu.org
Hi!

Thanks a bunch for reading through this. :-)

Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (29 lines)
> Hello!
>
> Marius Bakke <marius@gnu.org> skribis:
>
>> * gnu/services/virtualization.scm (<ganeti-noded-configuration>,
>> <ganeti-confd-configuration>, <ganeti-wconfd-configuration>,
>> <ganeti-luxid-configuration>, <ganeti-rapi-configuration>,
>> <ganeti-kvmd-configuration>, <ganeti-mond-configuration>),
>> <ganeti-metad-configuration>, <ganeti-watcher-configuration>,
>> <ganeti-cleaner-configuration>, <ganeti-configuration>, <ganeti-os>,
>> <ganeti-os-variant>, <debootstrap-configuration>): New record types.
>> (%default-ganeti-environment-variables, ganeti-noded-service,
>> ganeti-noded-service-type, ganeti-confd-service, ganeti-confd-service-type,
>> ganeti-wconfd-service, ganeti-wconfd-service-type, ganeti-luxid-service,
>> ganeti-luxid-service-type, ganeti-rapi-service, ganeti-rapi-service-type,
>> ganeti-kvmd-service, ganeti-kvmd-service-type, ganeti-mond-service,
>> ganeti-mond-service-type, ganeti-metad-service, ganeti-metad-service-type,
>> ganeti-watcher-command, ganeti-watcher-jobs, ganeti-watcher-service-type,
>> ganeti-cleaner-jobs, ganeti-cleaner-service-type, ganeti-activation,
>> ganeti-shepherd-services, ganeti-mcron-jobs, ganeti-service-type,
>> hooks->directory, debootstrap-configuration-compiler, debootstrap-variant,
>> ganeti-os-variant->configuration, ganeti-os->directory, ganeti-directory,
>> file-storage-file, ganeti-etc-service, ganeti-service-type): New variables.
>> * gnu/tests/virtualization.scm (%debootstrap-hooks, %ganeti-os,
>> run-ganeti-test, %test-ganeti-kvm, %test-ganeti-lxc): New variables.
>> * doc/guix.texi (Virtualization Services): Document accordingly.
>
> Since it’s a big chunk, perhaps it could live in (gnu services ganeti)?

I was "on the fence" about this myself, so I'm happy that you tipped me
over so to speak.

Toggle quote (5 lines)
>> +Ganeti is a cluster-based virtual machine management system. It consists
> ^
> Maybe add one more sentence to give an idea of what it does or what
> features it provides.

That makes sense. I explained more in the transient blog post, but the
permanent documentation deserves better treatment.

Toggle quote (10 lines)
>> +of multiple services which are described later in this section. In addition
>> +to the Ganeti service, you will need the OpenSSH service
>> +(@pxref{Networking Services, @code{openssh-service-type}}), and update the
>> +@file{/etc/hosts} file (@pxref{operating-system Reference, @code{hosts-file}})
>> +with the cluster name and address (or use a DNS server). Here is an example
>> +configuration for a Ganeti cluster node:
> ^
> Add “that does X and Y”, or “with X nodes running Y”, something like
> that. :-)

Thanks. :-)

Toggle quote (7 lines)
>> +There is also a
>> +@url{https://guix.gnu.org/blog/2020/ganeti-cluster-on-guix/,blog post}
>> +describing how to configure a small cluster.
>
> It’d be great to see if part of the examples in the post (which I
> haven’t read yet) can be folded in the manual.

Agreed. I kind of wrote them together, before the service was
"finalized", and focused mostly on the end-to-end tutorial. I'll try to
extract generic parts into the manual.

Toggle quote (19 lines)
>> +@table @asis
>> +@item @code{ganeti} (default: @code{ganeti})
>> +The @code{ganeti} package to use. It will be installed to the system profile
>> +and make @command{gnt-cluster}, @command{gnt-instance}, etc available. Note
>> +that the value specified here does not affect the other services as each refer
>> +to a specific @code{ganeti} package (see below).
>> +
>> +@item @code{noded-configuration} (default: @code{(ganeti-noded-configuration)})
>> +@item @code{confd-configuration} (default: @code{(ganeti-confd-configuration)})
>> +@item @code{wconfd-configuration} (default: @code{(ganeti-wconfd-configuration)})
>> +@item @code{luxid-configuration} (default: @code{(ganeti-luxid-configuration)})
>> +@item @code{rapi-configuration} (default: @code{(ganeti-rapi-configuration)})
>> +@item @code{kvmd-configuration} (default: @code{(ganeti-kvmd-configuration)})
>> +@item @code{mond-configuration} (default: @code{(ganeti-mond-configuration)})
>> +@item @code{watcher-configuration} (default: @code{(ganeti-watcher-configuration)})
>> +@item @code{cleaner-configuration} (default: @code{(ganeti-cleaner-configuration)})
>
> You need @itemx for all but the first one.

Ahh, that's much better, thanks again!

Toggle quote (2 lines)
> Anyway, that looks very nice!

:-)
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEu7At3yzq9qgNHeZDoqBt8qM6VPoFAl8KNRUACgkQoqBt8qM6
VPpLZggAkhiu1wN+VyKFpEfgEhIvqH30Z82p6AjsAFQs0K395DUNgJTpU746Zjlv
krQ20xm2fwbpf5ByqGtT6z3Jo3hh1Y34A5nZOIHeKkfvt/cV1kmVEBTElIsOx2J/
I7LogDGdWBd4urS1hQ5iBHUN0fzpWq6eR0m1GAtuzOq/tPsnw5s63X0DyFxo86O3
QPecjNNGZrXH0gw/fOPcwnVEot82rIwPJ3k45PJ/giqvjpyWsv5x/J3O0Pu26FbD
2daUZ42Pxk5G47SWY2yIbc0+2gfeltlRaKHseTtMKQ7Kvu6tyspbGaevntYr6vBB
Tn/PaGbzjDWiJ6CJRZ2VoH4j6XYA4Q==
=fuGj
-----END PGP SIGNATURE-----

M
M
Marius Bakke wrote on 12 Jul 2020 00:08
Re: [bug#42261] [PATCH 1/4] gnu: Add ganeti.
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42261@debbugs.gnu.org)
87ft9xd7s8.fsf@gnu.org
Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (27 lines)
> Marius Bakke <marius@gnu.org> skribis:
>
>> * gnu/packages/virtualization.scm (system->qemu-target, ganeti): New variables.
>> * gnu/packages/patches/ganeti-copy-hmac.patch,
>> gnu/packages/patches/ganeti-disable-version-symlinks.patch,
>> gnu/packages/patches/ganeti-drbd-compat.patch,
>> gnu/packages/patches/ganeti-haskell-pythondir.patch,
>> gnu/packages/patches/ganeti-openvswitch-may-exist.patch,
>> gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch,
>> gnu/packages/patches/ganeti-shepherd-master-failover.patch,
>> gnu/packages/patches/ganeti-shepherd-support.patch: New files.
>> * gnu/local.mk (dist_patch_DATA): Adjust accordingly.
>> ---
>> gnu/local.mk | 8 +
>> gnu/packages/patches/ganeti-copy-hmac.patch | 83 ++++
>> .../ganeti-disable-version-symlinks.patch | 136 +++++++
>> gnu/packages/patches/ganeti-drbd-compat.patch | 168 ++++++++
>> .../patches/ganeti-haskell-pythondir.patch | 66 +++
>> .../ganeti-openvswitch-may-exist.patch | 25 ++
>> .../patches/ganeti-preserve-PYTHONPATH.patch | 21 +
>> .../ganeti-shepherd-master-failover.patch | 26 ++
>> .../patches/ganeti-shepherd-support.patch | 87 ++++
>> gnu/packages/virtualization.scm | 378 ++++++++++++++++++
>> 10 files changed, 998 insertions(+)
>
> The patches are quite big, but maybe that’s unavoidable.

Some have already been merged upstream, others should be shortly.
Ultimately I hope to only carry the Shepherd- and PYTHONPATH-related
patches. I haven't dared submitting 'disable-version-symlinks.patch'
yet, mainly because I struggled to find a clean way to conditionally
override Automake variables, ref

(there is a reply from Karl Berry in 2020-07)

Toggle quote (2 lines)
> Apart from that, on a cursory look it LGTM!

Awesome, I was able to do some more testing today and expect to push
this in a couple of days.
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEu7At3yzq9qgNHeZDoqBt8qM6VPoFAl8KOFcACgkQoqBt8qM6
VPoNeAf/d7bfWqv37Pc/iW3pFJ+VMZU2VY/bSnpQ9ZchHOlv2HbR9MDgKyHH45kZ
AmOMjJ50Ti4fpdRj748+3gYhgNMF2uCnygfJmZW0m4CCIGwX5cDtEzaTTA/UHyxb
PVgnjpk2n2x/yrWzc/xPZ0LcNe2xEHnpgp1zAyKusw3w9UVyxczi8c0ukJse1PEJ
3bq2QCvoU1dVF9ExVN0DsKcR5xhQXn/Njijn53Fxs5RjPDasPZ7ewdiu4NNkd4GL
c9giSDVKPBYhX4o4cl1kcvpzHHMDWPoCFGHeKRsi6rKLm+eliznAd3cELYFo9TBq
Di+00zO69haOGZ7v2VnGqGmlrPU0wA==
=HezY
-----END PGP SIGNATURE-----

L
L
Ludovic Courtès wrote on 13 Jul 2020 12:32
(name . Marius Bakke)(address . marius@gnu.org)(address . 42261@debbugs.gnu.org)
87zh83so25.fsf@gnu.org
Hi,

Marius Bakke <marius@gnu.org> skribis:

Toggle quote (33 lines)
> Ludovic Courtès <ludo@gnu.org> writes:
>
>> Marius Bakke <marius@gnu.org> skribis:
>>
>>> * gnu/packages/virtualization.scm (system->qemu-target, ganeti): New variables.
>>> * gnu/packages/patches/ganeti-copy-hmac.patch,
>>> gnu/packages/patches/ganeti-disable-version-symlinks.patch,
>>> gnu/packages/patches/ganeti-drbd-compat.patch,
>>> gnu/packages/patches/ganeti-haskell-pythondir.patch,
>>> gnu/packages/patches/ganeti-openvswitch-may-exist.patch,
>>> gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch,
>>> gnu/packages/patches/ganeti-shepherd-master-failover.patch,
>>> gnu/packages/patches/ganeti-shepherd-support.patch: New files.
>>> * gnu/local.mk (dist_patch_DATA): Adjust accordingly.
>>> ---
>>> gnu/local.mk | 8 +
>>> gnu/packages/patches/ganeti-copy-hmac.patch | 83 ++++
>>> .../ganeti-disable-version-symlinks.patch | 136 +++++++
>>> gnu/packages/patches/ganeti-drbd-compat.patch | 168 ++++++++
>>> .../patches/ganeti-haskell-pythondir.patch | 66 +++
>>> .../ganeti-openvswitch-may-exist.patch | 25 ++
>>> .../patches/ganeti-preserve-PYTHONPATH.patch | 21 +
>>> .../ganeti-shepherd-master-failover.patch | 26 ++
>>> .../patches/ganeti-shepherd-support.patch | 87 ++++
>>> gnu/packages/virtualization.scm | 378 ++++++++++++++++++
>>> 10 files changed, 998 insertions(+)
>>
>> The patches are quite big, but maybe that’s unavoidable.
>
> Some have already been merged upstream, others should be shortly.
> Ultimately I hope to only carry the Shepherd- and PYTHONPATH-related
> patches.

Great.

Toggle quote (7 lines)
> I haven't dared submitting 'disable-version-symlinks.patch' yet,
> mainly because I struggled to find a clean way to conditionally
> override Automake variables, ref
> <https://lists.gnu.org/archive/html/automake/2020-06/msg00000.html>
>
> (there is a reply from Karl Berry in 2020-07)

I think another option would be something like this (beware!):

pkglibdir =
if USE_VERSION_LINKS
pkglibdir += foo
else
pkglibdir += bar
endif

Toggle quote (5 lines)
>> Apart from that, on a cursory look it LGTM!
>
> Awesome, I was able to do some more testing today and expect to push
> this in a couple of days.

Yay!

Ludo’.
M
M
Marius Bakke wrote on 16 Jul 2020 22:36
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42261-done@debbugs.gnu.org)
871rlbp58r.fsf@gnu.org
Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (16 lines)
>> I haven't dared submitting 'disable-version-symlinks.patch' yet,
>> mainly because I struggled to find a clean way to conditionally
>> override Automake variables, ref
>> <https://lists.gnu.org/archive/html/automake/2020-06/msg00000.html>
>>
>> (there is a reply from Karl Berry in 2020-07)
>
> I think another option would be something like this (beware!):
>
> pkglibdir =
> if USE_VERSION_LINKS
> pkglibdir += foo
> else
> pkglibdir += bar
> endif

That's clever, but unfortunately did not work because the += adds an
extra whitespace between entries. So in this case $(pkglibdir) would
expand to ' bar', which may or may not work depending on whether the
usage is quoted. For things like $(bindir), install-binSCRIPTS
unfortunately quotes the entries. Tricky stuff!

Toggle quote (7 lines)
>>> Apart from that, on a cursory look it LGTM!
>>
>> Awesome, I was able to do some more testing today and expect to push
>> this in a couple of days.
>
> Yay!

I've made lots of tweaks recently, such as adding default hooks for
debootstrap so that basic things work out of the box. Finally pushed
now, and I intend to publish the blog post tomorrow.

One step closer to worl^W datacenter domination. \o/
-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEu7At3yzq9qgNHeZDoqBt8qM6VPoFAl8QujQACgkQoqBt8qM6
VPom2wgAqWfUA3zXfiUnCYI/jXHhxAwx/VrPkzknXzBvCDjpllpPeuGH0ON3fx0I
okhJx6WBEH9UWxJrw/k3NuFhj87fKFGqzWJEibFQ1XMxgJOVF6RruQwKKz6iwGCd
MhzLpccEy/RgFCppnh1QzO+r2KleJDrwSXeILLfBANCW0hkwiQvfyOiZm1AA4VVk
czV9n83BLxhnCzIPu2VhvyDEf9Xqfb24Xwo+K2i8D/7OQWxIiGvzUSvdhsaI8Z79
EVfycVRKgdv1cyAJ+hzDsQmKvvvNjNaxD5O2An4vFSfRqzBh3wYzFj4iiVI8Z87F
dAlJhm+6aXdicnByCPmBIuYsbQ/Maw==
=MHPr
-----END PGP SIGNATURE-----

Closed
?
Your comment

This issue is archived.

To comment on this conversation send an email to 42261@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 42261
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch