+ # redo the original-requested BE parameters, if any
+ bep = qa_config.get("backend-parameters", "")
+ if bep:
+ AssertCommand(["gnt-cluster", "modify", "-B", bep])
+
+
+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 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_policy, ret_specs) = qa_utils.ParseIPolicy(policy)
+
+ # Sanity checks
+ 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)
+
+
+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 = "allowed 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=None, diff_specs=None, fail=False,
+ old_values=None):
+ """Change instance specs.
+
+ 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}
+ @return: same as L{_GetClusterIPolicy}
+
+ """
+ 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 = ["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),
+ (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[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 = {
+ 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(
+ 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)
+