from ganeti import pathutils
import qa_config
-import qa_utils
import qa_error
+import qa_instance
+import qa_logging
+import qa_utils
from qa_utils import AssertEqual, AssertCommand, GetCommandOutput
"gnt-cluster", "init",
"--primary-ip-version=%d" % qa_config.get("primary_ip_version", 4),
"--enabled-hypervisors=%s" % ",".join(qa_config.GetEnabledHypervisors()),
- "--enabled-storage-types=%s" %
- ",".join(qa_config.GetEnabledStorageTypes())
+ "--enabled-disk-templates=%s" %
+ ",".join(qa_config.GetEnabledDiskTemplates())
]
for spec_type in ("mem-size", "disk-size", "disk-count", "cpu-count",
original_name = qa_config.get("name")
rename_target = qa_config.get("rename", None)
if rename_target is None:
- print qa_utils.FormatError('"rename" entry is missing')
+ print qa_logging.FormatError('"rename" entry is missing')
return
for data in [
AssertCommand(["gnt-cluster", "modify", "-D", param], fail=True)
-def TestClusterModifyStorageTypes():
- """gnt-cluster modify --enabled-storage-types=..."""
- default_storage_type = qa_config.GetDefaultStorageType()
+def TestClusterModifyDiskTemplates():
+ """gnt-cluster modify --enabled-disk-templates=..."""
+ enabled_disk_templates = qa_config.GetEnabledDiskTemplates()
+ default_disk_template = qa_config.GetDefaultDiskTemplate()
+
+ _TestClusterModifyDiskTemplatesArguments(default_disk_template,
+ enabled_disk_templates)
+
+ _RestoreEnabledDiskTemplates()
+ nodes = qa_config.AcquireManyNodes(2)
+
+ instance_template = enabled_disk_templates[0]
+ instance = qa_instance.CreateInstanceByDiskTemplate(nodes, instance_template)
+
+ _TestClusterModifyUnusedDiskTemplate(instance_template)
+ _TestClusterModifyUsedDiskTemplate(instance_template,
+ enabled_disk_templates)
+
+ qa_instance.TestInstanceRemove(instance)
+ _RestoreEnabledDiskTemplates()
+
+
+def _RestoreEnabledDiskTemplates():
+ """Sets the list of enabled disk templates back to the list of enabled disk
+ templates from the QA configuration. This can be used to make sure that
+ the tests that modify the list of disk templates do not interfere with
+ other tests.
+
+ """
AssertCommand(
["gnt-cluster", "modify",
- "--enabled-storage-types=%s" % default_storage_type],
+ "--enabled-disk-template=%s" %
+ ",".join(qa_config.GetEnabledDiskTemplates())],
fail=False)
- AssertCommand(["gnt-cluster", "info"])
+
+
+def _TestClusterModifyDiskTemplatesArguments(default_disk_template,
+ enabled_disk_templates):
+ """Tests argument handling of 'gnt-cluster modify' with respect to
+ the parameter '--enabled-disk-templates'. This test is independent
+ of instances.
+
+ """
AssertCommand(
["gnt-cluster", "modify",
- "--enabled-storage-types=%s" %
- ",".join(qa_config.GetEnabledStorageTypes())],
+ "--enabled-disk-template=%s" %
+ ",".join(enabled_disk_templates)],
fail=False)
- AssertCommand(["gnt-cluster", "info"])
- # bogus types
+
+ # bogus templates
AssertCommand(["gnt-cluster", "modify",
- "--enabled-storage-types=pinkbunny"],
+ "--enabled-disk-templates=pinkbunny"],
fail=True)
+
# duplicate entries do no harm
AssertCommand(
["gnt-cluster", "modify",
- "--enabled-storage-types=%s,%s" %
- (default_storage_type, default_storage_type)],
+ "--enabled-disk-templates=%s,%s" %
+ (default_disk_template, default_disk_template)],
+ fail=False)
+
+
+def _TestClusterModifyUsedDiskTemplate(instance_template,
+ enabled_disk_templates):
+ """Tests that disk templates that are currently in use by instances cannot
+ be disabled on the cluster.
+
+ """
+ # If the list of enabled disk templates contains only one template
+ # we need to add some other templates, because the list of enabled disk
+ # templates can only be set to a non-empty list.
+ new_disk_templates = list(set(enabled_disk_templates)
+ - set([instance_template]))
+ if not new_disk_templates:
+ new_disk_templates = list(set(constants.DISK_TEMPLATES)
+ - set([instance_template]))
+ AssertCommand(
+ ["gnt-cluster", "modify",
+ "--enabled-disk-templates=%s" %
+ ",".join(new_disk_templates)],
+ fail=True)
+
+
+def _TestClusterModifyUnusedDiskTemplate(instance_template):
+ """Tests that unused disk templates can be disabled safely."""
+ all_disk_templates = constants.DISK_TEMPLATES
+ AssertCommand(
+ ["gnt-cluster", "modify",
+ "--enabled-disk-templates=%s" %
+ ",".join(all_disk_templates)],
+ fail=False)
+ new_disk_templates = [instance_template]
+ AssertCommand(
+ ["gnt-cluster", "modify",
+ "--enabled-disk-templates=%s" %
+ ",".join(new_disk_templates)],
fail=False)
- AssertCommand(["gnt-cluster", "info"])
def TestClusterModifyBe():
@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"
+ - specs is a dictionary containing only the specs, using the internal
+ format (see L{constants.IPOLICY_DEFAULTS} for an example)
"""
info = qa_utils.GetObjectInfo(["gnt-cluster", "info"])
policy = info["Instance policy - limits for instances"]
- ret_specs = {}
- ret_policy = {}
- for (key, val) in policy.items():
- if key in constants.IPOLICY_ISPECS:
- for (par, pval) in val.items():
- if par == "memory-size":
- par = "mem-size"
- d = ret_specs.setdefault(par, {})
- d[key] = pval
- else:
- ret_policy[key] = val
+ (ret_policy, ret_specs) = qa_utils.ParseIPolicy(policy)
# Sanity checks
- assert len(ret_specs) > 0
- good = ("min" in d and "std" in d and "max" in d for d in ret_specs)
- assert good, "Missing item in specs: %s" % ret_specs
+ assert "minmax" in ret_specs and "std" in ret_specs
+ assert len(ret_specs["minmax"]) > 0
assert len(ret_policy) > 0
return (ret_policy, ret_specs)
# Disk templates are treated slightly differently
par = "disk-templates"
- disp_str = "enabled disk templates"
+ disp_str = "allowed disk templates"
curr_val = old_policy[disp_str]
test_values = [
(True, constants.DT_PLAIN),
AssertEqual(eff_policy[p], old_policy[p])
-def TestClusterSetISpecs(new_specs, fail=False, old_values=None):
+def TestClusterSetISpecs(new_specs=None, diff_specs=None, 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.
+ At most one of new_specs or diff_specs can be specified.
+
+ @type new_specs: dict
+ @param new_specs: new complete specs, in the same format returned by
+ L{_GetClusterIPolicy}
+ @type diff_specs: dict
+ @param diff_specs: partial specs, it can be an incomplete specifications, but
+ if min/max specs are specified, their number must match the number of the
+ existing specs
@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}
+ 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)
+ build_cmd = lambda opts: ["gnt-cluster", "modify"] + opts
+ return qa_utils.TestSetISpecs(
+ new_specs=new_specs, diff_specs=diff_specs,
+ get_policy_fn=_GetClusterIPolicy, build_cmd_fn=build_cmd,
+ fail=fail, old_values=old_values)
def TestClusterModifyISpecs():
"""gnt-cluster modify --specs-*"""
- params = ["mem-size", "disk-size", "disk-count", "cpu-count", "nic-count"]
+ params = ["memory-size", "disk-size", "disk-count", "cpu-count", "nic-count"]
(cur_policy, cur_specs) = _GetClusterIPolicy()
+ # This test assumes that there is only one min/max bound
+ assert len(cur_specs[constants.ISPECS_MINMAX]) == 1
for par in params:
test_values = [
(True, 0, 4, 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"])
+ cur_specs[constants.ISPECS_MINMAX][0][constants.ISPECS_MIN][par],
+ cur_specs[constants.ISPECS_STD][par],
+ cur_specs[constants.ISPECS_MINMAX][0][constants.ISPECS_MAX][par])
]
for (good, mn, st, mx) in test_values:
- new_vals = {par: {"min": str(mn), "std": str(st), "max": str(mx)}}
+ new_vals = {
+ constants.ISPECS_MINMAX: [{
+ constants.ISPECS_MIN: {par: mn},
+ constants.ISPECS_MAX: {par: mx}
+ }],
+ constants.ISPECS_STD: {par: st}
+ }
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)
+ (cur_policy, cur_specs) = TestClusterSetISpecs(
+ diff_specs=new_vals, fail=not good, old_values=cur_state)
+
+ # Get the ipolicy command
+ mnode = qa_config.GetMasterNode()
+ initcmd = GetCommandOutput(mnode.primary, "gnt-cluster show-ispecs-cmd")
+ modcmd = ["gnt-cluster", "modify"]
+ opts = initcmd.split()
+ assert opts[0:2] == ["gnt-cluster", "init"]
+ for k in range(2, len(opts) - 1):
+ if opts[k].startswith("--ipolicy-"):
+ assert k + 2 <= len(opts)
+ modcmd.extend(opts[k:k + 2])
+ # Re-apply the ipolicy (this should be a no-op)
+ AssertCommand(modcmd)
+ new_initcmd = GetCommandOutput(mnode.primary, "gnt-cluster show-ispecs-cmd")
+ AssertEqual(initcmd, new_initcmd)
def TestClusterInfo():
script = qa_utils.UploadFile(master.primary, "../tools/burnin")
try:
+ disks = qa_config.GetDiskOptions()
# Run burnin
cmd = [script,
"--os=%s" % qa_config.get("os"),
"--minmem-size=%s" % qa_config.get(constants.BE_MINMEM),
"--maxmem-size=%s" % qa_config.get(constants.BE_MAXMEM),
- "--disk-size=%s" % ",".join(qa_config.get("disk")),
- "--disk-growth=%s" % ",".join(qa_config.get("disk-growth")),
+ "--disk-size=%s" % ",".join([d.get("size") for d in disks]),
+ "--disk-growth=%s" % ",".join([d.get("growth") for d in disks]),
"--disk-template=%s" % disk_template]
if parallel:
cmd.append("--parallel")
failovermaster = qa_config.AcquireNode(exclude=master)
cmd = ["gnt-cluster", "master-failover"]
+ node_list_cmd = ["gnt-node", "list"]
try:
AssertCommand(cmd, node=failovermaster)
+ AssertCommand(node_list_cmd, node=failovermaster)
# Back to original master node
AssertCommand(cmd, node=master)
+ AssertCommand(node_list_cmd, node=master)
finally:
failovermaster.Release()