Commit d82dec68 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Merge branch 'devel-2.7'



* devel-2.7:
  hv_*: Always return from Verify, style fixes
  _VerifyErrors()._Error() and _ErrorIf() are now consistent
  Handle the result of QueryGroups() correctly
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarBernardo Dal Seno <bdalseno@google.com>
parents 9842f020 cd04dfd2
......@@ -2027,6 +2027,10 @@ class _VerifyErrors(object):
"""
ltype = kwargs.get(self.ETYPE_FIELD, self.ETYPE_ERROR)
itype, etxt, _ = ecode
# If the error code is in the list of ignored errors, demote the error to a
# warning
if etxt in self.op.ignore_errors: # pylint: disable=E1101
ltype = self.ETYPE_WARNING
# first complete the msg
if args:
msg = msg % args
......@@ -2041,26 +2045,17 @@ class _VerifyErrors(object):
msg = "%s: %s%s: %s" % (ltype, itype, item, msg)
# and finally report it via the feedback_fn
self._feedback_fn(" - %s" % msg) # Mix-in. pylint: disable=E1101
# do not mark the operation as failed for WARN cases only
if ltype == self.ETYPE_ERROR:
self.bad = True
 
def _ErrorIf(self, cond, ecode, *args, **kwargs):
def _ErrorIf(self, cond, *args, **kwargs):
"""Log an error message if the passed condition is True.
 
