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
|