diff --git a/lib/cli.py b/lib/cli.py index 2113308d146ce39600842314f0c48a231f1bfe2f..6152ed7ceb5536d86ac2582b48e5a1bbda62ebef 100644 --- a/lib/cli.py +++ b/lib/cli.py @@ -3731,7 +3731,7 @@ def FormatPolicyInfo(custom_ipolicy, eff_ipolicy, iscluster): if iscluster: eff_ipolicy = custom_ipolicy - custom_minmax = custom_ipolicy.get(constants.ISPECS_MINMAX) + custom_minmax = custom_ipolicy.get(constants.ISPECS_MINMAX, {}) ret = [ (key, FormatParamsDictInfo(custom_minmax.get(key, {}), diff --git a/lib/cmdlib.py b/lib/cmdlib.py index d6f16d07df5cd74351b24208de3af8c5782fdb95..19898e73057988fdca55180f3f75a79c2ea78f52 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -813,20 +813,6 @@ def _GetUpdatedParams(old_params, update_dict, return params_copy -def _UpdateMinMaxISpecs(ipolicy, new_minmax, group_policy): - use_none = use_default = group_policy - minmax = ipolicy.setdefault(constants.ISPECS_MINMAX, {}) - for (key, value) in new_minmax.items(): - if key not in constants.ISPECS_MINMAX_KEYS: - raise errors.OpPrereqError("Invalid key in new ipolicy/%s: %s" % - (constants.ISPECS_MINMAX, key), - errors.ECODE_INVAL) - old_spec = minmax.get(key, {}) - minmax[key] = _GetUpdatedParams(old_spec, value, use_none=use_none, - use_default=use_default) - utils.ForceDictType(minmax[key], constants.ISPECS_PARAMETER_TYPES) - - def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False): """Return the new version of an instance policy. @@ -834,41 +820,43 @@ def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False): we should support removal of policy entries """ - use_none = use_default = group_policy ipolicy = copy.deepcopy(old_ipolicy) for key, value in new_ipolicy.items(): if key not in constants.IPOLICY_ALL_KEYS: raise errors.OpPrereqError("Invalid key in new ipolicy: %s" % key, errors.ECODE_INVAL) - if key == constants.ISPECS_MINMAX: - _UpdateMinMaxISpecs(ipolicy, value, group_policy) - elif key == constants.ISPECS_STD: - ipolicy[key] = _GetUpdatedParams(old_ipolicy.get(key, {}), value, - use_none=use_none, - use_default=use_default) - utils.ForceDictType(ipolicy[key], constants.ISPECS_PARAMETER_TYPES) + if (not value or value == [constants.VALUE_DEFAULT] or + value == constants.VALUE_DEFAULT): + if group_policy: + del ipolicy[key] + else: + raise errors.OpPrereqError("Can't unset ipolicy attribute '%s'" + " on the cluster'" % key, + errors.ECODE_INVAL) else: - if (not value or value == [constants.VALUE_DEFAULT] or - value == constants.VALUE_DEFAULT): + if key in constants.IPOLICY_PARAMETERS: + # FIXME: we assume all such values are float + try: + ipolicy[key] = float(value) + except (TypeError, ValueError), err: + raise errors.OpPrereqError("Invalid value for attribute" + " '%s': '%s', error: %s" % + (key, value, err), errors.ECODE_INVAL) + elif key == constants.ISPECS_MINMAX: + for k in value.keys(): + utils.ForceDictType(value[k], constants.ISPECS_PARAMETER_TYPES) + ipolicy[key] = value + elif key == constants.ISPECS_STD: if group_policy: - del ipolicy[key] - else: - raise errors.OpPrereqError("Can't unset ipolicy attribute '%s'" - " on the cluster'" % key, - errors.ECODE_INVAL) + msg = "%s cannot appear in group instance specs" % key + raise errors.OpPrereqError(msg, errors.ECODE_INVAL) + ipolicy[key] = _GetUpdatedParams(old_ipolicy.get(key, {}), value, + use_none=False, use_default=False) + utils.ForceDictType(ipolicy[key], constants.ISPECS_PARAMETER_TYPES) else: - if key in constants.IPOLICY_PARAMETERS: - # FIXME: we assume all such values are float - try: - ipolicy[key] = float(value) - except (TypeError, ValueError), err: - raise errors.OpPrereqError("Invalid value for attribute" - " '%s': '%s', error: %s" % - (key, value, err), errors.ECODE_INVAL) - else: - # FIXME: we assume all others are lists; this should be redone - # in a nicer way - ipolicy[key] = list(value) + # FIXME: we assume all others are lists; this should be redone + # in a nicer way + ipolicy[key] = list(value) try: objects.InstancePolicy.CheckParameterSyntax(ipolicy, not group_policy) except errors.ConfigurationError, err: diff --git a/lib/objects.py b/lib/objects.py index ebf6fc00cdf7ac113e8b95804060f0984ab1a044..282aece4d24c2ff5f61a10d609f89b68ad320e47 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -82,35 +82,17 @@ def FillDict(defaults_dict, custom_dict, skip_keys=None): return ret_dict -def _FillMinMaxISpecs(default_specs, custom_specs): - assert frozenset(default_specs.keys()) == constants.ISPECS_MINMAX_KEYS - ret_specs = {} - for key in constants.ISPECS_MINMAX_KEYS: - ret_specs[key] = FillDict(default_specs[key], - custom_specs.get(key, {})) - return ret_specs - - def FillIPolicy(default_ipolicy, custom_ipolicy): """Fills an instance policy with defaults. """ assert frozenset(default_ipolicy.keys()) == constants.IPOLICY_ALL_KEYS - ret_dict = {} - # Instance specs - new_mm = _FillMinMaxISpecs(default_ipolicy[constants.ISPECS_MINMAX], - custom_ipolicy.get(constants.ISPECS_MINMAX, {})) - ret_dict[constants.ISPECS_MINMAX] = new_mm - new_std = FillDict(default_ipolicy[constants.ISPECS_STD], - custom_ipolicy.get(constants.ISPECS_STD, {})) - ret_dict[constants.ISPECS_STD] = new_std - # list items - for key in [constants.IPOLICY_DTS]: - ret_dict[key] = list(custom_ipolicy.get(key, default_ipolicy[key])) - # other items which we know we can directly copy (immutables) - for key in constants.IPOLICY_PARAMETERS: - ret_dict[key] = custom_ipolicy.get(key, default_ipolicy[key]) - + ret_dict = copy.deepcopy(custom_ipolicy) + for key in default_ipolicy: + if key not in ret_dict: + ret_dict[key] = copy.deepcopy(default_ipolicy[key]) + elif key == constants.ISPECS_STD: + ret_dict[key] = FillDict(default_ipolicy[key], ret_dict[key]) return ret_dict @@ -198,13 +180,7 @@ def MakeEmptyIPolicy(): """Create empty IPolicy dictionary. """ - return { - constants.ISPECS_MINMAX: { - constants.ISPECS_MIN: {}, - constants.ISPECS_MAX: {}, - }, - constants.ISPECS_STD: {}, - } + return {} class ConfigObject(outils.ValidatedSlots): @@ -953,6 +929,14 @@ class InstancePolicy(ConfigObject): raise errors.ConfigurationError("Invalid keys in ipolicy: %s" % utils.CommaJoin(wrong_keys)) + @classmethod + def _CheckIncompleteSpec(cls, spec, keyname): + missing_params = constants.ISPECS_PARAMETERS - frozenset(spec.keys()) + if missing_params: + msg = ("Missing instance specs parameters for %s: %s" % + (keyname, utils.CommaJoin(missing_params))) + raise errors.ConfigurationError(msg) + @classmethod def CheckISpecSyntax(cls, ipolicy, check_std): """Check the instance policy specs for validity. @@ -977,6 +961,10 @@ class InstancePolicy(ConfigObject): if missing: msg = "Missing instance specification: %s" % utils.CommaJoin(missing) raise errors.ConfigurationError(msg) + for (key, spec) in minmaxspecs.items(): + InstancePolicy._CheckIncompleteSpec(spec, key) + if check_std: + InstancePolicy._CheckIncompleteSpec(stdspec, constants.ISPECS_STD) for param in constants.ISPECS_PARAMETERS: InstancePolicy._CheckISpecParamSyntax(minmaxspecs, stdspec, param, check_std) @@ -1002,7 +990,7 @@ class InstancePolicy(ConfigObject): """ minspec = minmaxspecs[constants.ISPECS_MIN] maxspec = minmaxspecs[constants.ISPECS_MAX] - min_v = minspec.get(name, 0) + min_v = minspec[name] if check_std: std_v = stdspec.get(name, min_v) @@ -1011,13 +999,10 @@ class InstancePolicy(ConfigObject): std_v = min_v std_msg = "-" - max_v = maxspec.get(name, std_v) + max_v = maxspec[name] if min_v > std_v or std_v > max_v: err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" % - (name, - minspec.get(name, "-"), - maxspec.get(name, "-"), - std_msg)) + (name, min_v, max_v, std_msg)) raise errors.ConfigurationError(err) @classmethod diff --git a/src/Ganeti/Objects.hs b/src/Ganeti/Objects.hs index d6cd124889fb648220543f68c5e35e82ba74e2b5..908daecf63e24b47a16a039ec9bee6c0b80e6449 100644 --- a/src/Ganeti/Objects.hs +++ b/src/Ganeti/Objects.hs @@ -66,9 +66,7 @@ module Ganeti.Objects , PartialISpecParams(..) , fillISpecParams , allISpecParamFields - , FilledMinMaxISpecs(..) - , PartialMinMaxISpecs(..) - , fillMinMaxISpecs + , MinMaxISpecs(..) , FilledIPolicy(..) , PartialIPolicy(..) , fillIPolicy @@ -505,16 +503,7 @@ $(buildParam "ISpec" "ispec" , simpleField C.ispecSpindleUse [t| Int |] ]) --- | Partial min-max instance specs. These is not built via buildParam since --- it has a special 2-level inheritance mode. -$(buildObject "PartialMinMaxISpecs" "mmis" - [ renameField "MinSpecP" $ simpleField "min" [t| PartialISpecParams |] - , renameField "MaxSpecP" $ simpleField "max" [t| PartialISpecParams |] - ]) - --- | Filled min-max instance specs. This is not built via buildParam since --- it has a special 2-level inheritance mode. -$(buildObject "FilledMinMaxISpecs" "mmis" +$(buildObject "MinMaxISpecs" "mmis" [ renameField "MinSpec" $ simpleField "min" [t| FilledISpecParams |] , renameField "MaxSpec" $ simpleField "max" [t| FilledISpecParams |] ]) @@ -523,8 +512,9 @@ $(buildObject "FilledMinMaxISpecs" "mmis" -- has a special 2-level inheritance mode. $(buildObject "PartialIPolicy" "ipolicy" [ optionalField . renameField "MinMaxISpecsP" - $ simpleField C.ispecsMinmax [t| PartialMinMaxISpecs |] - , renameField "StdSpecP" $ simpleField "std" [t| PartialISpecParams |] + $ simpleField C.ispecsMinmax [t| MinMaxISpecs |] + , optionalField . renameField "StdSpecP" + $ simpleField "std" [t| PartialISpecParams |] , optionalField . renameField "SpindleRatioP" $ simpleField "spindle-ratio" [t| Double |] , optionalField . renameField "VcpuRatioP" @@ -537,24 +527,13 @@ $(buildObject "PartialIPolicy" "ipolicy" -- has a special 2-level inheritance mode. $(buildObject "FilledIPolicy" "ipolicy" [ renameField "MinMaxISpecs" - $ simpleField C.ispecsMinmax [t| FilledMinMaxISpecs |] + $ simpleField C.ispecsMinmax [t| MinMaxISpecs |] , renameField "StdSpec" $ simpleField "std" [t| FilledISpecParams |] , simpleField "spindle-ratio" [t| Double |] , simpleField "vcpu-ratio" [t| Double |] , simpleField "disk-templates" [t| [DiskTemplate] |] ]) --- | Custom filler for the min-max instance specs. -fillMinMaxISpecs :: FilledMinMaxISpecs -> Maybe PartialMinMaxISpecs -> - FilledMinMaxISpecs -fillMinMaxISpecs fminmax Nothing = fminmax -fillMinMaxISpecs (FilledMinMaxISpecs { mmisMinSpec = fmin - , mmisMaxSpec = fmax }) - (Just PartialMinMaxISpecs { mmisMinSpecP = pmin - , mmisMaxSpecP = pmax }) = - FilledMinMaxISpecs { mmisMinSpec = fillISpecParams fmin pmin - , mmisMaxSpec = fillISpecParams fmax pmax } - -- | Custom filler for the ipolicy types. fillIPolicy :: FilledIPolicy -> PartialIPolicy -> FilledIPolicy fillIPolicy (FilledIPolicy { ipolicyMinMaxISpecs = fminmax @@ -567,8 +546,10 @@ fillIPolicy (FilledIPolicy { ipolicyMinMaxISpecs = fminmax , ipolicySpindleRatioP = pspindleRatio , ipolicyVcpuRatioP = pvcpuRatio , ipolicyDiskTemplatesP = pdiskTemplates}) = - FilledIPolicy { ipolicyMinMaxISpecs = fillMinMaxISpecs fminmax pminmax - , ipolicyStdSpec = fillISpecParams fstd pstd + FilledIPolicy { ipolicyMinMaxISpecs = fromMaybe fminmax pminmax + , ipolicyStdSpec = case pstd of + Nothing -> fstd + Just p -> fillISpecParams fstd p , ipolicySpindleRatio = fromMaybe fspindleRatio pspindleRatio , ipolicyVcpuRatio = fromMaybe fvcpuRatio pvcpuRatio , ipolicyDiskTemplates = fromMaybe fdiskTemplates diff --git a/test/hs/Test/Ganeti/Objects.hs b/test/hs/Test/Ganeti/Objects.hs index 81bf3fd988ed8f6ee05d8dbe322afc1064f7c9e4..23ea054eb96c4ac3ff844b596b2786877055d287 100644 --- a/test/hs/Test/Ganeti/Objects.hs +++ b/test/hs/Test/Ganeti/Objects.hs @@ -143,14 +143,13 @@ genInstWithNets nets = do -- | FIXME: This generates completely random data, without normal -- validation rules. $(genArbitrary ''PartialISpecParams) -$(genArbitrary ''PartialMinMaxISpecs) -- | FIXME: This generates completely random data, without normal -- validation rules. $(genArbitrary ''PartialIPolicy) $(genArbitrary ''FilledISpecParams) -$(genArbitrary ''FilledMinMaxISpecs) +$(genArbitrary ''MinMaxISpecs) $(genArbitrary ''FilledIPolicy) $(genArbitrary ''IpFamily) $(genArbitrary ''FilledNDParams) diff --git a/test/py/ganeti.cmdlib_unittest.py b/test/py/ganeti.cmdlib_unittest.py index 5603e4ae34d3dff3b969c76496b3a42019607b4d..68ee95e27f70988906408afdc52e6f998f4584e3 100755 --- a/test/py/ganeti.cmdlib_unittest.py +++ b/test/py/ganeti.cmdlib_unittest.py @@ -1733,81 +1733,81 @@ class TestGetUpdatedIPolicy(unittest.TestCase): """Tests for cmdlib._GetUpdatedIPolicy()""" _OLD_CLUSTER_POLICY = { constants.IPOLICY_VCPU_RATIO: 1.5, - constants.ISPECS_MINMAX: { - constants.ISPECS_MIN: { - constants.ISPEC_MEM_SIZE: 20, - constants.ISPEC_CPU_COUNT: 2, - }, - constants.ISPECS_MAX: {}, - }, - constants.ISPECS_STD: {}, + constants.ISPECS_MINMAX: constants.ISPECS_MINMAX_DEFAULTS, + constants.ISPECS_STD: constants.IPOLICY_DEFAULTS[constants.ISPECS_STD], } _OLD_GROUP_POLICY = { constants.IPOLICY_SPINDLE_RATIO: 2.5, constants.ISPECS_MINMAX: { constants.ISPECS_MIN: { - constants.ISPEC_DISK_SIZE: 20, - constants.ISPEC_NIC_COUNT: 2, + constants.ISPEC_MEM_SIZE: 128, + constants.ISPEC_CPU_COUNT: 1, + constants.ISPEC_DISK_COUNT: 1, + constants.ISPEC_DISK_SIZE: 1024, + constants.ISPEC_NIC_COUNT: 1, + constants.ISPEC_SPINDLE_USE: 1, + }, + constants.ISPECS_MAX: { + constants.ISPEC_MEM_SIZE: 32768, + constants.ISPEC_CPU_COUNT: 8, + constants.ISPEC_DISK_COUNT: 5, + constants.ISPEC_DISK_SIZE: 1024 * 1024, + constants.ISPEC_NIC_COUNT: 3, + constants.ISPEC_SPINDLE_USE: 12, }, - constants.ISPECS_MAX: {}, }, } def _TestSetSpecs(self, old_policy, isgroup): - ispec_key = constants.ISPECS_MIN - diff_ispec = { - constants.ISPEC_MEM_SIZE: 50, - constants.ISPEC_DISK_SIZE: 30, + diff_minmax = { + constants.ISPECS_MIN: { + constants.ISPEC_MEM_SIZE: 64, + constants.ISPEC_CPU_COUNT: 1, + constants.ISPEC_DISK_COUNT: 2, + constants.ISPEC_DISK_SIZE: 64, + constants.ISPEC_NIC_COUNT: 1, + constants.ISPEC_SPINDLE_USE: 1, + }, + constants.ISPECS_MAX: { + constants.ISPEC_MEM_SIZE: 16384, + constants.ISPEC_CPU_COUNT: 10, + constants.ISPEC_DISK_COUNT: 12, + constants.ISPEC_DISK_SIZE: 1024, + constants.ISPEC_NIC_COUNT: 9, + constants.ISPEC_SPINDLE_USE: 18, + }, } + diff_std = { + constants.ISPEC_DISK_COUNT: 10, + constants.ISPEC_DISK_SIZE: 512, + } diff_policy = { - constants.ISPECS_MINMAX: { - ispec_key: diff_ispec, - }, + constants.ISPECS_MINMAX: diff_minmax } if not isgroup: - diff_std = { - constants.ISPEC_CPU_COUNT: 3, - constants.ISPEC_DISK_COUNT: 3, - } diff_policy[constants.ISPECS_STD] = diff_std new_policy = cmdlib._GetUpdatedIPolicy(old_policy, diff_policy, group_policy=isgroup) self.assertTrue(constants.ISPECS_MINMAX in new_policy) - new_ispec = new_policy[constants.ISPECS_MINMAX][ispec_key] - for key in diff_ispec: - self.assertTrue(key in new_ispec) - self.assertEqual(new_ispec[key], diff_ispec[key]) + self.assertEqual(new_policy[constants.ISPECS_MINMAX], diff_minmax) for key in old_policy: if not key in diff_policy: self.assertTrue(key in new_policy) self.assertEqual(new_policy[key], old_policy[key]) - if constants.ISPECS_MINMAX in old_policy: - old_minmax = old_policy[constants.ISPECS_MINMAX] - for key in old_minmax: - if key != ispec_key: - self.assertTrue(key in new_policy[constants.ISPECS_MINMAX]) - self.assertEqual(new_policy[constants.ISPECS_MINMAX][key], - old_minmax[key]) - old_ispec = old_policy[constants.ISPECS_MINMAX][ispec_key] - for key in old_ispec: - if not key in diff_ispec: - self.assertTrue(key in new_ispec) - self.assertEqual(new_ispec[key], old_ispec[key]) - if not isgroup: new_std = new_policy[constants.ISPECS_STD] for key in diff_std: self.assertTrue(key in new_std) self.assertEqual(new_std[key], diff_std[key]) + old_std = old_policy.get(constants.ISPECS_STD, {}) + for key in old_std: + self.assertTrue(key in new_std) + if key not in diff_std: + self.assertEqual(new_std[key], old_std[key]) - - def _TestSet(self, old_policy, isgroup): - diff_policy = { - constants.IPOLICY_VCPU_RATIO: 3, - constants.IPOLICY_SPINDLE_RATIO: 1.9, - } + def _TestSet(self, old_policy, diff_policy, isgroup): new_policy = cmdlib._GetUpdatedIPolicy(old_policy, diff_policy, group_policy=isgroup) for key in diff_policy: @@ -1819,9 +1819,15 @@ class TestGetUpdatedIPolicy(unittest.TestCase): self.assertEqual(new_policy[key], old_policy[key]) def testSet(self): - self._TestSet(self._OLD_GROUP_POLICY, True) + diff_policy = { + constants.IPOLICY_VCPU_RATIO: 3, + constants.IPOLICY_DTS: [constants.DT_FILE], + } + self._TestSet(self._OLD_GROUP_POLICY, diff_policy, True) self._TestSetSpecs(self._OLD_GROUP_POLICY, True) - self._TestSet(self._OLD_CLUSTER_POLICY, False) + self._TestSet({}, diff_policy, True) + self._TestSetSpecs({}, True) + self._TestSet(self._OLD_CLUSTER_POLICY, diff_policy, False) self._TestSetSpecs(self._OLD_CLUSTER_POLICY, False) def testUnset(self): @@ -1838,9 +1844,13 @@ class TestGetUpdatedIPolicy(unittest.TestCase): self.assertTrue(key in new_policy) self.assertEqual(new_policy[key], old_policy[key]) + self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy, + old_policy, diff_policy, group_policy=False) + def _TestInvalidKeys(self, old_policy, isgroup): + INVALID_KEY = "this_key_shouldnt_be_allowed" INVALID_DICT = { - "this_key_shouldnt_be_allowed": 3, + INVALID_KEY: 3, } invalid_policy = INVALID_DICT self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy, @@ -1848,21 +1858,47 @@ class TestGetUpdatedIPolicy(unittest.TestCase): invalid_ispecs = { constants.ISPECS_MINMAX: INVALID_DICT, } - self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy, + self.assertRaises(errors.TypeEnforcementError, cmdlib._GetUpdatedIPolicy, old_policy, invalid_ispecs, group_policy=isgroup) - for key in constants.ISPECS_MINMAX_KEYS: - invalid_ispec = { - constants.ISPECS_MINMAX: { - key: INVALID_DICT, - }, + if isgroup: + invalid_for_group = { + constants.ISPECS_STD: constants.IPOLICY_DEFAULTS[constants.ISPECS_STD], } + self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy, + old_policy, invalid_for_group, group_policy=isgroup) + good_ispecs = self._OLD_CLUSTER_POLICY[constants.ISPECS_MINMAX] + invalid_ispecs = copy.deepcopy(good_ispecs) + invalid_policy = { + constants.ISPECS_MINMAX: invalid_ispecs, + } + for key in constants.ISPECS_MINMAX_KEYS: + ispec = invalid_ispecs[key] + ispec[INVALID_KEY] = None self.assertRaises(errors.TypeEnforcementError, cmdlib._GetUpdatedIPolicy, - old_policy, invalid_ispec, group_policy=isgroup) + old_policy, invalid_policy, group_policy=isgroup) + del ispec[INVALID_KEY] + for par in constants.ISPECS_PARAMETERS: + oldv = ispec[par] + ispec[par] = "this_is_not_good" + self.assertRaises(errors.TypeEnforcementError, + cmdlib._GetUpdatedIPolicy, + old_policy, invalid_policy, group_policy=isgroup) + ispec[par] = oldv + # This is to make sure that no two errors were present during the tests + cmdlib._GetUpdatedIPolicy(old_policy, invalid_policy, group_policy=isgroup) def testInvalidKeys(self): self._TestInvalidKeys(self._OLD_GROUP_POLICY, True) self._TestInvalidKeys(self._OLD_CLUSTER_POLICY, False) + def testInvalidValues(self): + for par in (constants.IPOLICY_PARAMETERS | + frozenset([constants.IPOLICY_DTS])): + bad_policy = { + par: "invalid_value", + } + self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy, {}, + bad_policy, group_policy=True) if __name__ == "__main__": testutils.GanetiTestProgram() diff --git a/test/py/ganeti.config_unittest.py b/test/py/ganeti.config_unittest.py index 71d60e6cc45ad0bfa8812db1f330b1f31756363a..7eff2e6d1a2836e270f77be6623d3cff6fee51db 100755 --- a/test/py/ganeti.config_unittest.py +++ b/test/py/ganeti.config_unittest.py @@ -436,11 +436,9 @@ class TestConfigRunner(unittest.TestCase): # depending on the owner (cluster or group) if isgroup: errs = cfg.VerifyConfig() - # FIXME: A bug in FillIPolicy (issue 401) makes this test fail, so we - # invert the assertions for the time being - self.assertFalse(len(errs) >= 1) + self.assertTrue(len(errs) >= 1) errstr = "%s has invalid instance policy" % ipowner - self.assertFalse(_IsErrorInList(errstr, errs)) + self.assertTrue(_IsErrorInList(errstr, errs)) else: self.assertRaises(AssertionError, cfg.VerifyConfig) del ipolicy[INVALID_KEY] @@ -461,13 +459,17 @@ class TestConfigRunner(unittest.TestCase): else: del ipolicy[key] - ispeclist = [ - (ipolicy[constants.ISPECS_MINMAX][constants.ISPECS_MIN], - "%s/%s" % (constants.ISPECS_MINMAX, constants.ISPECS_MIN)), - (ipolicy[constants.ISPECS_MINMAX][constants.ISPECS_MAX], - "%s/%s" % (constants.ISPECS_MINMAX, constants.ISPECS_MAX)), - (ipolicy[constants.ISPECS_STD], constants.ISPECS_STD), - ] + ispeclist = [] + if constants.ISPECS_MINMAX in ipolicy: + ispeclist.extend([ + (ipolicy[constants.ISPECS_MINMAX][constants.ISPECS_MIN], + "%s/%s" % (constants.ISPECS_MINMAX, constants.ISPECS_MIN)), + (ipolicy[constants.ISPECS_MINMAX][constants.ISPECS_MAX], + "%s/%s" % (constants.ISPECS_MINMAX, constants.ISPECS_MAX)), + ]) + if constants.ISPECS_STD in ipolicy: + ispeclist.append((ipolicy[constants.ISPECS_STD], constants.ISPECS_STD)) + for (ispec, ispecpath) in ispeclist: ispec[INVALID_KEY] = None errs = cfg.VerifyConfig() @@ -494,6 +496,28 @@ class TestConfigRunner(unittest.TestCase): errs = cfg.VerifyConfig() self.assertFalse(errs) + if constants.ISPECS_MINMAX in ipolicy: + # Test partial minmax specs + minmax = ipolicy[constants.ISPECS_MINMAX] + for key in constants.ISPECS_MINMAX_KEYS: + self.assertTrue(key in minmax) + ispec = minmax[key] + del minmax[key] + errs = cfg.VerifyConfig() + self.assertTrue(len(errs) >= 1) + self.assertTrue(_IsErrorInList("Missing instance specification", errs)) + minmax[key] = ispec + for par in constants.ISPECS_PARAMETERS: + oldv = ispec[par] + del ispec[par] + errs = cfg.VerifyConfig() + self.assertTrue(len(errs) >= 1) + self.assertTrue(_IsErrorInList("Missing instance specs parameters", + errs)) + ispec[par] = oldv + errs = cfg.VerifyConfig() + self.assertFalse(errs) + def _TestVerifyConfigGroupIPolicy(self, groupinfo, cfg): old_ipolicy = groupinfo.ipolicy ipolicy = cfg.GetClusterInfo().SimpleFillIPolicy({}) @@ -506,16 +530,6 @@ class TestConfigRunner(unittest.TestCase): errs = cfg.VerifyConfig() self.assertFalse(errs) ipolicy[key] = oldv - # Test partial minmax specs - minmax = ipolicy[constants.ISPECS_MINMAX] - for ispec_key in minmax.keys(): - ispec = minmax[ispec_key] - for par in constants.ISPECS_PARAMETERS: - oldv = ispec[par] - del ispec[par] - errs = cfg.VerifyConfig() - self.assertFalse(errs) - ispec[par] = oldv groupinfo.ipolicy = old_ipolicy def _TestVerifyConfigClusterIPolicy(self, ipolicy, cfg): @@ -526,14 +540,18 @@ class TestConfigRunner(unittest.TestCase): del ipolicy[key] self.assertRaises(AssertionError, cfg.VerifyConfig) ipolicy[key] = oldv - # Test partial minmax specs - minmax = ipolicy[constants.ISPECS_MINMAX] - for key in constants.ISPECS_MINMAX_KEYS: - self.assertTrue(key in minmax) - oldv = minmax[key] - del minmax[key] - self.assertRaises(AssertionError, cfg.VerifyConfig) - minmax[key] = oldv + errs = cfg.VerifyConfig() + self.assertFalse(errs) + # Partial standard specs + ispec = ipolicy[constants.ISPECS_STD] + for par in constants.ISPECS_PARAMETERS: + oldv = ispec[par] + del ispec[par] + errs = cfg.VerifyConfig() + self.assertTrue(len(errs) >= 1) + self.assertTrue(_IsErrorInList("Missing instance specs parameters", + errs)) + ispec[par] = oldv errs = cfg.VerifyConfig() self.assertFalse(errs) diff --git a/test/py/ganeti.objects_unittest.py b/test/py/ganeti.objects_unittest.py index 4bc7f95a666e9710545ed6c2c5d00489689d842c..f1b211d5c895a1a4fd4c13cafae3c8f3ef494475 100755 --- a/test/py/ganeti.objects_unittest.py +++ b/test/py/ganeti.objects_unittest.py @@ -460,18 +460,6 @@ class TestInstancePolicy(unittest.TestCase): def testCheckISpecParamSyntax(self): par = "my_parameter" for check_std in [True, False]: - # Only one policy limit - for key in constants.ISPECS_MINMAX_KEYS: - minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS) - minmax[key][par] = 11 - objects.InstancePolicy._CheckISpecParamSyntax(minmax, {}, par, - check_std) - if check_std: - minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS) - stdspec = {par: 11} - objects.InstancePolicy._CheckISpecParamSyntax(minmax, stdspec, par, - check_std) - # Min and max only good_values = [(11, 11), (11, 40), (0, 0)] for (mn, mx) in good_values: @@ -588,34 +576,6 @@ class TestInstancePolicy(unittest.TestCase): self._AssertIPolicyIsFull(policy) self._AssertIPolicyMerged(constants.IPOLICY_DEFAULTS, diff_pol, policy) - def testFillIPolicySpecs(self): - partial_ipolicies = [ - { - constants.ISPECS_MINMAX: { - constants.ISPECS_MIN: {constants.ISPEC_MEM_SIZE: 32}, - constants.ISPECS_MAX: {constants.ISPEC_CPU_COUNT: 1024} - }, - }, - { - constants.ISPECS_MINMAX: { - constants.ISPECS_MAX: { - constants.ISPEC_DISK_COUNT: constants.MAX_DISKS - 1, - constants.ISPEC_NIC_COUNT: constants.MAX_NICS - 1, - }, - constants.ISPECS_MIN: {}, - }, - constants.ISPECS_STD: {constants.ISPEC_DISK_SIZE: 2048}, - }, - { - constants.ISPECS_STD: {constants.ISPEC_SPINDLE_USE: 3}, - }, - ] - for diff_pol in partial_ipolicies: - policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, diff_pol) - objects.InstancePolicy.CheckParameterSyntax(policy, True) - self._AssertIPolicyIsFull(policy) - self._AssertIPolicyMerged(constants.IPOLICY_DEFAULTS, diff_pol, policy) - if __name__ == "__main__": testutils.GanetiTestProgram()