diff options
author | Marius Bakke <marius@gnu.org> | 2020-07-03 00:28:57 +0200 |
---|---|---|
committer | Marius Bakke <marius@gnu.org> | 2020-07-16 21:51:43 +0200 |
commit | 72a91d74cec01bfcfcef2b62c5b327fab82950b6 (patch) | |
tree | d93d3d99a5b2fe2f06765286e72cc89e17195b98 /gnu/packages/patches | |
parent | 851cc11cd1c28178110ea7db5d528b342e9bc5be (diff) | |
download | guix-72a91d74cec01bfcfcef2b62c5b327fab82950b6.tar.gz |
gnu: Add ganeti.
* gnu/packages/virtualization.scm (system->qemu-target, ganeti): New variables. * gnu/packages/patches/ganeti-deterministic-manual.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-os-disk-size.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.
Diffstat (limited to 'gnu/packages/patches')
-rw-r--r-- | gnu/packages/patches/ganeti-deterministic-manual.patch | 16 | ||||
-rw-r--r-- | gnu/packages/patches/ganeti-disable-version-symlinks.patch | 136 | ||||
-rw-r--r-- | gnu/packages/patches/ganeti-drbd-compat.patch | 166 | ||||
-rw-r--r-- | gnu/packages/patches/ganeti-haskell-pythondir.patch | 66 | ||||
-rw-r--r-- | gnu/packages/patches/ganeti-os-disk-size.patch | 17 | ||||
-rw-r--r-- | gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch | 21 | ||||
-rw-r--r-- | gnu/packages/patches/ganeti-shepherd-master-failover.patch | 18 | ||||
-rw-r--r-- | gnu/packages/patches/ganeti-shepherd-support.patch | 87 |
8 files changed, 527 insertions, 0 deletions
diff --git a/gnu/packages/patches/ganeti-deterministic-manual.patch b/gnu/packages/patches/ganeti-deterministic-manual.patch new file mode 100644 index 0000000000..2d90aa740e --- /dev/null +++ b/gnu/packages/patches/ganeti-deterministic-manual.patch @@ -0,0 +1,16 @@ +Sort the ecode list in the gnt-cluster manual for deterministic results. + +Submitted upstream: <https://github.com/ganeti/ganeti/pull/1504>. + +diff --git a/lib/build/sphinx_ext.py b/lib/build/sphinx_ext.py +--- a/lib/build/sphinx_ext.py ++++ b/lib/build/sphinx_ext.py +@@ -108,7 +108,7 @@ CV_ECODES_DOC = "ecodes" + # pylint: disable=W0621 + CV_ECODES_DOC_LIST = [(name, doc) for (_, name, doc) in constants.CV_ALL_ECODES] + DOCUMENTED_CONSTANTS = { +- CV_ECODES_DOC: CV_ECODES_DOC_LIST, ++ CV_ECODES_DOC: sorted(CV_ECODES_DOC_LIST, key=lambda tup: tup[0]), + } + + 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..32f46bc7ed --- /dev/null +++ b/gnu/packages/patches/ganeti-drbd-compat.patch @@ -0,0 +1,166 @@ +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,20 @@ 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() ++ ++ 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 as e: ++ base.ThrowError("drbd%d: can't set the synchronization parameters: %s" % ++ (minor, utils.CommaJoin(e.args[0]))) ++ + def _AssembleNet(self, minor, net_info, dual_pri=False, hmac=None, + secret=None): + """Configure the network part of the device. +@@ -432,21 +453,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 +487,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/src/AutoConf.hs.in +--- a/src/AutoConf.hs.in ++++ b/src/AutoConf.hs.in +@@ -157,6 +157,9 @@ sharedir = "SHAREDIR" + versionedsharedir :: String + versionedsharedir = "VERSIONEDSHAREDIR" + ++pythondir :: String ++pythondir = "PYTHONDIR" ++ + drbdBarriers :: String + drbdBarriers = "DRBD_BARRIERS" + +diff --git a/src/Ganeti/Path.hs b/src/Ganeti/Path.hs +--- a/src/Ganeti/Path.hs ++++ b/src/Ganeti/Path.hs +@@ -188,5 +188,5 @@ getInstReasonFilename instName = instanceReasonDir `pjoin` instName + + -- | The path to the Python executable for starting jobs. + jqueueExecutorPy :: IO FilePath +-jqueueExecutorPy = return $ versionedsharedir +- </> "ganeti" </> "jqueue" </> "exec.py" ++jqueueExecutorPy = return $ pythondir ++ </> "ganeti" </> "jqueue" </> "exec.py" +diff --git a/src/Ganeti/Query/Exec.hs b/src/Ganeti/Query/Exec.hs +--- a/src/Ganeti/Query/Exec.hs ++++ b/src/Ganeti/Query/Exec.hs +@@ -99,12 +99,12 @@ spawnJobProcess jid = withErrorLogAt CRITICAL (show jid) $ + do + use_debug <- isDebugMode + env_ <- (M.toList . M.insert "GNT_DEBUG" (if use_debug then "1" else "0") +- . M.insert "PYTHONPATH" AC.versionedsharedir ++ . M.insert "PYTHONPATH" AC.pythondir + . M.fromList) + `liftM` getEnvironment + execPy <- P.jqueueExecutorPy + logDebug $ "Executing " ++ AC.pythonPath ++ " " ++ execPy +- ++ " with PYTHONPATH=" ++ AC.versionedsharedir ++ ++ " with PYTHONPATH=" ++ AC.pythondir + + (master, child) <- pipeClient connectConfig + let (rh, wh) = clientToHandle child + diff --git a/gnu/packages/patches/ganeti-os-disk-size.patch b/gnu/packages/patches/ganeti-os-disk-size.patch new file mode 100644 index 0000000000..16b1d7615c --- /dev/null +++ b/gnu/packages/patches/ganeti-os-disk-size.patch @@ -0,0 +1,17 @@ +This exposes information about disk sizes to OS install scripts. instance-guix +uses this if available to determine the size of the VM image. + +Submitted upstream: +https://github.com/ganeti/ganeti/pull/1503 + +diff --git a/lib/backend.py b/lib/backend.py +--- a/lib/backend.py ++++ b/lib/backend.py +@@ -4305,6 +4305,7 @@ def OSEnvironment(instance, inst_os, debug=0): + uri = _CalculateDeviceURI(instance, disk, real_disk) + result["DISK_%d_ACCESS" % idx] = disk.mode + result["DISK_%d_UUID" % idx] = disk.uuid ++ result["DISK_%d_SIZE" % idx] = str(disk.size) + if real_disk.dev_path: + result["DISK_%d_PATH" % idx] = real_disk.dev_path + if uri: diff --git a/gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch b/gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch new file mode 100644 index 0000000000..1358e30633 --- /dev/null +++ b/gnu/packages/patches/ganeti-preserve-PYTHONPATH.patch @@ -0,0 +1,21 @@ +Do not override PYTHONPATH when calling Python code from the Haskell +daemons. This is necessary because the Python library dependencies are +only available through PYTHONPATH. + +diff --git a/src/Ganeti/Query/Exec.hs b/src/Ganeti/Query/Exec.hs +--- a/src/Ganeti/Query/Exec.hs ++++ b/src/Ganeti/Query/Exec.hs +@@ -99,12 +99,10 @@ spawnJobProcess jid = withErrorLogAt CRITICAL (show jid) $ + do + use_debug <- isDebugMode + env_ <- (M.toList . M.insert "GNT_DEBUG" (if use_debug then "1" else "0") +- . M.insert "PYTHONPATH" AC.pythondir + . M.fromList) + `liftM` getEnvironment + execPy <- P.jqueueExecutorPy + logDebug $ "Executing " ++ AC.pythonPath ++ " " ++ execPy +- ++ " with PYTHONPATH=" ++ AC.pythondir + + (master, child) <- pipeClient connectConfig + let (rh, wh) = clientToHandle child + diff --git a/gnu/packages/patches/ganeti-shepherd-master-failover.patch b/gnu/packages/patches/ganeti-shepherd-master-failover.patch new file mode 100644 index 0000000000..36a7918998 --- /dev/null +++ b/gnu/packages/patches/ganeti-shepherd-master-failover.patch @@ -0,0 +1,18 @@ +By default, master-failover will call "herd start ganeti-wconfd" with +extra arguments such as --force-node. That does not work with the +Shepherd, so the Guix service has a "force-start" action for this purpose. + +diff --git a/lib/bootstrap.py b/lib/bootstrap.py +--- a/lib/bootstrap.py ++++ b/lib/bootstrap.py +@@ -1011,9 +1011,7 @@ def MasterFailover(no_voting=False): + + try: + # Forcefully start WConfd so that we can access the configuration +- result = utils.RunCmd([pathutils.DAEMON_UTIL, +- "start", constants.WCONFD, "--force-node", +- "--no-voting", "--yes-do-it"]) ++ result = utils.RunCmd(["herd", "force-start", constants.WCONFD]) + if result.failed: + raise errors.OpPrereqError("Could not start the configuration daemon," + " command %s had exitcode %s and error %s" % diff --git a/gnu/packages/patches/ganeti-shepherd-support.patch b/gnu/packages/patches/ganeti-shepherd-support.patch new file mode 100644 index 0000000000..f750604344 --- /dev/null +++ b/gnu/packages/patches/ganeti-shepherd-support.patch @@ -0,0 +1,87 @@ +Ganeti uses an internal tool to start/stop daemons during init and +upgrade. This patch makes the tool use native Shepherd facilities. + +diff --git a/daemons/daemon-util.in b/daemons/daemon-util.in +--- a/daemons/daemon-util.in ++++ b/daemons/daemon-util.in +@@ -184,6 +184,21 @@ use_systemctl() { + return 1 + } + ++# Checks if we should use the Shepherd to start/stop daemons ++use_shepherd() { ++ # Is Shepherd running as PID 1? ++ ps --no-headers -p 1 -o cmd | grep -q shepherd || return 1 ++ ++ type -p herd >/dev/null || return 1 ++ ++ # Does Shepherd know about Ganeti at all? ++ if herd status | grep -q ganeti; then ++ return 0 ++ fi ++ ++ return 1 ++} ++ + # Prints path to PID file for a daemon. + daemon_pidfile() { + if [[ "$#" -lt 1 ]]; then +@@ -261,6 +276,13 @@ check() { + else + return 1 + fi ++ elif use_shepherd; then ++ activestate="$(herd status ${name})" ++ if echo $activestate | grep -q Running ; then ++ return 0 ++ else ++ return 1 ++ fi + elif type -p start-stop-daemon >/dev/null; then + start-stop-daemon --stop --signal 0 --quiet \ + --pidfile $pidfile --name "$name" +@@ -291,6 +313,20 @@ start() { + return $? + fi + ++ if use_shepherd; then ++ if herd status "$name" | grep -q "disabled"; then ++ # The Shepherd will disable a service that has stopped, even if it exits ++ # gracefully. Thus, we must re-enable it in case of a master failover. ++ herd enable "${name}" ++ fi ++ # Note: unlike systemd, which happily starts a service and returns success ++ # even if the daemon immediately exits, the Shepherd actually waits for it ++ # to come up. Thus, ignore the exit status from 'herd start' in case of ++ # master daemons running on the wrong node, or ganeti-kvmd disabled, etc. ++ herd start "${name}" ++ return 0 ++ fi ++ + # Read $<daemon>_ARGS and $EXTRA_<daemon>_ARGS + eval local args="\"\$${ucname}_ARGS \$EXTRA_${ucname}_ARGS\"" + +@@ -336,6 +372,13 @@ stop() { + + if use_systemctl; then + systemctl stop "${name}.service" ++ elif use_shepherd; then ++ if herd status | grep -q "$name"; then ++ herd stop "$name" ++ else ++ # Do not raise an error if the service has not been enabled. ++ return 0 ++ fi + elif type -p start-stop-daemon >/dev/null; then + start-stop-daemon --stop --quiet --oknodo --retry 30 \ + --pidfile $pidfile --name "$name" +@@ -352,6 +395,9 @@ check_and_start() { + if use_systemctl; then + echo "${name} supervised by systemd but not running, will not restart." + return 1 ++ elif use_shepherd; then ++ echo "${name} supervised by shepherd but not running, will not restart." ++ return 1 + fi + + start $name |