#!/usr/bin/python -u
#
-# Copyright (C) 2007, 2008, 2009, 2010 Google Inc.
+# Copyright (C) 2007, 2008, 2009, 2010, 2011 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
pnode, snode)
-@rapi.client.UsesRapiClient
-def main():
- """Main program.
+def RunQa():
+ """Main QA body.
"""
- parser = optparse.OptionParser(usage="%prog [options] <config-file>")
- parser.add_option('--yes-do-it', dest='yes_do_it',
- action="store_true",
- help="Really execute the tests")
- (qa_config.options, args) = parser.parse_args()
-
- if len(args) == 1:
- (config_file, ) = args
- else:
- parser.error("Wrong number of arguments.")
-
- if not qa_config.options.yes_do_it:
- print ("Executing this script irreversibly destroys any Ganeti\n"
- "configuration on all nodes involved. If you really want\n"
- "to start testing, supply the --yes-do-it option.")
- sys.exit(1)
-
- qa_config.Load(config_file)
-
rapi_user = "ganeti-qa"
rapi_secret = utils.GenerateSecret()
RunTestIf("cluster-destroy", qa_cluster.TestClusterDestroy)
+@rapi.client.UsesRapiClient
+def main():
+ """Main program.
+
+ """
+ parser = optparse.OptionParser(usage="%prog [options] <config-file>")
+ parser.add_option('--yes-do-it', dest='yes_do_it',
+ action="store_true",
+ help="Really execute the tests")
+ (qa_config.options, args) = parser.parse_args()
+
+ if len(args) == 1:
+ (config_file, ) = args
+ else:
+ parser.error("Wrong number of arguments.")
+
+ if not qa_config.options.yes_do_it:
+ print ("Executing this script irreversibly destroys any Ganeti\n"
+ "configuration on all nodes involved. If you really want\n"
+ "to start testing, supply the --yes-do-it option.")
+ sys.exit(1)
+
+ qa_config.Load(config_file)
+
+ qa_utils.StartMultiplexer(qa_config.GetMasterNode()["primary"])
+ try:
+ RunQa()
+ finally:
+ qa_utils.CloseMultiplexers()
+
if __name__ == '__main__':
main()
#
#
-# Copyright (C) 2007 Google Inc.
+# Copyright (C) 2007, 2011 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
import sys
import subprocess
import random
+import tempfile
from ganeti import utils
from ganeti import compat
_ERROR_SEQ = None
_RESET_SEQ = None
+_MULTIPLEXERS = {}
+
def _SetupColours():
"""Initializes the colour constants.
return rcode
-def GetSSHCommand(node, cmd, strict=True):
+def GetSSHCommand(node, cmd, strict=True, opts=None):
"""Builds SSH command to be executed.
@type node: string
@param node: node the command should run on
@type cmd: string
- @param cmd: command to be executed in the node
+ @param cmd: command to be executed in the node; if None or empty
+ string, no command will be executed
@type strict: boolean
@param strict: whether to enable strict host key checking
+ @type opts: list
+ @param opts: list of additional options
"""
args = [ 'ssh', '-oEscapeChar=none', '-oBatchMode=yes', '-l', 'root', '-t' ]
args.append('-oStrictHostKeyChecking=%s' % tmp)
args.append('-oClearAllForwardings=yes')
args.append('-oForwardAgent=yes')
+ if opts:
+ args.extend(opts)
+ if node in _MULTIPLEXERS:
+ spath = _MULTIPLEXERS[node][0]
+ args.append('-oControlPath=%s' % spath)
+ args.append('-oControlMaster=no')
args.append(node)
- args.append(cmd)
+ if cmd:
+ args.append(cmd)
return args
return StartLocalCommand(GetSSHCommand(node, cmd, strict=strict))
+def StartMultiplexer(node):
+ """Starts a multiplexer command.
+
+ @param node: the node for which to open the multiplexer
+
+ """
+ if node in _MULTIPLEXERS:
+ return
+
+ # Note: yes, we only need mktemp, since we'll remove the file anyway
+ sname = tempfile.mktemp(prefix="ganeti-qa-multiplexer.")
+ utils.RemoveFile(sname)
+ opts = ["-N", "-oControlPath=%s" % sname, "-oControlMaster=yes"]
+ print "Created socket at %s" % sname
+ child = StartLocalCommand(GetSSHCommand(node, None, opts=opts))
+ _MULTIPLEXERS[node] = (sname, child)
+
+
+def CloseMultiplexers():
+ """Closes all current multiplexers and cleans up.
+
+ """
+ for node in _MULTIPLEXERS.keys():
+ (sname, child) = _MULTIPLEXERS.pop(node)
+ utils.KillProcess(child.pid, timeout=10, waitpid=True)
+ utils.RemoveFile(sname)
+
+
def GetCommandOutput(node, cmd):
"""Returns the output of a command executed on the given node.