Revision 587f8ff6

b/qa/qa_cluster.py
1 1
#
2 2
#
3 3

  
4
# Copyright (C) 2007, 2010, 2011, 2012 Google Inc.
4
# Copyright (C) 2007, 2010, 2011, 2012, 2013 Google Inc.
5 5
#
6 6
# This program is free software; you can redistribute it and/or modify
7 7
# it under the terms of the GNU General Public License as published by
......
23 23

  
24 24
"""
25 25

  
26
import re
26 27
import tempfile
27 28
import os.path
28 29

  
......
59 60
    AssertEqual(qa_utils.GetCommandOutput(node["primary"], cmd), content)
60 61

  
61 62

  
63
# Cluster-verify errors (date, "ERROR", then error code)
64
_CVERROR_RE = re.compile(r"^[\w\s:]+\s+- ERROR:([A-Z0-9_-]+):")
65

  
66

  
67
def _GetCVErrorCodes(cvout):
68
  ret = set()
69
  for l in cvout.splitlines():
70
    m = _CVERROR_RE.match(l)
71
    if m:
72
      ecode = m.group(1)
73
      ret.add(ecode)
74
  return ret
75

  
76

  
77
def AssertClusterVerify(fail=False, errors=None):
78
  """Run cluster-verify and check the result
79

  
80
  @type fail: bool
81
  @param fail: if cluster-verify is expected to fail instead of succeeding
82
  @type errors: list of tuples
83
  @param errors: List of CV_XXX errors that are expected; if specified, all the
84
      errors listed must appear in cluster-verify output. A non-empty value
85
      implies C{fail=True}.
86

  
87
  """
88
  cvcmd = "gnt-cluster verify"
89
  mnode = qa_config.GetMasterNode()
90
  if errors:
91
    cvout = GetCommandOutput(mnode["primary"], cvcmd + " --error-codes",
92
                             fail=True)
93
    actual = _GetCVErrorCodes(cvout)
94
    expected = compat.UniqueFrozenset(e for (_, e, _) in errors)
95
    if not actual.issuperset(expected):
96
      missing = expected.difference(actual)
97
      raise qa_error.Error("Cluster-verify didn't return these expected"
98
                           " errors: %s" % utils.CommaJoin(missing))
99
  else:
100
    AssertCommand(cvcmd, fail=fail, node=mnode)
101

  
102

  
62 103
# data for testing failures due to bad keys/values for disk parameters
63 104
_FAIL_PARAMS = ["nonexistent:resync-rate=1",
64 105
                "drbd:nonexistent=1",
b/qa/qa_utils.py
1 1
#
2 2
#
3 3

  
4
# Copyright (C) 2007, 2011, 2012 Google Inc.
4
# Copyright (C) 2007, 2011, 2012, 2013 Google Inc.
5 5
#
6 6
# This program is free software; you can redistribute it and/or modify
7 7
# it under the terms of the GNU General Public License as published by
......
148 148
  return result
149 149

  
150 150

  
151
def _AssertRetCode(rcode, fail, cmdstr, nodename):
152
  """Check the return value from a command and possibly raise an exception.
153

  
154
  """
155
  if fail and rcode == 0:
156
    raise qa_error.Error("Command '%s' on node %s was expected to fail but"
157
                         " didn't" % (cmdstr, nodename))
158
  elif not fail and rcode != 0:
159
    raise qa_error.Error("Command '%s' on node %s failed, exit code %s" %
160
                         (cmdstr, nodename, rcode))
161

  
162

  
151 163
def AssertCommand(cmd, fail=False, node=None):
152 164
  """Checks that a remote command succeeds.
153 165

  
......
173 185
    cmdstr = utils.ShellQuoteArgs(cmd)
174 186

  
175 187
  rcode = StartSSH(nodename, cmdstr).wait()
176

  
177
  if fail:
178
    if rcode == 0:
179
      raise qa_error.Error("Command '%s' on node %s was expected to fail but"
180
                           " didn't" % (cmdstr, nodename))
181
  else:
182
    if rcode != 0:
183
      raise qa_error.Error("Command '%s' on node %s failed, exit code %s" %
184
                           (cmdstr, nodename, rcode))
188
  _AssertRetCode(rcode, fail, cmdstr, nodename)
185 189

  
186 190
  return rcode
187 191

  
......
278 282
    utils.RemoveFile(sname)
279 283

  
280 284

  
281
def GetCommandOutput(node, cmd, tty=None):
285
def GetCommandOutput(node, cmd, tty=None, fail=False):
282 286
  """Returns the output of a command executed on the given node.
283 287

  
288
  @type node: string
289
  @param node: node the command should run on
290
  @type cmd: string
291
  @param cmd: command to be executed in the node (cannot be empty or None)
292
  @type tty: bool or None
293
  @param tty: if we should use tty; if None, it will be auto-detected
294
  @type fail: bool
295
  @param fail: whether the command is expected to fail
284 296
  """
297
  assert cmd
285 298
  p = StartLocalCommand(GetSSHCommand(node, cmd, tty=tty),
286 299
                        stdout=subprocess.PIPE)
287
  AssertEqual(p.wait(), 0)
300
  rcode = p.wait()
301
  _AssertRetCode(rcode, fail, node, cmd)
288 302
  return p.stdout.read()
289 303

  
290 304

  

Also available in: Unified diff