"""
cond = (bool(cond)
or self.op.debug_simulate_errors) # pylint: disable=E1101
# If the error code is in the list of ignored errors, demote the error to a
# warning
(_, etxt, _) = ecode
if etxt in self.op.ignore_errors: # pylint: disable=E1101
kwargs[self.ETYPE_FIELD] = self.ETYPE_WARNING
if cond:
self._Error(ecode, *args, **kwargs)
# do not mark the operation as failed for WARN cases only
if kwargs.get(self.ETYPE_FIELD, self.ETYPE_ERROR) == self.ETYPE_ERROR:
self.bad = self.bad or cond
if (bool(cond)
or self.op.debug_simulate_errors): # pylint: disable=E1101
self._Error(*args, **kwargs)
 
 
class LUClusterVerify(NoHooksLU):
......
......@@ -266,6 +266,8 @@ class BaseHypervisor(object):
def Verify(self):
"""Verify the hypervisor.
@return: Problem description if something is wrong, C{None} otherwise
"""
raise NotImplementedError
......
......@@ -281,9 +281,13 @@ class ChrootManager(hv_base.BaseHypervisor):
For the chroot manager, it just checks the existence of the base dir.
@return: Problem description if something is wrong, C{None} otherwise
"""
if not os.path.exists(self._ROOT_DIR):
return "The required directory '%s' does not exist." % self._ROOT_DIR
if os.path.exists(self._ROOT_DIR):
return None
else:
return "The required directory '%s' does not exist" % self._ROOT_DIR
@classmethod
def PowercycleNode(cls):
......
......@@ -239,9 +239,13 @@ class FakeHypervisor(hv_base.BaseHypervisor):
For the fake hypervisor, it just checks the existence of the base
dir.
@return: Problem description if something is wrong, C{None} otherwise
"""
if not os.path.exists(self._ROOT_DIR):
return "The required directory '%s' does not exist." % self._ROOT_DIR
if os.path.exists(self._ROOT_DIR):
return None
else:
return "The required directory '%s' does not exist" % self._ROOT_DIR
@classmethod
def PowercycleNode(cls):
......
......@@ -2019,16 +2019,19 @@ class KVMHypervisor(hv_base.BaseHypervisor):
def Verify(self):
"""Verify the hypervisor.
Check that the binary exists.
Check that the required binaries exist.
@return: Problem description if something is wrong, C{None} otherwise
"""
# FIXME: this is the global kvm version, but the actual version can be
# customized as an hv parameter. we should use the nodegroup's default kvm
# path parameter here.
if not os.path.exists(constants.KVM_PATH):
return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
return "The KVM binary ('%s') does not exist" % constants.KVM_PATH
if not os.path.exists(constants.SOCAT_PATH):
return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
return "The socat binary ('%s') does not exist" % constants.SOCAT_PATH
return None
@classmethod
def CheckParameterSyntax(cls, hvparams):
......
......@@ -401,11 +401,15 @@ class LXCHypervisor(hv_base.BaseHypervisor):
def Verify(self):
"""Verify the hypervisor.
For the chroot manager, it just checks the existence of the base dir.
For the LXC manager, it just checks the existence of the base dir.
@return: Problem description if something is wrong, C{None} otherwise
"""
if not os.path.exists(self._ROOT_DIR):
return "The required directory '%s' does not exist." % self._ROOT_DIR
if os.path.exists(self._ROOT_DIR):
return None
else:
return "The required directory '%s' does not exist" % self._ROOT_DIR
@classmethod
def PowercycleNode(cls):
......
......@@ -435,11 +435,15 @@ class XenHypervisor(hv_base.BaseHypervisor):
For Xen, this verifies that the xend process is running.
@return: Problem description if something is wrong, C{None} otherwise
"""
result = utils.RunCmd([constants.XEN_CMD, "info"])
if result.failed:
return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
return None
@staticmethod
def _GetConfigFileDiskData(block_devices, blockdev_prefix):
"""Get disk directive for xen config file.
......
......@@ -1533,5 +1533,143 @@ class TestCheckOpportunisticLocking(unittest.TestCase):
cmdlib._CheckOpportunisticLocking(op)
class _OpTestVerifyErrors(opcodes.OpCode):
OP_PARAMS = [
opcodes._PDebugSimulateErrors,
opcodes._PErrorCodes,
opcodes._PIgnoreErrors,
]
class _LuTestVerifyErrors(cmdlib._VerifyErrors):
def __init__(self, **kwargs):
cmdlib._VerifyErrors.__init__(self)
self.op = _OpTestVerifyErrors(**kwargs)
self.op.Validate(True)
self.msglist = []
self._feedback_fn = self.msglist.append
self.bad = False
def DispatchCallError(self, which, *args, **kwargs):
if which:
self._Error(*args, **kwargs)
else:
self._ErrorIf(True, *args, **kwargs)
def CallErrorIf(self, c, *args, **kwargs):
self._ErrorIf(c, *args, **kwargs)
class TestVerifyErrors(unittest.TestCase):
# Fake cluster-verify error code structures; we use two arbitary real error
# codes to pass validation of ignore_errors
(_, _ERR1ID, _) = constants.CV_ECLUSTERCFG
_NODESTR = "node"
_NODENAME = "mynode"
_ERR1CODE = (_NODESTR, _ERR1ID, "Error one")
(_, _ERR2ID, _) = constants.CV_ECLUSTERCERT
_INSTSTR = "instance"
_INSTNAME = "myinstance"
_ERR2CODE = (_INSTSTR, _ERR2ID, "Error two")
# Arguments used to call _Error() or _ErrorIf()
_ERR1ARGS = (_ERR1CODE, _NODENAME, "Error1 is %s", "an error")
_ERR2ARGS = (_ERR2CODE, _INSTNAME, "Error2 has no argument")
# Expected error messages
_ERR1MSG = _ERR1ARGS[2] % _ERR1ARGS[3]
_ERR2MSG = _ERR2ARGS[2]
def testNoError(self):
lu = _LuTestVerifyErrors()
lu.CallErrorIf(False, self._ERR1CODE, *self._ERR1ARGS)
self.assertFalse(lu.bad)
self.assertFalse(lu.msglist)
def _InitTest(self, **kwargs):
self.lu1 = _LuTestVerifyErrors(**kwargs)
self.lu2 = _LuTestVerifyErrors(**kwargs)
def _CallError(self, *args, **kwargs):
# Check that _Error() and _ErrorIf() produce the same results
self.lu1.DispatchCallError(True, *args, **kwargs)
self.lu2.DispatchCallError(False, *args, **kwargs)
self.assertEqual(self.lu1.bad, self.lu2.bad)
self.assertEqual(self.lu1.msglist, self.lu2.msglist)
# Test-specific checks are made on one LU
return self.lu1
def _checkMsgCommon(self, logstr, errmsg, itype, item, warning):
self.assertTrue(errmsg in logstr)
if warning:
self.assertTrue("WARNING" in logstr)
else:
self.assertTrue("ERROR" in logstr)
self.assertTrue(itype in logstr)
self.assertTrue(item in logstr)
def _checkMsg1(self, logstr, warning=False):
self._checkMsgCommon(logstr, self._ERR1MSG, self._NODESTR,
self._NODENAME, warning)
def _checkMsg2(self, logstr, warning=False):
self._checkMsgCommon(logstr, self._ERR2MSG, self._INSTSTR,
self._INSTNAME, warning)
def testPlain(self):
self._InitTest()
lu = self._CallError(*self._ERR1ARGS)
self.assertTrue(lu.bad)
self.assertEqual(len(lu.msglist), 1)
self._checkMsg1(lu.msglist[0])
def testMultiple(self):
self._InitTest()
self._CallError(*self._ERR1ARGS)
lu = self._CallError(*self._ERR2ARGS)
self.assertTrue(lu.bad)
self.assertEqual(len(lu.msglist), 2)
self._checkMsg1(lu.msglist[0])
self._checkMsg2(lu.msglist[1])
def testIgnore(self):
self._InitTest(ignore_errors=[self._ERR1ID])
lu = self._CallError(*self._ERR1ARGS)
self.assertFalse(lu.bad)
self.assertEqual(len(lu.msglist), 1)
self._checkMsg1(lu.msglist[0], warning=True)
def testWarning(self):
self._InitTest()
lu = self._CallError(*self._ERR1ARGS,
code=_LuTestVerifyErrors.ETYPE_WARNING)
self.assertFalse(lu.bad)
self.assertEqual(len(lu.msglist), 1)
self._checkMsg1(lu.msglist[0], warning=True)
def testWarning2(self):
self._InitTest()
self._CallError(*self._ERR1ARGS)
lu = self._CallError(*self._ERR2ARGS,
code=_LuTestVerifyErrors.ETYPE_WARNING)
self.assertTrue(lu.bad)
self.assertEqual(len(lu.msglist), 2)
self._checkMsg1(lu.msglist[0])
self._checkMsg2(lu.msglist[1], warning=True)
def testDebugSimulate(self):
lu = _LuTestVerifyErrors(debug_simulate_errors=True)
lu.CallErrorIf(False, *self._ERR1ARGS)
self.assertTrue(lu.bad)
self.assertEqual(len(lu.msglist), 1)
self._checkMsg1(lu.msglist[0])
def testErrCodes(self):
self._InitTest(error_codes=True)
lu = self._CallError(*self._ERR1ARGS)
self.assertTrue(lu.bad)
self.assertEqual(len(lu.msglist), 1)
self._checkMsg1(lu.msglist[0])
self.assertTrue(self._ERR1ID in lu.msglist[0])
if __name__ == "__main__":
testutils.GanetiTestProgram()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment