Revision f7e6f3c8

b/qa/ganeti-qa.py
1 1
#!/usr/bin/python -u
2 2
#
3 3

  
4
# Copyright (C) 2007, 2008, 2009, 2010 Google Inc.
4
# Copyright (C) 2007, 2008, 2009, 2010, 2011 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
......
354 354
            pnode, snode)
355 355

  
356 356

  
357
@rapi.client.UsesRapiClient
358
def main():
359
  """Main program.
357
def RunQa():
358
  """Main QA body.
360 359

  
361 360
  """
362
  parser = optparse.OptionParser(usage="%prog [options] <config-file>")
363
  parser.add_option('--yes-do-it', dest='yes_do_it',
364
      action="store_true",
365
      help="Really execute the tests")
366
  (qa_config.options, args) = parser.parse_args()
367

  
368
  if len(args) == 1:
369
    (config_file, ) = args
370
  else:
371
    parser.error("Wrong number of arguments.")
372

  
373
  if not qa_config.options.yes_do_it:
374
    print ("Executing this script irreversibly destroys any Ganeti\n"
375
           "configuration on all nodes involved. If you really want\n"
376
           "to start testing, supply the --yes-do-it option.")
377
    sys.exit(1)
378

  
379
  qa_config.Load(config_file)
380

  
381 361
  rapi_user = "ganeti-qa"
382 362
  rapi_secret = utils.GenerateSecret()
383 363

  
......
476 456
  RunTestIf("cluster-destroy", qa_cluster.TestClusterDestroy)
477 457

  
478 458

  
459
@rapi.client.UsesRapiClient
460
def main():
461
  """Main program.
462

  
463
  """
464
  parser = optparse.OptionParser(usage="%prog [options] <config-file>")
465
  parser.add_option('--yes-do-it', dest='yes_do_it',
466
      action="store_true",
467
      help="Really execute the tests")
468
  (qa_config.options, args) = parser.parse_args()
469

  
470
  if len(args) == 1:
471
    (config_file, ) = args
472
  else:
473
    parser.error("Wrong number of arguments.")
474

  
475
  if not qa_config.options.yes_do_it:
476
    print ("Executing this script irreversibly destroys any Ganeti\n"
477
           "configuration on all nodes involved. If you really want\n"
478
           "to start testing, supply the --yes-do-it option.")
479
    sys.exit(1)
480

  
481
  qa_config.Load(config_file)
482

  
483
  qa_utils.StartMultiplexer(qa_config.GetMasterNode()["primary"])
484
  try:
485
    RunQa()
486
  finally:
487
    qa_utils.CloseMultiplexers()
488

  
479 489
if __name__ == '__main__':
480 490
  main()
b/qa/qa_utils.py
1 1
#
2 2
#
3 3

  
4
# Copyright (C) 2007 Google Inc.
4
# Copyright (C) 2007, 2011 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
......
28 28
import sys
29 29
import subprocess
30 30
import random
31
import tempfile
31 32

  
32 33
from ganeti import utils
33 34
from ganeti import compat
......
42 43
_ERROR_SEQ = None
43 44
_RESET_SEQ = None
44 45

  
46
_MULTIPLEXERS = {}
47

  
45 48

  
46 49
def _SetupColours():
47 50
  """Initializes the colour constants.
......
143 146
  return rcode
144 147

  
145 148

  
146
def GetSSHCommand(node, cmd, strict=True):
149
def GetSSHCommand(node, cmd, strict=True, opts=None):
147 150
  """Builds SSH command to be executed.
148 151

  
149 152
  @type node: string
150 153
  @param node: node the command should run on
151 154
  @type cmd: string
152
  @param cmd: command to be executed in the node
155
  @param cmd: command to be executed in the node; if None or empty
156
      string, no command will be executed
153 157
  @type strict: boolean
154 158
  @param strict: whether to enable strict host key checking
159
  @type opts: list
160
  @param opts: list of additional options
155 161

  
156 162
  """
157 163
  args = [ 'ssh', '-oEscapeChar=none', '-oBatchMode=yes', '-l', 'root', '-t' ]
......
163 169
  args.append('-oStrictHostKeyChecking=%s' % tmp)
164 170
  args.append('-oClearAllForwardings=yes')
165 171
  args.append('-oForwardAgent=yes')
172
  if opts:
173
    args.extend(opts)
174
  if node in _MULTIPLEXERS:
175
    spath = _MULTIPLEXERS[node][0]
176
    args.append('-oControlPath=%s' % spath)
177
    args.append('-oControlMaster=no')
166 178
  args.append(node)
167
  args.append(cmd)
179
  if cmd:
180
    args.append(cmd)
168 181

  
169 182
  return args
170 183

  
......
184 197
  return StartLocalCommand(GetSSHCommand(node, cmd, strict=strict))
185 198

  
186 199

  
200
def StartMultiplexer(node):
201
  """Starts a multiplexer command.
202

  
203
  @param node: the node for which to open the multiplexer
204

  
205
  """
206
  if node in _MULTIPLEXERS:
207
    return
208

  
209
  # Note: yes, we only need mktemp, since we'll remove the file anyway
210
  sname = tempfile.mktemp(prefix="ganeti-qa-multiplexer.")
211
  utils.RemoveFile(sname)
212
  opts = ["-N", "-oControlPath=%s" % sname, "-oControlMaster=yes"]
213
  print "Created socket at %s" % sname
214
  child = StartLocalCommand(GetSSHCommand(node, None, opts=opts))
215
  _MULTIPLEXERS[node] = (sname, child)
216

  
217

  
218
def CloseMultiplexers():
219
  """Closes all current multiplexers and cleans up.
220

  
221
  """
222
  for node in _MULTIPLEXERS.keys():
223
    (sname, child) = _MULTIPLEXERS.pop(node)
224
    utils.KillProcess(child.pid, timeout=10, waitpid=True)
225
    utils.RemoveFile(sname)
226

  
227

  
187 228
def GetCommandOutput(node, cmd):
188 229
  """Returns the output of a command executed on the given node.
189 230

  

Also available in: Unified diff