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.master
parent
851cc11cd1
commit
72a91d74ce
|
@ -947,6 +947,14 @@ dist_patch_DATA = \
|
||||||
%D%/packages/patches/fontconfig-hurd-path-max.patch \
|
%D%/packages/patches/fontconfig-hurd-path-max.patch \
|
||||||
%D%/packages/patches/freeimage-unbundle.patch \
|
%D%/packages/patches/freeimage-unbundle.patch \
|
||||||
%D%/packages/patches/fuse-overlapping-headers.patch \
|
%D%/packages/patches/fuse-overlapping-headers.patch \
|
||||||
|
%D%/packages/patches/ganeti-deterministic-manual.patch \
|
||||||
|
%D%/packages/patches/ganeti-disable-version-symlinks.patch \
|
||||||
|
%D%/packages/patches/ganeti-drbd-compat.patch \
|
||||||
|
%D%/packages/patches/ganeti-haskell-pythondir.patch \
|
||||||
|
%D%/packages/patches/ganeti-os-disk-size.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/gash-utils-ls-test.patch \
|
||||||
%D%/packages/patches/gawk-shell.patch \
|
%D%/packages/patches/gawk-shell.patch \
|
||||||
%D%/packages/patches/gcc-arm-bug-71399.patch \
|
%D%/packages/patches/gcc-arm-bug-71399.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]),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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]
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
|
@ -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
|
||||||
|
|
|
@ -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" %
|
|
@ -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
|
|
@ -38,6 +38,7 @@
|
||||||
#:use-module (gnu packages attr)
|
#:use-module (gnu packages attr)
|
||||||
#:use-module (gnu packages autotools)
|
#:use-module (gnu packages autotools)
|
||||||
#:use-module (gnu packages backup)
|
#:use-module (gnu packages backup)
|
||||||
|
#:use-module (gnu packages base)
|
||||||
#:use-module (gnu packages bison)
|
#:use-module (gnu packages bison)
|
||||||
#:use-module (gnu packages check)
|
#:use-module (gnu packages check)
|
||||||
#:use-module (gnu packages cmake)
|
#:use-module (gnu packages cmake)
|
||||||
|
@ -60,11 +61,19 @@
|
||||||
#:use-module (gnu packages gnome)
|
#:use-module (gnu packages gnome)
|
||||||
#:use-module (gnu packages gnupg)
|
#:use-module (gnu packages gnupg)
|
||||||
#:use-module (gnu packages golang)
|
#:use-module (gnu packages golang)
|
||||||
|
#:use-module (gnu packages graphviz)
|
||||||
#:use-module (gnu packages gtk)
|
#:use-module (gnu packages gtk)
|
||||||
|
#:use-module (gnu packages haskell)
|
||||||
|
#:use-module (gnu packages haskell-apps)
|
||||||
|
#:use-module (gnu packages haskell-check)
|
||||||
|
#:use-module (gnu packages haskell-crypto)
|
||||||
|
#:use-module (gnu packages haskell-web)
|
||||||
|
#:use-module (gnu packages haskell-xyz)
|
||||||
#:use-module (gnu packages image)
|
#:use-module (gnu packages image)
|
||||||
#:use-module (gnu packages libbsd)
|
#:use-module (gnu packages libbsd)
|
||||||
#:use-module (gnu packages libusb)
|
#:use-module (gnu packages libusb)
|
||||||
#:use-module (gnu packages linux)
|
#:use-module (gnu packages linux)
|
||||||
|
#:use-module (gnu packages m4)
|
||||||
#:use-module (gnu packages ncurses)
|
#:use-module (gnu packages ncurses)
|
||||||
#:use-module (gnu packages nettle)
|
#:use-module (gnu packages nettle)
|
||||||
#:use-module (gnu packages networking)
|
#:use-module (gnu packages networking)
|
||||||
|
@ -75,6 +84,7 @@
|
||||||
#:use-module (gnu packages polkit)
|
#:use-module (gnu packages polkit)
|
||||||
#:use-module (gnu packages protobuf)
|
#:use-module (gnu packages protobuf)
|
||||||
#:use-module (gnu packages python)
|
#:use-module (gnu packages python)
|
||||||
|
#:use-module (gnu packages python-crypto)
|
||||||
#:use-module (gnu packages python-web)
|
#:use-module (gnu packages python-web)
|
||||||
#:use-module (gnu packages python-xyz)
|
#:use-module (gnu packages python-xyz)
|
||||||
#:use-module (gnu packages pulseaudio)
|
#:use-module (gnu packages pulseaudio)
|
||||||
|
@ -82,6 +92,7 @@
|
||||||
#:use-module (gnu packages sdl)
|
#:use-module (gnu packages sdl)
|
||||||
#:use-module (gnu packages sphinx)
|
#:use-module (gnu packages sphinx)
|
||||||
#:use-module (gnu packages spice)
|
#:use-module (gnu packages spice)
|
||||||
|
#:use-module (gnu packages ssh)
|
||||||
#:use-module (gnu packages texinfo)
|
#:use-module (gnu packages texinfo)
|
||||||
#:use-module (gnu packages textutils)
|
#:use-module (gnu packages textutils)
|
||||||
#:use-module (gnu packages tls)
|
#:use-module (gnu packages tls)
|
||||||
|
@ -349,6 +360,390 @@ server and embedded PowerPC, and S390 guests.")
|
||||||
"usbredir" "libdrm" "libepoxy" "pulseaudio" "vde2"
|
"usbredir" "libdrm" "libepoxy" "pulseaudio" "vde2"
|
||||||
"libcacard")))))
|
"libcacard")))))
|
||||||
|
|
||||||
|
(define (system->qemu-target system)
|
||||||
|
(cond
|
||||||
|
((string-prefix? "i686" system)
|
||||||
|
"qemu-system-i386")
|
||||||
|
((string-prefix? "arm" system)
|
||||||
|
"qemu-system-arm")
|
||||||
|
(else
|
||||||
|
(string-append "qemu-system-" (match (string-split system #\-)
|
||||||
|
((arch kernel) arch)
|
||||||
|
(_ system))))))
|
||||||
|
|
||||||
|
(define-public ganeti
|
||||||
|
(package
|
||||||
|
(name "ganeti")
|
||||||
|
;; Note: we use a pre-release for Python 3 compatibility as well as many
|
||||||
|
;; other fixes.
|
||||||
|
(version "3.0.0beta1-24-g024cc9fa2")
|
||||||
|
(source (origin
|
||||||
|
(method git-fetch)
|
||||||
|
(uri (git-reference
|
||||||
|
(url "https://github.com/ganeti/ganeti")
|
||||||
|
(commit (string-append "v" version))))
|
||||||
|
(sha256
|
||||||
|
(base32 "1ll34qd2mifni3bhg7cnir3xfnkafig8ch33qndqwrsby0y5ssia"))
|
||||||
|
(file-name (git-file-name name version))
|
||||||
|
(patches (search-patches "ganeti-shepherd-support.patch"
|
||||||
|
"ganeti-shepherd-master-failover.patch"
|
||||||
|
"ganeti-deterministic-manual.patch"
|
||||||
|
"ganeti-drbd-compat.patch"
|
||||||
|
"ganeti-os-disk-size.patch"
|
||||||
|
"ganeti-haskell-pythondir.patch"
|
||||||
|
"ganeti-disable-version-symlinks.patch"
|
||||||
|
"ganeti-preserve-PYTHONPATH.patch"))))
|
||||||
|
(build-system gnu-build-system)
|
||||||
|
(arguments
|
||||||
|
`(#:imported-modules (,@%gnu-build-system-modules
|
||||||
|
(guix build haskell-build-system)
|
||||||
|
(guix build python-build-system))
|
||||||
|
#:modules (,@%gnu-build-system-modules
|
||||||
|
((guix build haskell-build-system) #:prefix haskell:)
|
||||||
|
((guix build python-build-system) #:select (python-version))
|
||||||
|
(ice-9 rdelim))
|
||||||
|
|
||||||
|
;; The default test target includes a lot of checks that are only really
|
||||||
|
;; relevant for developers such as NEWS file checking, line lengths, etc.
|
||||||
|
;; We are only interested in the "py-tests" and "hs-tests" targets: this
|
||||||
|
;; is the closest we've got even though it includes a little more.
|
||||||
|
#:test-target "check-TESTS"
|
||||||
|
|
||||||
|
#:configure-flags
|
||||||
|
(list "--localstatedir=/var"
|
||||||
|
"--sharedstatedir=/var"
|
||||||
|
"--sysconfdir=/etc"
|
||||||
|
"--enable-haskell-tests"
|
||||||
|
|
||||||
|
;; By default, the build system installs everything to versioned
|
||||||
|
;; directories such as $libdir/3.0 and relies on a $libdir/default
|
||||||
|
;; symlink pointed from /etc/ganeti/{lib,share} to actually function.
|
||||||
|
;; This is done to accommodate installing multiple versions in
|
||||||
|
;; parallel, but is of little use to us as Guix users can just
|
||||||
|
;; roll back and forth. Thus, disable it for simplicity.
|
||||||
|
"--disable-version-links"
|
||||||
|
|
||||||
|
;; Ganeti can optionally take control over SSH host keys and
|
||||||
|
;; distribute them to nodes as they are added, and also rotate keys
|
||||||
|
;; with 'gnt-cluster renew-crypto --new-ssh-keys'. Thus it needs to
|
||||||
|
;; know how to restart the SSH daemon.
|
||||||
|
"--with-sshd-restart-command='herd restart ssh-daemon'"
|
||||||
|
|
||||||
|
;; Look for OS definitions in this directory by default. It can
|
||||||
|
;; be changed in the cluster configuration.
|
||||||
|
"--with-os-search-path=/run/current-system/profile/share/ganeti/os"
|
||||||
|
|
||||||
|
;; The default QEMU executable to use. We don't use the package
|
||||||
|
;; here because this entry is stored in the cluster configuration.
|
||||||
|
(string-append "--with-kvm-path=/run/current-system/profile/bin/"
|
||||||
|
,(system->qemu-target (%current-system))))
|
||||||
|
#:phases
|
||||||
|
(modify-phases %standard-phases
|
||||||
|
(add-after 'unpack 'create-vcs-version
|
||||||
|
(lambda _
|
||||||
|
;; If we are building from a git checkout, we need to create a
|
||||||
|
;; 'vcs-version' file manually because the build system does
|
||||||
|
;; not have access to the git repository information.
|
||||||
|
(unless (file-exists? "vcs-version")
|
||||||
|
(call-with-output-file "vcs-version"
|
||||||
|
(lambda (port)
|
||||||
|
(format port "v~a~%" ,version))))
|
||||||
|
#t))
|
||||||
|
(add-after 'unpack 'patch-absolute-file-names
|
||||||
|
(lambda _
|
||||||
|
(substitute* '("lib/utils/process.py"
|
||||||
|
"lib/utils/text.py"
|
||||||
|
"src/Ganeti/Constants.hs"
|
||||||
|
"src/Ganeti/HTools/CLI.hs"
|
||||||
|
"test/py/ganeti.config_unittest.py"
|
||||||
|
"test/py/ganeti.hooks_unittest.py"
|
||||||
|
"test/py/ganeti.utils.process_unittest.py"
|
||||||
|
"test/py/ganeti.utils.text_unittest.py"
|
||||||
|
"test/py/ganeti.utils.wrapper_unittest.py")
|
||||||
|
(("/bin/sh") (which "sh"))
|
||||||
|
(("/bin/bash") (which "bash"))
|
||||||
|
(("/usr/bin/env") (which "env"))
|
||||||
|
(("/bin/true") (which "true")))
|
||||||
|
|
||||||
|
;; This script is called by the node daemon at startup to perform
|
||||||
|
;; sanity checks on the cluster IP addresses, and it is also used
|
||||||
|
;; in a master-failover scenario. Add absolute references to
|
||||||
|
;; avoid propagating these executables.
|
||||||
|
(substitute* "tools/master-ip-setup"
|
||||||
|
(("arping") (which "arping"))
|
||||||
|
(("ndisc6") (which "ndisc6"))
|
||||||
|
(("fping") (which "fping"))
|
||||||
|
(("grep") (which "grep"))
|
||||||
|
(("ip addr") (string-append (which "ip") " addr")))
|
||||||
|
#t))
|
||||||
|
(add-after 'unpack 'override-builtin-PATH
|
||||||
|
(lambda _
|
||||||
|
;; Ganeti runs OS install scripts and similar with a built-in
|
||||||
|
;; hard coded PATH. Patch so it works on Guix System.
|
||||||
|
(substitute* "src/Ganeti/Constants.hs"
|
||||||
|
(("/sbin:/bin:/usr/sbin:/usr/bin")
|
||||||
|
"/run/setuid-programs:/run/current-system/profile/sbin:\
|
||||||
|
/run/current-system/profile/bin"))
|
||||||
|
#t))
|
||||||
|
(add-after 'bootstrap 'patch-sphinx-version-detection
|
||||||
|
(lambda _
|
||||||
|
;; The build system runs 'sphinx-build --version' to verify that
|
||||||
|
;; the Sphinx is recent enough, but does not expect the
|
||||||
|
;; .sphinx-build-real executable name created by the Sphinx wrapper.
|
||||||
|
(substitute* "configure"
|
||||||
|
(("\\$SPHINX --version 2>&1")
|
||||||
|
"$SPHINX --version 2>&1 | sed 's/.sphinx-build-real/sphinx-build/g'"))
|
||||||
|
#t))
|
||||||
|
|
||||||
|
;; The build system invokes Cabal and GHC, which do not work with
|
||||||
|
;; GHC_PACKAGE_PATH: <https://github.com/haskell/cabal/issues/3728>.
|
||||||
|
;; Tweak the build system to do roughly what haskell-build-system does.
|
||||||
|
(add-before 'configure 'configure-haskell
|
||||||
|
(assoc-ref haskell:%standard-phases 'setup-compiler))
|
||||||
|
(add-after 'configure 'do-not-use-GHC_PACKAGE_PATH
|
||||||
|
(lambda _
|
||||||
|
(unsetenv "GHC_PACKAGE_PATH")
|
||||||
|
(substitute* "Makefile"
|
||||||
|
(("\\$\\(CABAL\\)")
|
||||||
|
"$(CABAL) --package-db=../package.conf.d")
|
||||||
|
(("\\$\\(GHC\\)")
|
||||||
|
"$(GHC) -package-db=../package.conf.d"))
|
||||||
|
#t))
|
||||||
|
|
||||||
|
(add-after 'configure 'fix-installation-directories
|
||||||
|
(lambda _
|
||||||
|
(substitute* "Makefile"
|
||||||
|
;; Do not attempt to create /var during install.
|
||||||
|
(("\\$\\(DESTDIR\\)\\$\\{localstatedir\\}")
|
||||||
|
"$(DESTDIR)${prefix}${localstatedir}")
|
||||||
|
;; Similarly, do not attempt to install the sample ifup scripts
|
||||||
|
;; to /etc/ganeti.
|
||||||
|
(("\\$\\(DESTDIR\\)\\$\\(ifupdir\\)")
|
||||||
|
"$(DESTDIR)${prefix}$(ifupdir)"))
|
||||||
|
#t))
|
||||||
|
(add-before 'build 'adjust-tests
|
||||||
|
(lambda _
|
||||||
|
;; Disable tests that can not run. Do it early to prevent
|
||||||
|
;; touching the Makefile later and triggering a needless rebuild.
|
||||||
|
(substitute* "Makefile"
|
||||||
|
;; These tests expect the presence of a 'root' user (via
|
||||||
|
;; ganeti/runtime.py), which fails in the build environment.
|
||||||
|
(("test/py/ganeti\\.asyncnotifier_unittest\\.py") "")
|
||||||
|
(("test/py/ganeti\\.backend_unittest\\.py") "")
|
||||||
|
(("test/py/ganeti\\.daemon_unittest\\.py") "")
|
||||||
|
(("test/py/ganeti\\.tools\\.ensure_dirs_unittest\\.py") "")
|
||||||
|
(("test/py/ganeti\\.utils\\.io_unittest-runasroot\\.py") "")
|
||||||
|
;; Disable the bash_completion test, as it requires the full
|
||||||
|
;; bash instead of bash-minimal.
|
||||||
|
(("test/py/bash_completion\\.bash")
|
||||||
|
"")
|
||||||
|
;; This test requires networking.
|
||||||
|
(("test/py/import-export_unittest\\.bash")
|
||||||
|
""))
|
||||||
|
|
||||||
|
;; Many of the Makefile targets reset PYTHONPATH before running
|
||||||
|
;; the Python interpreter, which does not work very well for us.
|
||||||
|
(substitute* "Makefile"
|
||||||
|
(("PYTHONPATH=")
|
||||||
|
(string-append "PYTHONPATH=" (getenv "PYTHONPATH") ":")))
|
||||||
|
#t))
|
||||||
|
(add-after 'build 'build-bash-completions
|
||||||
|
(lambda _
|
||||||
|
(let ((orig-pythonpath (getenv "PYTHONPATH")))
|
||||||
|
(setenv "PYTHONPATH" (string-append ".:" orig-pythonpath))
|
||||||
|
(invoke "./autotools/build-bash-completion")
|
||||||
|
(setenv "PYTHONPATH" orig-pythonpath)
|
||||||
|
#t)))
|
||||||
|
(add-before 'check 'pre-check
|
||||||
|
(lambda* (#:key inputs #:allow-other-keys)
|
||||||
|
;; Set TZDIR so that time zones are found.
|
||||||
|
(setenv "TZDIR" (string-append (assoc-ref inputs "tzdata")
|
||||||
|
"/share/zoneinfo"))
|
||||||
|
|
||||||
|
;; This test checks whether PYTHONPATH is untouched, and extends
|
||||||
|
;; it to include test directories if so. Add an else branch for
|
||||||
|
;; our modified PYTHONPATH, in order to prevent a confusing test
|
||||||
|
;; failure where expired certificates are not cleaned because
|
||||||
|
;; check-cert-expired is silently crashing.
|
||||||
|
(substitute* "test/py/ganeti-cleaner_unittest.bash"
|
||||||
|
(("then export PYTHONPATH=(.*)" all testpath)
|
||||||
|
(string-append all "else export PYTHONPATH="
|
||||||
|
(getenv "PYTHONPATH") ":" testpath "\n")))
|
||||||
|
|
||||||
|
(substitute* "test/py/ganeti.utils.process_unittest.py"
|
||||||
|
;; This test attempts to run an executable with
|
||||||
|
;; RunCmd(..., reset_env=True), which fails because the default
|
||||||
|
;; PATH from Constants.hs does not exist in the build container.
|
||||||
|
((".*def testResetEnv.*" all)
|
||||||
|
(string-append " @unittest.skipIf(True, "
|
||||||
|
"\"cannot reset env in the build container\")\n"
|
||||||
|
all))
|
||||||
|
|
||||||
|
;; XXX: Somehow this test fails in the build container, but
|
||||||
|
;; works in 'guix environment -C', even without /bin/sh?
|
||||||
|
((".*def testPidFile.*" all)
|
||||||
|
(string-append " @unittest.skipIf(True, "
|
||||||
|
"\"testPidFile fails in the build container\")\n"
|
||||||
|
all)))
|
||||||
|
|
||||||
|
;; XXX: Why are these links not added automatically.
|
||||||
|
(with-directory-excursion "test/hs"
|
||||||
|
(for-each (lambda (file)
|
||||||
|
(symlink "../../src/htools" file))
|
||||||
|
'("hspace" "hscan" "hinfo" "hbal" "hroller"
|
||||||
|
"hcheck" "hail" "hsqueeze")))
|
||||||
|
#t))
|
||||||
|
(add-after 'install 'install-bash-completions
|
||||||
|
(lambda* (#:key outputs #:allow-other-keys)
|
||||||
|
(let* ((out (assoc-ref outputs "out"))
|
||||||
|
(compdir (string-append out "/etc/bash_completion.d")))
|
||||||
|
(mkdir-p compdir)
|
||||||
|
(copy-file "doc/examples/bash_completion"
|
||||||
|
(string-append compdir "/ganeti"))
|
||||||
|
;; The one file contains completions for many different
|
||||||
|
;; executables. Create symlinks for found completions.
|
||||||
|
(with-directory-excursion compdir
|
||||||
|
(for-each
|
||||||
|
(lambda (prog) (symlink "ganeti" prog))
|
||||||
|
(call-with-input-file "ganeti"
|
||||||
|
(lambda (port)
|
||||||
|
(let loop ((line (read-line port))
|
||||||
|
(progs '()))
|
||||||
|
(if (eof-object? line)
|
||||||
|
progs
|
||||||
|
(if (string-prefix? "complete" line)
|
||||||
|
(loop (read-line port)
|
||||||
|
;; Extract "prog" from lines of the form:
|
||||||
|
;; "complete -F _prog -o filenames prog".
|
||||||
|
;; Note that 'burnin' is listed with the
|
||||||
|
;; absolute file name, which is why we
|
||||||
|
;; run everything through 'basename'.
|
||||||
|
(cons (basename (car (reverse (string-split
|
||||||
|
line #\ ))))
|
||||||
|
progs))
|
||||||
|
(loop (read-line port) progs))))))))
|
||||||
|
#t)))
|
||||||
|
;; Wrap all executables with PYTHONPATH. We can't borrow the phase
|
||||||
|
;; from python-build-system because we also need to wrap the scripts
|
||||||
|
;; in $out/lib/ganeti such as "node-daemon-setup".
|
||||||
|
(add-after 'install 'wrap
|
||||||
|
(lambda* (#:key inputs outputs #:allow-other-keys)
|
||||||
|
(let* ((out (assoc-ref outputs "out"))
|
||||||
|
(sbin (string-append out "/sbin"))
|
||||||
|
(lib (string-append out "/lib"))
|
||||||
|
(python (assoc-ref inputs "python"))
|
||||||
|
(major+minor (python-version python))
|
||||||
|
(PYTHONPATH (string-append lib "/python" major+minor
|
||||||
|
"/site-packages:"
|
||||||
|
(getenv "PYTHONPATH"))))
|
||||||
|
(define (shell-script? file)
|
||||||
|
(call-with-ascii-input-file file
|
||||||
|
(lambda (port)
|
||||||
|
(let ((shebang (false-if-exception (read-line port))))
|
||||||
|
(and shebang
|
||||||
|
(string-prefix? "#!" shebang)
|
||||||
|
(or (string-contains shebang "/bin/bash")
|
||||||
|
(string-contains shebang "/bin/sh")))))))
|
||||||
|
|
||||||
|
(define (wrap? file)
|
||||||
|
;; Do not wrap shell scripts because some are meant to be
|
||||||
|
;; sourced, which breaks if they are wrapped. We do wrap
|
||||||
|
;; the Haskell executables because some call out to Python
|
||||||
|
;; directly.
|
||||||
|
(and (executable-file? file)
|
||||||
|
(not (symbolic-link? file))
|
||||||
|
(not (shell-script? file))))
|
||||||
|
|
||||||
|
(for-each (lambda (file)
|
||||||
|
(wrap-program file
|
||||||
|
`("PYTHONPATH" ":" prefix (,PYTHONPATH))))
|
||||||
|
(filter wrap?
|
||||||
|
(append (find-files (string-append lib "/ganeti"))
|
||||||
|
(find-files sbin))))
|
||||||
|
#t))))))
|
||||||
|
(native-inputs
|
||||||
|
`(("haskell" ,ghc)
|
||||||
|
("cabal" ,cabal-install)
|
||||||
|
("m4" ,m4)
|
||||||
|
|
||||||
|
;; These inputs are necessary to bootstrap the package, because we
|
||||||
|
;; have patched the build system.
|
||||||
|
("autoconf" ,autoconf)
|
||||||
|
("automake" ,automake)
|
||||||
|
|
||||||
|
;; For the documentation.
|
||||||
|
("python-docutils" ,python-docutils)
|
||||||
|
("sphinx" ,python-sphinx)
|
||||||
|
("pandoc" ,ghc-pandoc)
|
||||||
|
("dot" ,graphviz)
|
||||||
|
|
||||||
|
;; Test dependencies.
|
||||||
|
("fakeroot" ,fakeroot)
|
||||||
|
("ghc-temporary" ,ghc-temporary)
|
||||||
|
("ghc-test-framework" ,ghc-test-framework)
|
||||||
|
("ghc-test-framework-hunit" ,ghc-test-framework-hunit)
|
||||||
|
("ghc-test-framework-quickcheck2" ,ghc-test-framework-quickcheck2)
|
||||||
|
("python-mock" ,python-mock)
|
||||||
|
("python-pyyaml" ,python-pyyaml)
|
||||||
|
("openssh" ,openssh)
|
||||||
|
("procps" ,procps)
|
||||||
|
("shelltestrunner" ,shelltestrunner)
|
||||||
|
("tzdata" ,tzdata-for-tests)))
|
||||||
|
(inputs
|
||||||
|
`(("arping" ,iputils) ;must be the iputils version
|
||||||
|
("curl" ,curl)
|
||||||
|
("fping" ,fping)
|
||||||
|
("iproute2" ,iproute)
|
||||||
|
("ndisc6" ,ndisc6)
|
||||||
|
("socat" ,socat)
|
||||||
|
("qemu" ,qemu-minimal) ;for qemu-img
|
||||||
|
("ghc-attoparsec" ,ghc-attoparsec)
|
||||||
|
("ghc-base64-bytestring" ,ghc-base64-bytestring)
|
||||||
|
("ghc-cryptonite" ,ghc-cryptonite)
|
||||||
|
("ghc-curl" ,ghc-curl)
|
||||||
|
("ghc-hinotify" ,ghc-hinotify)
|
||||||
|
("ghc-hslogger" ,ghc-hslogger)
|
||||||
|
("ghc-json" ,ghc-json)
|
||||||
|
("ghc-lens" ,ghc-lens)
|
||||||
|
("ghc-lifted-base" ,ghc-lifted-base)
|
||||||
|
("ghc-network" ,ghc-network)
|
||||||
|
("ghc-old-time" ,ghc-old-time)
|
||||||
|
("ghc-psqueue" ,ghc-psqueue)
|
||||||
|
("ghc-regex-pcre" ,ghc-regex-pcre)
|
||||||
|
("ghc-utf8-string" ,ghc-utf8-string)
|
||||||
|
("ghc-zlib" ,ghc-zlib)
|
||||||
|
|
||||||
|
;; For the optional metadata daemon.
|
||||||
|
("ghc-snap-core" ,ghc-snap-core)
|
||||||
|
("ghc-snap-server" ,ghc-snap-server)
|
||||||
|
|
||||||
|
("python" ,python)
|
||||||
|
("python-pyopenssl" ,python-pyopenssl)
|
||||||
|
("python-simplejson" ,python-simplejson)
|
||||||
|
("python-pyparsing" ,python-pyparsing)
|
||||||
|
("python-pyinotify" ,python-pyinotify)
|
||||||
|
("python-pycurl" ,python-pycurl)
|
||||||
|
("python-bitarray" ,python-bitarray)
|
||||||
|
("python-paramiko" ,python-paramiko)
|
||||||
|
("python-psutil" ,python-psutil)))
|
||||||
|
(home-page "http://www.ganeti.org/")
|
||||||
|
(synopsis "Cluster-based virtual machine management system")
|
||||||
|
(description
|
||||||
|
"Ganeti is a virtual machine management tool built on top of existing
|
||||||
|
virtualization technologies such as Xen or KVM. Ganeti controls:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item Disk creation management;
|
||||||
|
@item Operating system installation for instances (in co-operation with
|
||||||
|
OS-specific install scripts); and
|
||||||
|
@item Startup, shutdown, and failover between physical systems.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
Ganeti is designed to facilitate cluster management of virtual servers and
|
||||||
|
to provide fast and simple recovery after physical failures, using
|
||||||
|
commodity hardware.")
|
||||||
|
(license license:bsd-2)))
|
||||||
|
|
||||||
(define-public libosinfo
|
(define-public libosinfo
|
||||||
(package
|
(package
|
||||||
(name "libosinfo")
|
(name "libosinfo")
|
||||||
|
|
Reference in New Issue