Commit 3a44fd5f authored by Iustin Pop's avatar Iustin Pop
Browse files

Merge branch 'stable-2.6'



* stable-2.6: (26 commits)
  Bump version for beta 2 release
  Fix epydoc raises L{...} usage
  Fix race condition in test for *FileID functions
  Move KVM keymap from GenerateRuntime to ExecuteRuntime
  Add the keymap directory to the list of runtime KVM dirs
  Fix make -n use
  Enable hlint in lint and reorganise this target
  Improve error message for auto-promote/node modify
  Fix QA import of existing instances
  Remove one obsolete hlint override
  Fix prefix bug in Haskell ssconf implementation
  Move the ssconf file prefix constant to constants.py
  QA: Add configuration options for static MAC address
  QA: Ignore tags using regular expression
  Fix parallel build failures
  QA: Add default setting for tests
  QA: add toggle for fewer common instance tests
  QA: stop logging SSH arguments for each invocation
  Switch QA to tty-less mode
  Fix a type issue and bad logic in cluster verification
  ...
Signed-off-by: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarRené Nussbaumer <rn@google.com>
parents 4a78c361 1ad80d57
......@@ -160,8 +160,8 @@ CLEANFILES = \
.hpc/*.mix htools/*.tix \
doc/hs-lint.html
# BUILT_SOURCES should only be used as a dependency on phony targets. Otherwise
# it'll cause the target to rebuild every time.
# BUILT_SOURCES should only be used as a dependency on phony
# targets. Otherwise it'll cause the target to rebuild every time.
BUILT_SOURCES = \
$(built_base_sources) \
$(BUILT_PYTHON_SOURCES) \
......@@ -999,13 +999,17 @@ man/footer.html: man/footer.rst
$(PANDOC) -f rst -t html -o $@ $<
man/%.gen: man/%.rst lib/query.py lib/build/sphinx_ext.py \
lib/build/shell_example_lexer.py
lib/build/shell_example_lexer.py \
| $(RUN_IN_TEMPDIR) $(BUILT_PYTHON_SOURCES)
@echo "Checking $< for hardcoded paths..."
@if grep -nEf autotools/wrong-hardcoded-paths $<; then \
echo "Man page $< has harcoded paths (see above)!" 1>&2 ; \
exit 1; \
fi
PYTHONPATH=. $(RUN_IN_TEMPDIR) $(CURDIR)/$(DOCPP) < $< > $@
set -e ; \
trap 'echo auto-removing $@; rm $@' EXIT; \
PYTHONPATH=. $(RUN_IN_TEMPDIR) $(CURDIR)/$(DOCPP) < $< > $@ ;\
trap - EXIT
man/%.7.in man/%.8.in man/%.1.in: man/%.gen man/footer.man
@test -n "$(PANDOC)" || \
......@@ -1048,12 +1052,16 @@ vcs-version:
echo "Cannot auto-generate $@ file"; exit 1; \
fi
.PHONY: clean-vcs-version
clean-vcs-version:
rm -f vcs-version
.PHONY: regen-vcs-version
regen-vcs-version:
set -e; \
cd $(srcdir); \
if test -d .git; then \
rm -f vcs-version; \
$(MAKE) clean-vcs-version; \
$(MAKE) vcs-version; \
fi
......@@ -1138,6 +1146,7 @@ lib/_autoconf.py: Makefile | lib/.dir
echo "ENABLE_CONFD = $(ENABLE_CONFD)"; \
echo "PY_CONFD = $(PY_CONFD)"; \
echo "HS_CONFD = $(HS_CONFD)"; \
echo "XEN_CMD = '$(XEN_CMD)'"; \
} > $@
lib/_vcsversion.py: Makefile vcs-version | lib/.dir
......@@ -1309,28 +1318,43 @@ PEP8_IGNORE = E111,E261,E501
# For excluding pep8 expects filenames only, not whole paths
PEP8_EXCLUDE = $(subst $(space),$(comma),$(strip $(notdir $(BUILT_PYTHON_SOURCES))))
LINT_TARGETS = pylint pylint-qa
if HAS_PEP8
LINT_TARGETS += pep8
endif
if HAS_HLINT
LINT_TARGETS += hlint
endif
.PHONY: lint
lint: $(BUILT_SOURCES)
lint: $(LINT_TARGETS)
.PHONY: pylint
pylint: $(BUILT_SOURCES)
@test -n "$(PYLINT)" || { echo 'pylint' not found during configure; exit 1; }
if test -z "$(PEP8)"; then \
echo '"pep8" not found during configure' >&2; \
else \
$(PEP8) --repeat --ignore='$(PEP8_IGNORE)' --exclude='$(PEP8_EXCLUDE)' \
$(pep8_python_code); \
fi
$(PYLINT) $(LINT_OPTS) $(lint_python_code)
.PHONY: pylint-qa
pylint-qa: $(BUILT_SOURCES)
@test -n "$(PYLINT)" || { echo 'pylint' not found during configure; exit 1; }
cd $(top_srcdir)/qa && \
PYTHONPATH=$(abs_top_srcdir) $(PYLINT) $(LINT_OPTS) \
--rcfile ../pylintrc $(patsubst qa/%.py,%,$(qa_scripts))
.PHONY: pep8
pep8: $(BUILT_SOURCES)
@test -n "$(PEP8)" || { echo 'pep8' not found during configure; exit 1; }
$(PEP8) --ignore='$(PEP8_IGNORE)' --exclude='$(PEP8_EXCLUDE)' \
--repeat $(pep8_python_code)
.PHONY: hlint
hlint: $(HS_BUILT_SRCS) htools/lint-hints.hs
@test -n "$(HLINT)" || { echo 'hlint' not found during configure; exit 1; }
if tty -s; then C="-c"; else C=""; fi; \
hlint --report=doc/hs-lint.html --cross $$C \
$(HLINT) --report=doc/hs-lint.html --cross $$C \
--ignore "Use first" \
--ignore "Use comparing" \
--ignore "Use on" \
--ignore "Use Control.Exception.catch" \
--ignore "Reduce duplication" \
--hint htools/lint-hints \
$(filter-out htools/Ganeti/THH.hs,$(HS_LIB_SRCS))
......@@ -1338,8 +1362,8 @@ hlint: $(HS_BUILT_SRCS) htools/lint-hints.hs
# a dist hook rule for updating the vcs-version file; this is
# hardcoded due to where it needs to build the file...
dist-hook:
$(MAKE) regen-vcs-version && \
rm -f $(top_distdir)/vcs-version && \
$(MAKE) regen-vcs-version
rm -f $(top_distdir)/vcs-version
cp -p $(srcdir)/vcs-version $(top_distdir)
# a distcheck hook rule for catching revision control directories
......@@ -1465,7 +1489,8 @@ py-coverage: $(BUILT_SOURCES) $(python_tests)
.PHONY: hs-coverage
hs-coverage: $(haskell_tests) htools/hpc-htools
rm -f *.tix && $(MAKE) hs-check
rm -f *.tix
$(MAKE) hs-check
@mkdir_p@ $(COVERAGE_HS_DIR)
hpc combine $(HPCEXCL) test.tix hpc-htools.tix > coverage-htools.tix
hpc markup --destdir=$(COVERAGE_HS_DIR) coverage-htools.tix
......
......@@ -2,10 +2,10 @@ News
====
Version 2.6.0 beta1
Version 2.6.0 beta2
-------------------
*(Released Wed, 23 Mar 2011)*
*(Released Mon, 11 Jun 2012)*
New features
~~~~~~~~~~~~
......@@ -256,6 +256,10 @@ Python 2.7 is better supported, and after Ganeti 2.6 we will investigate
whether to still support Python 2.4 or move to Python 2.6 as minimum
required version.
Support for Fedora has been slightly improved; the provided example
init.d script should work better on it and the INSTALL file should
document the needed dependencies.
Internal changes
~~~~~~~~~~~~~~~~
......@@ -291,6 +295,30 @@ verification. This will remove some rare but hard to diagnose errors in
import-export.
Version 2.6.0 beta1
-------------------
*(Released Wed, 23 May 2012)*
First beta release of 2.6. The following changes were done from beta1 to
beta2:
- integrated patch for distributions without ``start-stop-daemon``
- adapted example init.d script to work on Fedora
- fixed log handling in Haskell daemons
- adapted checks in the watcher for pycurl linked against libnss
- add partial support for ``xl`` instead of ``xm`` for Xen
- fixed a type issue in cluster verification
- fixed ssconf handling in the Haskell code (was breaking confd in IPv6
clusters)
Plus integrated fixes from the 2.5 branch:
- fixed ``kvm-ifup`` to use ``/bin/bash``
- fixed parallel build failures
- KVM live migration when using a custom keymap
Version 2.5.1
-------------
......
......@@ -2,7 +2,7 @@
m4_define([gnt_version_major], [2])
m4_define([gnt_version_minor], [6])
m4_define([gnt_version_revision], [0])
m4_define([gnt_version_suffix], [~beta1])
m4_define([gnt_version_suffix], [~beta2])
m4_define([gnt_version_full],
m4_format([%d.%d.%d%s],
gnt_version_major, gnt_version_minor,
......@@ -98,6 +98,19 @@ AC_ARG_WITH([xen-initrd],
[xen_initrd="/boot/initrd-3-xenU"])
AC_SUBST(XEN_INITRD, $xen_initrd)
# --with-xen-cmd=...
AC_ARG_WITH([xen-cmd],
[AS_HELP_STRING([--with-xen-cmd=CMD],
[Sets the xen cli interface command (default is xm)]
)],
[xen_cmd="$withval"],
[xen_cmd="xm"])
AC_SUBST(XEN_CMD, $xen_cmd)
if ! test "$XEN_CMD" = xl -o "$XEN_CMD" = xm; then
AC_MSG_ERROR([Unsupported xen command specified])
fi
# --with-kvm-kernel=...
AC_ARG_WITH([kvm-kernel],
[AS_HELP_STRING([--with-kvm-kernel=PATH],
......@@ -374,6 +387,7 @@ if test -z "$PEP8"
then
AC_MSG_WARN([pep8 not found, checking code will not be complete])
fi
AM_CONDITIONAL([HAS_PEP8], [test "$PEP8"])
# Check for socat
AC_ARG_VAR(SOCAT, [socat path])
......@@ -505,6 +519,14 @@ if test "$HADDOCK" && test "$HSCOLOUR"; then
fi
AC_SUBST(HTOOLS_APIDOC)
# Check for hlint
HLINT=no
AC_ARG_VAR(HLINT, [hlint path])
AC_PATH_PROG(HLINT, [hlint], [])
if test -z "$HLINT"; then
AC_MSG_WARN([hlint not found, checking code will not be possible])
fi
fi # end if enable_htools, define automake conditions
if test "$HTOOLS" != "yes" && test "$HS_CONFD" = "True"; then
......@@ -515,6 +537,7 @@ fi
AM_CONDITIONAL([WANT_HTOOLS], [test x$HTOOLS = xyes])
AM_CONDITIONAL([WANT_HTOOLSTESTS], [test "x$GHC_PKG_QUICKCHECK" != x])
AM_CONDITIONAL([WANT_HTOOLSAPIDOC], [test x$HTOOLS_APIDOC = xyes])
AM_CONDITIONAL([HAS_HLINT], [test "$HLINT"])
# Check for fakeroot
AC_ARG_VAR(FAKEROOT_PATH, [fakeroot path])
......
......@@ -47,7 +47,7 @@ Use cases
We consider the following use cases:
- A virtualization cluster with FibreChannel shared storage, mapping at
leaste one LUN per instance, accessible by the whole cluster.
least one LUN per instance, accessible by the whole cluster.
- A virtualization cluster with instance images stored as files on an
NFS server.
- A virtualization cluster storing instance images on a Ceph volume.
......
......@@ -8,10 +8,11 @@ Documents Ganeti version 2.6
Introduction
------------
In order to allow customisation of operations, ganeti runs scripts
under ``/etc/ganeti/hooks`` based on certain rules.
In order to allow customisation of operations, Ganeti runs scripts in
sub-directories of ``@SYSCONFDIR@/ganeti/hooks``. These sub-directories
are named ``$hook-$phase.d``, where ``$phase`` is either ``pre`` or
``post`` and ``$hook`` matches the directory name given for a hook (e.g.
``cluster-verify-post.d`` or ``node-add-pre.d``).
This is similar to the ``/etc/network/`` structure present in Debian
for network interface handling.
......
......@@ -41,6 +41,7 @@ module Ganeti.HTools.QC
, testCLI
, testJSON
, testLUXI
, testSsconf
) where
import Test.QuickCheck
......@@ -58,6 +59,7 @@ import qualified Data.IntMap as IntMap
import qualified Ganeti.OpCodes as OpCodes
import qualified Ganeti.Jobs as Jobs
import qualified Ganeti.Luxi as Luxi
import qualified Ganeti.Ssconf as Ssconf
import qualified Ganeti.HTools.CLI as CLI
import qualified Ganeti.HTools.Cluster as Cluster
import qualified Ganeti.HTools.Container as Container
......@@ -1731,3 +1733,16 @@ prop_Luxi_CallEncoding op =
testSuite "LUXI"
[ 'prop_Luxi_CallEncoding
]
-- * Ssconf tests
instance Arbitrary Ssconf.SSKey where
arbitrary = elements [minBound..maxBound]
prop_Ssconf_filename key =
printTestCase "Key doesn't start with correct prefix" $
Ssconf.sSFilePrefix `isPrefixOf` Ssconf.keyToFilename (Just "") key
testSuite "Ssconf"
[ 'prop_Ssconf_filename
]
......@@ -30,6 +30,8 @@ module Ganeti.Ssconf
, sSKeyToRaw
, sSKeyFromRaw
, getPrimaryIPFamily
, keyToFilename
, sSFilePrefix
) where
import Ganeti.THH
......@@ -51,6 +53,10 @@ import Ganeti.HTools.Utils
maxFileSize :: Int
maxFileSize = 131072
-- | ssconf file prefix, re-exported from Constants.
sSFilePrefix :: FilePath
sSFilePrefix = C.ssconfFileprefix
$(declareSADT "SSKey"
[ ("SSClusterName", 'C.ssClusterName)
, ("SSClusterTags", 'C.ssClusterTags)
......@@ -80,7 +86,8 @@ $(declareSADT "SSKey"
keyToFilename :: Maybe FilePath -- ^ Optional config path override
-> SSKey -- ^ ssconf key
-> FilePath
keyToFilename optpath key = fromMaybe C.dataDir optpath </> sSKeyToRaw key
keyToFilename optpath key = fromMaybe C.dataDir optpath </>
sSFilePrefix ++ sSKeyToRaw key
-- | Runs an IO action while transforming any error into 'Bad'
-- values. It also accepts an optional value to use in case the error
......
......@@ -125,6 +125,7 @@ allTests =
, (fast, testCLI)
, (fast, testJSON)
, (fast, testLUXI)
, (fast, testSsconf)
, (slow, testCluster)
]
......
......@@ -3152,6 +3152,8 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
 
for instance in self.my_inst_names:
inst_config = self.my_inst_info[instance]
if inst_config.admin_state == constants.ADMINST_OFFLINE:
i_offline += 1
 
for nname in inst_config.all_nodes:
if nname not in node_image:
......@@ -3291,12 +3293,6 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
non_primary_inst = set(nimg.instances).difference(nimg.pinst)
 
for inst in non_primary_inst:
# FIXME: investigate best way to handle offline insts
if inst.admin_state == constants.ADMINST_OFFLINE:
if verbose:
feedback_fn("* Skipping offline instance %s" % inst.name)
i_offline += 1
continue
test = inst in self.all_inst_info
_ErrorIf(test, constants.CV_EINSTANCEWRONGNODE, inst,
"instance should not run on node %s", node_i.name)
......@@ -5929,7 +5925,8 @@ class LUNodeSetParams(LogicalUnit):
if mc_remaining < mc_should:
raise errors.OpPrereqError("Not enough master candidates, please"
" pass auto promote option to allow"
" promotion", errors.ECODE_STATE)
" promotion (--auto-promote or RAPI"
" auto_promote=True)", errors.ECODE_STATE)
 
self.old_flags = old_flags = (node.master_candidate,
node.drained, node.offline)
......
......@@ -267,7 +267,10 @@ EXPORT_CONF_FILE = "config.ini"
XEN_BOOTLOADER = _autoconf.XEN_BOOTLOADER
XEN_KERNEL = _autoconf.XEN_KERNEL
XEN_INITRD = _autoconf.XEN_INITRD
XEN_CMD = "xm"
XEN_CMD_XM = "xm"
XEN_CMD_XL = "xl"
# FIXME: This will be made configurable using hvparams in Ganeti 2.7
XEN_CMD = _autoconf.XEN_CMD
KVM_PATH = _autoconf.KVM_PATH
KVM_KERNEL = _autoconf.KVM_KERNEL
......@@ -1695,6 +1698,8 @@ RSS_DESCRIPTION = {
MAX_NICS = 8
MAX_DISKS = 16
# SSCONF file prefix
SSCONF_FILEPREFIX = "ssconf_"
# SSCONF keys
SS_CLUSTER_NAME = "cluster_name"
SS_CLUSTER_TAGS = "cluster_tags"
......
#
#
# Copyright (C) 2008, 2009, 2010, 2011 Google Inc.
# Copyright (C) 2008, 2009, 2010, 2011, 2012 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -420,7 +420,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
# a separate directory, called 'chroot-quarantine'.
_CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
_DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
_CHROOT_DIR, _CHROOT_QUARANTINE_DIR]
_CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
PARAMETERS = {
constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
......@@ -944,6 +944,13 @@ class KVMHypervisor(hv_base.BaseHypervisor):
def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
"""Generate KVM information to start an instance.
@attention: this function must not have any side-effects; for
example, it must not write to the filesystem, or read values
from the current system the are expected to differ between
nodes, since it is only run once at instance startup;
actions/kvm arguments that can vary between systems should be
done in L{_ExecuteKVMRuntime}
"""
# pylint: disable=R0914,R0915
_, v_major, v_min, _ = self._GetKVMVersion()
......@@ -1099,16 +1106,6 @@ class KVMHypervisor(hv_base.BaseHypervisor):
elif vnc_bind_address:
kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
keymap = hvp[constants.HV_KEYMAP]
if keymap:
keymap_path = self._InstanceKeymapFile(instance.name)
# If a keymap file is specified, KVM won't use its internal defaults. By
# first including the "en-us" layout, an error on loading the actual
# layout (e.g. because it can't be found) won't lead to a non-functional
# keyboard. A keyboard with incorrect keys is still better than none.
utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
kvm_cmd.extend(["-k", keymap_path])
if vnc_bind_address:
if netutils.IP4Address.IsValid(vnc_bind_address):
if instance.network_port > constants.VNC_BASE_PORT:
......@@ -1144,6 +1141,8 @@ class KVMHypervisor(hv_base.BaseHypervisor):
kvm_cmd.extend(["-vnc", vnc_arg])
elif spice_bind:
# FIXME: this is wrong here; the iface ip address differs
# between systems, so it should be done in _ExecuteKVMRuntime
if netutils.IsValidInterface(spice_bind):
# The user specified a network interface, we have to figure out the IP
# address.
......@@ -1314,7 +1313,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
raise errors.HypervisorError("Failed to start instance %s" % name)
def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
"""Execute a KVM cmd, after completing it with some last minute data
"""Execute a KVM cmd, after completing it with some last minute data.
@type incoming: tuple of strings
@param incoming: (target_host_ip, port)
......@@ -1345,6 +1344,16 @@ class KVMHypervisor(hv_base.BaseHypervisor):
if security_model == constants.HT_SM_USER:
kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
keymap = conf_hvp[constants.HV_KEYMAP]
if keymap:
keymap_path = self._InstanceKeymapFile(name)
# If a keymap file is specified, KVM won't use its internal defaults. By
# first including the "en-us" layout, an error on loading the actual
# layout (e.g. because it can't be found) won't lead to a non-functional
# keyboard. A keyboard with incorrect keys is still better than none.
utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
kvm_cmd.extend(["-k", keymap_path])
# We have reasons to believe changing something like the nic driver/type
# upon migration won't exactly fly with the instance kernel, so for nic
# related parameters we'll use up_hvp
......@@ -1538,7 +1547,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
@type text: string
@param text: output of kvm --help
@return: (version, v_maj, v_min, v_rev)
@raise L{errors.HypervisorError}: when the KVM version cannot be retrieved
@raise errors.HypervisorError: when the KVM version cannot be retrieved
"""
match = cls._VERSION_RE.search(text.splitlines()[0])
......@@ -1559,7 +1568,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
"""Return the installed KVM version.
@return: (version, v_maj, v_min, v_rev)
@raise L{errors.HypervisorError}: when the KVM version cannot be retrieved
@raise errors.HypervisorError: when the KVM version cannot be retrieved
"""
result = utils.RunCmd([constants.KVM_PATH, "--help"])
......
......@@ -537,13 +537,19 @@ class XenHypervisor(hv_base.BaseHypervisor):
" %s, cannot migrate" % (target, port))
# FIXME: migrate must be upgraded for transitioning to "xl" (xen 4.1).
# -l doesn't exist anymore
# -p doesn't exist anymore
# -C config_file must be passed
# This should be reworked in Ganeti 2.7
# ssh must recognize the key of the target host for the migration
args = [constants.XEN_CMD, "migrate", "-p", "%d" % port]
if live:
args.append("-l")
args = [constants.XEN_CMD, "migrate"]
if constants.XEN_CMD == constants.XEN_CMD_XM:
args.extend(["-p", "%d" % port])
if live:
args.append("-l")
elif constants.XEN_CMD == constants.XEN_CMD_XL:
args.extend(["-C", self._ConfigFileName(instance.name)])
else:
raise errors.HypervisorError("Unsupported xen command: %s" %
constants.XEN_CMD)
args.extend([instance.name, target])
result = utils.RunCmd(args)
if result.failed:
......
......@@ -256,6 +256,9 @@ def GenericCurlConfig(verbose=False, use_signal=False,
lcsslver = sslver.lower()
if lcsslver.startswith("openssl/"):
pass
elif lcsslver.startswith("nss/"):
# TODO: investigate compatibility beyond a simple test
pass
elif lcsslver.startswith("gnutls/"):
if capath:
raise Error("cURL linked against GnuTLS has no support for a"
......
#
#
# Copyright (C) 2006, 2007, 2008, 2010 Google Inc.
# Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -273,7 +273,6 @@ class SimpleStore(object):
- keys are restricted to predefined values
"""
_SS_FILEPREFIX = "ssconf_"
_VALID_KEYS = (
constants.SS_CLUSTER_NAME,
constants.SS_CLUSTER_TAGS,
......@@ -314,7 +313,7 @@ class SimpleStore(object):
raise errors.ProgrammerError("Invalid key requested from SSConf: '%s'"
% str(key))
filename = self._cfg_dir + "/" + self._SS_FILEPREFIX + key
filename = self._cfg_dir + "/" + constants.SSCONF_FILEPREFIX + key
return filename
def _ReadFile(self, key, default=None):
......
......@@ -464,7 +464,8 @@ def RunQa():
for use_client in [True, False]:
rapi_instance = RunTest(qa_rapi.TestRapiInstanceAdd, pnode,
use_client)
RunCommonInstanceTests(rapi_instance)
if qa_config.TestEnabled("instance-plain-rapi-common-tests"):
RunCommonInstanceTests(rapi_instance)
RunTest(qa_rapi.TestRapiInstanceRemove, rapi_instance, use_client)
del rapi_instance
......@@ -553,7 +554,12 @@ def main():
qa_config.Load(config_file)
qa_utils.StartMultiplexer(qa_config.GetMasterNode()["primary"])
primary = qa_config.GetMasterNode()["primary"]
qa_utils.StartMultiplexer(primary)
print ("SSH command for primary node: %s" %
utils.ShellQuoteArgs(qa_utils.GetSSHCommand(primary, "")))
print ("SSH command for other nodes: %s" %
utils.ShellQuoteArgs(qa_utils.GetSSHCommand("NODE", "")))
try:
RunQa()
finally:
......
......@@ -27,6 +27,9 @@
"# Script to check instance status": null,
"instance-check": null,
"# Regular expression to ignore existing tags": null,
"ignore-tags-re": null,
"nodes": [
{
"# Master node": null,
......@@ -42,10 +45,16 @@
"instances": [
{
"name": "xen-test-inst1"
"name": "xen-test-inst1",
"# Static MAC address": null,
"#nic.mac/0": "AA:00:00:11:11:11"
},
{
"name": "xen-test-inst2"
"name": "xen-test-inst2",
"# Static MAC address": null,
"#nic.mac/0": "AA:00:00:22:22:22"
}
],
......@@ -106,6 +115,7 @@
"instance-add-plain-disk": true,
"instance-add-drbd-disk": true,
"instance-convert-disk": true,
"instance-plain-rapi-common-tests": true,
"instance-export": true,
"instance-failover": true,
......
#
#
# Copyright (C) 2007, 2011 Google Inc.
# Copyright (C) 2007, 2011, 2012 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -154,6 +154,13 @@ def GetInstanceCheckScript():
return cfg.get(_INSTANCE_CHECK_KEY, None)
def GetInstanceNicMac(inst, default=None):
"""Returns MAC address for instance's network interface.
"""
return inst.get("nic.mac/0", default)
def GetMasterNode():
return cfg["nodes"][0]
......
......@@ -42,7 +42,7 @@ def _GetDiskStatePath(disk):
return "/sys/block/%s/device/state" % disk