Commit b3f3aa3d authored by Bernardo Dal Seno's avatar Bernardo Dal Seno
Browse files

Add QA for cluster policies



qa_cluster.TestClusterSetISpecs() is exported as it will be used in future
tests.
Signed-off-by: default avatarBernardo Dal Seno <bdalseno@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parent ba5c6c6b
......@@ -171,6 +171,8 @@ def RunClusterTests():
("cluster-reserved-lvs", qa_cluster.TestClusterReservedLvs),
# TODO: add more cluster modify tests
("cluster-modify", qa_cluster.TestClusterModifyEmpty),
("cluster-modify", qa_cluster.TestClusterModifyIPolicy),
("cluster-modify", qa_cluster.TestClusterModifyISpecs),
("cluster-modify", qa_cluster.TestClusterModifyBe),
("cluster-modify", qa_cluster.TestClusterModifyDisk),
("cluster-rename", qa_cluster.TestClusterRename),
......
......@@ -423,6 +423,199 @@ def TestClusterModifyBe():
AssertCommand(["gnt-cluster", "modify", "-B", bep])
_START_IPOLICY_RE = re.compile(r"^(\s*)Instance policy")
_START_ISPEC_RE = re.compile(r"^\s+-\s+(std|min|max)")
_VALUE_RE = r"([^\s:][^:]*):\s+(\S.*)$"
_IPOLICY_PARAM_RE = re.compile(r"^\s+-\s+" + _VALUE_RE)
_ISPEC_VALUE_RE = re.compile(r"^\s+" + _VALUE_RE)
def _GetClusterIPolicy():
"""Return the run-time values of the cluster-level instance policy.
@rtype: tuple
@return: (policy, specs), where:
- policy is a dictionary of the policy values, instance specs excluded
- specs is dict of dict, specs[par][key] is a spec value, where key is
"min", "max", or "std"
"""
mnode = qa_config.GetMasterNode()
info = GetCommandOutput(mnode["primary"], "gnt-cluster info")
inside_policy = False
end_ispec_re = None
curr_spec = ""
specs = {}
policy = {}
for line in info.splitlines():
if inside_policy:
# The order of the matching is important, as some REs overlap
m = _START_ISPEC_RE.match(line)
if m:
curr_spec = m.group(1)
continue
m = _IPOLICY_PARAM_RE.match(line)
if m:
policy[m.group(1)] = m.group(2).strip()
continue
m = _ISPEC_VALUE_RE.match(line)
if m:
assert curr_spec
par = m.group(1)
if par == "memory-size":
par = "mem-size"
d = specs.setdefault(par, {})
d[curr_spec] = m.group(2).strip()
continue
assert end_ispec_re is not None
if end_ispec_re.match(line):
inside_policy = False
else:
m = _START_IPOLICY_RE.match(line)
if m:
inside_policy = True
# We stop parsing when we find the same indentation level
re_str = r"^\s{%s}\S" % len(m.group(1))
end_ispec_re = re.compile(re_str)
# Sanity checks
assert len(specs) > 0
good = ("min" in d and "std" in d and "max" in d for d in specs)
assert good, "Missing item in specs: %s" % specs
assert len(policy) > 0
return (policy, specs)
def TestClusterModifyIPolicy():
"""gnt-cluster modify --ipolicy-*"""
basecmd = ["gnt-cluster", "modify"]
(old_policy, old_specs) = _GetClusterIPolicy()
for par in ["vcpu-ratio", "spindle-ratio"]:
curr_val = float(old_policy[par])
test_values = [
(True, 1.0),
(True, 1.5),
(True, 2),
(False, "a"),
# Restore the old value
(True, curr_val),
]
for (good, val) in test_values:
cmd = basecmd + ["--ipolicy-%s=%s" % (par, val)]
AssertCommand(cmd, fail=not good)
if good:
curr_val = val
# Check the affected parameter
(eff_policy, eff_specs) = _GetClusterIPolicy()
AssertEqual(float(eff_policy[par]), curr_val)
# Check everything else
AssertEqual(eff_specs, old_specs)
for p in eff_policy.keys():
if p == par:
continue
AssertEqual(eff_policy[p], old_policy[p])
# Disk templates are treated slightly differently
par = "disk-templates"
disp_str = "enabled disk templates"
curr_val = old_policy[disp_str]
test_values = [
(True, constants.DT_PLAIN),
(True, "%s,%s" % (constants.DT_PLAIN, constants.DT_DRBD8)),
(False, "thisisnotadisktemplate"),
(False, ""),
# Restore the old value
(True, curr_val.replace(" ", "")),
]
for (good, val) in test_values:
cmd = basecmd + ["--ipolicy-%s=%s" % (par, val)]
AssertCommand(cmd, fail=not good)
if good:
curr_val = val
# Check the affected parameter
(eff_policy, eff_specs) = _GetClusterIPolicy()
AssertEqual(eff_policy[disp_str].replace(" ", ""), curr_val)
# Check everything else
AssertEqual(eff_specs, old_specs)
for p in eff_policy.keys():
if p == disp_str:
continue
AssertEqual(eff_policy[p], old_policy[p])
def TestClusterSetISpecs(new_specs, fail=False, old_values=None):
"""Change instance specs.
@type new_specs: dict of dict
@param new_specs: new_specs[par][key], where key is "min", "max", "std". It
can be an empty dictionary.
@type fail: bool
@param fail: if the change is expected to fail
@type old_values: tuple
@param old_values: (old_policy, old_specs), as returned by
L{_GetClusterIPolicy}
@return: same as L{_GetClusterIPolicy}
"""
if old_values:
(old_policy, old_specs) = old_values
else:
(old_policy, old_specs) = _GetClusterIPolicy()
if new_specs:
cmd = ["gnt-cluster", "modify"]
for (par, keyvals) in new_specs.items():
if par == "spindle-use":
# ignore spindle-use, which is not settable
continue
cmd += [
"--specs-%s" % par,
",".join(["%s=%s" % (k, v) for (k, v) in keyvals.items()]),
]
AssertCommand(cmd, fail=fail)
# Check the new state
(eff_policy, eff_specs) = _GetClusterIPolicy()
AssertEqual(eff_policy, old_policy)
if fail:
AssertEqual(eff_specs, old_specs)
else:
for par in eff_specs:
for key in eff_specs[par]:
if par in new_specs and key in new_specs[par]:
AssertEqual(int(eff_specs[par][key]), int(new_specs[par][key]))
else:
AssertEqual(int(eff_specs[par][key]), int(old_specs[par][key]))
return (eff_policy, eff_specs)
def TestClusterModifyISpecs():
"""gnt-cluster modify --specs-*"""
params = ["mem-size", "disk-size", "disk-count", "cpu-count", "nic-count"]
(cur_policy, cur_specs) = _GetClusterIPolicy()
for par in params:
test_values = [
(True, 0, 4, 12),
(True, 4, 4, 12),
(True, 4, 12, 12),
(True, 4, 4, 4),
(False, 4, 0, 12),
(False, 4, 16, 12),
(False, 4, 4, 0),
(False, 12, 4, 4),
(False, 12, 4, 0),
(False, "a", 4, 12),
(False, 0, "a", 12),
(False, 0, 4, "a"),
# This is to restore the old values
(True,
cur_specs[par]["min"], cur_specs[par]["std"], cur_specs[par]["max"])
]
for (good, mn, st, mx) in test_values:
new_vals = {par: {"min": str(mn), "std": str(st), "max": str(mx)}}
cur_state = (cur_policy, cur_specs)
# We update cur_specs, as we've copied the values to restore already
(cur_policy, cur_specs) = TestClusterSetISpecs(new_vals, fail=not good,
old_values=cur_state)
def TestClusterInfo():
"""gnt-cluster info"""
AssertCommand(["gnt-cluster", "info"])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment