Revision 1672a0d1

b/qa/ganeti-qa.py
40 40
import qa_os
41 41
import qa_other
42 42
import qa_tags
43
import qa_utils
43 44

  
44 45

  
45 46
def RunTest(fn, *args):
......
236 237
    sys.exit(1)
237 238

  
238 239
  qa_config.Load(config_file)
240
  qa_utils.LoadHooks()
239 241

  
240 242
  RunTest(qa_other.UploadKnownHostsFile, known_hosts_file)
241 243

  
b/qa/qa-sample.yaml
70 70
# Other settings
71 71
options:
72 72
  burnin-instances: 2
73

  
74
  # Directory containing QA hooks
75
  #hooks-dir: hooks/
b/qa/qa_utils.py
36 36
_RESET_SEQ = None
37 37

  
38 38

  
39
# List of all hooks
40
_hooks = []
41

  
42

  
39 43
def _SetupColours():
40 44
  """Initializes the colour constants.
41 45

  
......
214 218
FormatWarning = lambda text: _FormatWithColor(text, _WARNING_SEQ)
215 219
FormatError = lambda text: _FormatWithColor(text, _ERROR_SEQ)
216 220
FormatInfo = lambda text: _FormatWithColor(text, _INFO_SEQ)
221

  
222

  
223
def LoadHooks():
224
  """Load all QA hooks.
225

  
226
  """
227
  hooks_dir = qa_config.get('options', {}).get('hooks-dir', None)
228
  if not hooks_dir:
229
    return
230
  if hooks_dir not in sys.path:
231
    sys.path.insert(0, hooks_dir)
232
  for name in utils.ListVisibleFiles(hooks_dir):
233
    if name.endswith('.py'):
234
      # Load and instanciate hook
235
      _hooks.append(__import__(name[:-3], None, None, ['']).hook())
236

  
237

  
238
class QaHookContext:
239
  name = None
240
  phase = None
241
  success = None
242
  args = None
243
  kwargs = None
244

  
245

  
246
def _CallHooks(ctx):
247
  """Calls all hooks with the given context.
248

  
249
  """
250
  if not _hooks:
251
    return
252

  
253
  name = "%s-%s" % (ctx.phase, ctx.name)
254
  if ctx.success is not None:
255
    msg = "%s (success=%s)" % (name, ctx.success)
256
  else:
257
    msg = name
258
  print FormatInfo("Begin %s" % msg)
259
  for hook in _hooks:
260
    hook.run(ctx)
261
  print FormatInfo("End %s" % name)
262

  
263

  
264
def DefineHook(name):
265
  """Wraps a function with calls to hooks.
266

  
267
  Usage: prefix function with @qa_utils.DefineHook(...)
268

  
269
  """
270
  def wrapper(fn):
271
    def new_f(*args, **kwargs):
272
      # Create context
273
      ctx = QaHookContext()
274
      ctx.name = name
275
      ctx.phase = 'pre'
276
      ctx.args = args
277
      ctx.kwargs = kwargs
278

  
279
      _CallHooks(ctx)
280
      try:
281
        ctx.phase = 'post'
282
        ctx.success = True
283
        try:
284
          # Call real function
285
          return fn(*args, **kwargs)
286
        except:
287
          ctx.success = False
288
          raise
289
      finally:
290
        _CallHooks(ctx)
291

  
292
    # Override function metadata
293
    new_f.func_name = fn.func_name
294
    new_f.func_doc = fn.func_doc
295

  
296
    return new_f
297

  
298
  return wrapper

Also available in: Unified diff