X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/dfe11bad3ad2c306886c9cd86156178eccb8bd6b..3f752d976d077d1eed3e8aa1a4bf39dd72296b0d:/qa/qa_utils.py diff --git a/qa/qa_utils.py b/qa/qa_utils.py index 70650c1..2005634 100644 --- a/qa/qa_utils.py +++ b/qa/qa_utils.py @@ -1,3 +1,6 @@ +# +# + # Copyright (C) 2007 Google Inc. # # This program is free software; you can redistribute it and/or modify @@ -36,6 +39,10 @@ _ERROR_SEQ = None _RESET_SEQ = None +# List of all hooks +_hooks = [] + + def _SetupColours(): """Initializes the colour constants. @@ -84,6 +91,11 @@ def AssertNotEqual(first, second): def GetSSHCommand(node, cmd, strict=True): """Builds SSH command to be executed. + Args: + - node: Node the command should run on + - cmd: Command to be executed as a list with all parameters + - strict: Whether to enable strict host key checking + """ args = [ 'ssh', '-oEscapeChar=none', '-oBatchMode=yes', '-l', 'root' ] @@ -187,7 +199,6 @@ def GetNodeInstances(node, secondaries=False): """ master = qa_config.GetMasterNode() - node_name = ResolveNodeName(node) # Get list of all instances @@ -214,3 +225,87 @@ def _FormatWithColor(text, seq): FormatWarning = lambda text: _FormatWithColor(text, _WARNING_SEQ) FormatError = lambda text: _FormatWithColor(text, _ERROR_SEQ) FormatInfo = lambda text: _FormatWithColor(text, _INFO_SEQ) + + +def LoadHooks(): + """Load all QA hooks. + + """ + hooks_dir = qa_config.get('options', {}).get('hooks-dir', None) + if not hooks_dir: + return + if hooks_dir not in sys.path: + sys.path.insert(0, hooks_dir) + for name in utils.ListVisibleFiles(hooks_dir): + if name.endswith('.py'): + # Load and instanciate hook + print "Loading hook %s" % name + _hooks.append(__import__(name[:-3], None, None, ['']).hook()) + + +class QaHookContext: + """Definition of context passed to hooks. + + """ + name = None + phase = None + success = None + args = None + kwargs = None + + +def _CallHooks(ctx): + """Calls all hooks with the given context. + + """ + if not _hooks: + return + + name = "%s-%s" % (ctx.phase, ctx.name) + if ctx.success is not None: + msg = "%s (success=%s)" % (name, ctx.success) + else: + msg = name + print FormatInfo("Begin %s" % msg) + for hook in _hooks: + hook.run(ctx) + print FormatInfo("End %s" % name) + + +def DefineHook(name): + """Wraps a function with calls to hooks. + + Usage: prefix function with @qa_utils.DefineHook(...) + + This is based on PEP 318, "Decorators for Functions and Methods". + + """ + def wrapper(fn): + def new_f(*args, **kwargs): + # Create context + ctx = QaHookContext() + ctx.name = name + ctx.phase = 'pre' + ctx.args = args + ctx.kwargs = kwargs + + _CallHooks(ctx) + try: + ctx.phase = 'post' + ctx.success = True + try: + # Call real function + return fn(*args, **kwargs) + except: + ctx.success = False + raise + finally: + _CallHooks(ctx) + + # Override function metadata + new_f.func_name = fn.func_name + new_f.func_doc = fn.func_doc + + return new_f + + return wrapper