Revision c9e05005 qa/qa_utils.py

b/qa/qa_utils.py
30 30
import random
31 31
import tempfile
32 32

  
33
try:
34
  import functools
35
except ImportError, err:
36
  raise ImportError("Python 2.5 or higher is required: %s" % err)
37

  
33 38
from ganeti import utils
34 39
from ganeti import compat
35 40
from ganeti import constants
41
from ganeti import ht
36 42

  
37 43
import qa_config
38 44
import qa_error
......
45 51

  
46 52
_MULTIPLEXERS = {}
47 53

  
54
#: Unique ID per QA run
55
_RUN_UUID = utils.NewUUID()
56

  
57

  
58
(INST_DOWN,
59
 INST_UP) = range(500, 502)
60

  
61
(FIRST_ARG,
62
 RETURN_VALUE) = range(1000, 1002)
63

  
48 64

  
49 65
def _SetupColours():
50 66
  """Initializes the colour constants.
......
522 538
                                              quoted_tmp_hosts))
523 539
  except qa_error.Error:
524 540
    AssertCommand(["rm", tmp_hosts])
541

  
542

  
543
def RunInstanceCheck(instance, running):
544
  """Check if instance is running or not.
545

  
546
  """
547
  script = qa_config.GetInstanceCheckScript()
548
  if not script:
549
    return
550

  
551
  master_node = qa_config.GetMasterNode()
552
  instance_name = instance["name"]
553

  
554
  # Build command to connect to master node
555
  master_ssh = GetSSHCommand(master_node["primary"], "--")
556

  
557
  if running:
558
    running_shellval = "1"
559
    running_text = ""
560
  else:
561
    running_shellval = ""
562
    running_text = "not "
563

  
564
  print FormatInfo("Checking if instance '%s' is %srunning" %
565
                   (instance_name, running_text))
566

  
567
  args = [script, instance_name]
568
  env = {
569
    "PATH": constants.HOOKS_PATH,
570
    "RUN_UUID": _RUN_UUID,
571
    "MASTER_SSH": utils.ShellQuoteArgs(master_ssh),
572
    "INSTANCE_NAME": instance_name,
573
    "INSTANCE_RUNNING": running_shellval,
574
    }
575

  
576
  result = os.spawnve(os.P_WAIT, script, args, env)
577
  if result != 0:
578
    raise qa_error.Error("Instance check failed with result %s" % result)
579

  
580

  
581
_TInstCheck = ht.TStrictDict(False, False, {
582
  "name": ht.TNonEmptyString,
583
  })
584

  
585

  
586
def _InstanceCheckInner(expected, instarg, args, result):
587
  """Helper function used by L{InstanceCheck}.
588

  
589
  """
590
  if instarg == FIRST_ARG:
591
    instance = args[0]
592
  elif instarg == RETURN_VALUE:
593
    instance = result
594
  else:
595
    raise Exception("Invalid value '%s' for instance argument" % instarg)
596

  
597
  if expected in (INST_DOWN, INST_UP):
598
    if not _TInstCheck(instance):
599
      raise Exception("Invalid instance: %s" % instance)
600

  
601
    RunInstanceCheck(instance, (expected == INST_UP))
602
  elif expected is not None:
603
    raise Exception("Invalid value '%s'" % expected)
604

  
605

  
606
def InstanceCheck(before, after, instarg):
607
  """Decorator to check instance status before and after test.
608

  
609
  @param before: L{INST_DOWN} if instance must be stopped before test,
610
    L{INST_UP} if instance must be running before test, L{None} to not check.
611
  @param after: L{INST_DOWN} if instance must be stopped after test,
612
    L{INST_UP} if instance must be running after test, L{None} to not check.
613
  @param instarg: L{FIRST_ARG} to use first argument to test as instance (a
614
    dictionary), L{RETURN_VALUE} to use return value (disallows pre-checks)
615

  
616
  """
617
  def decorator(fn):
618
    @functools.wraps(fn)
619
    def wrapper(*args, **kwargs):
620
      _InstanceCheckInner(before, instarg, args, NotImplemented)
621

  
622
      result = fn(*args, **kwargs)
623

  
624
      _InstanceCheckInner(after, instarg, args, result)
625

  
626
      return result
627
    return wrapper
628
  return decorator

Also available in: Unified diff