Commit 0f511c8a authored by Bernardo Dal Seno's avatar Bernardo Dal Seno
Browse files

Limit specs in instance policies are always complete



Specs used to specify limits in instance policies are always complete, even
at group level (only the whole limit set can be overridden). This is in
preparation for introducing multiple limits.
Signed-off-by: default avatarBernardo Dal Seno <bdalseno@google.com>
Reviewed-by: default avatarHelga Velroyen <helgav@google.com>
parent 62fed51b
...@@ -3731,7 +3731,7 @@ def FormatPolicyInfo(custom_ipolicy, eff_ipolicy, iscluster): ...@@ -3731,7 +3731,7 @@ def FormatPolicyInfo(custom_ipolicy, eff_ipolicy, iscluster):
if iscluster: if iscluster:
eff_ipolicy = custom_ipolicy eff_ipolicy = custom_ipolicy
custom_minmax = custom_ipolicy.get(constants.ISPECS_MINMAX) custom_minmax = custom_ipolicy.get(constants.ISPECS_MINMAX, {})
ret = [ ret = [
(key, (key,
FormatParamsDictInfo(custom_minmax.get(key, {}), FormatParamsDictInfo(custom_minmax.get(key, {}),
......
...@@ -813,20 +813,6 @@ def _GetUpdatedParams(old_params, update_dict, ...@@ -813,20 +813,6 @@ def _GetUpdatedParams(old_params, update_dict,
return params_copy 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): def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False):
"""Return the new version of an instance policy. """Return the new version of an instance policy.
   
...@@ -834,41 +820,43 @@ def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False): ...@@ -834,41 +820,43 @@ def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False):
we should support removal of policy entries we should support removal of policy entries
   
""" """
use_none = use_default = group_policy
ipolicy = copy.deepcopy(old_ipolicy) ipolicy = copy.deepcopy(old_ipolicy)
for key, value in new_ipolicy.items(): for key, value in new_ipolicy.items():
if key not in constants.IPOLICY_ALL_KEYS: if key not in constants.IPOLICY_ALL_KEYS:
raise errors.OpPrereqError("Invalid key in new ipolicy: %s" % key, raise errors.OpPrereqError("Invalid key in new ipolicy: %s" % key,
errors.ECODE_INVAL) errors.ECODE_INVAL)
if key == constants.ISPECS_MINMAX: if (not value or value == [constants.VALUE_DEFAULT] or
_UpdateMinMaxISpecs(ipolicy, value, group_policy) value == constants.VALUE_DEFAULT):
elif key == constants.ISPECS_STD: if group_policy:
ipolicy[key] = _GetUpdatedParams(old_ipolicy.get(key, {}), value, del ipolicy[key]
use_none=use_none, else:
use_default=use_default) raise errors.OpPrereqError("Can't unset ipolicy attribute '%s'"
utils.ForceDictType(ipolicy[key], constants.ISPECS_PARAMETER_TYPES) " on the cluster'" % key,
errors.ECODE_INVAL)
else: else:
if (not value or value == [constants.VALUE_DEFAULT] or if key in constants.IPOLICY_PARAMETERS:
value == constants.VALUE_DEFAULT): # 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: if group_policy:
del ipolicy[key] msg = "%s cannot appear in group instance specs" % key
else: raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
raise errors.OpPrereqError("Can't unset ipolicy attribute '%s'" ipolicy[key] = _GetUpdatedParams(old_ipolicy.get(key, {}), value,
" on the cluster'" % key, use_none=False, use_default=False)
errors.ECODE_INVAL) utils.ForceDictType(ipolicy[key], constants.ISPECS_PARAMETER_TYPES)
else: else:
if key in constants.IPOLICY_PARAMETERS: # FIXME: we assume all others are lists; this should be redone
# FIXME: we assume all such values are float # in a nicer way
try: ipolicy[key] = list(value)
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)
try: try:
objects.InstancePolicy.CheckParameterSyntax(ipolicy, not group_policy) objects.InstancePolicy.CheckParameterSyntax(ipolicy, not group_policy)
except errors.ConfigurationError, err: except errors.ConfigurationError, err:
......
...@@ -82,35 +82,17 @@ def FillDict(defaults_dict, custom_dict, skip_keys=None): ...@@ -82,35 +82,17 @@ def FillDict(defaults_dict, custom_dict, skip_keys=None):
return ret_dict 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): def FillIPolicy(default_ipolicy, custom_ipolicy):
"""Fills an instance policy with defaults. """Fills an instance policy with defaults.
""" """
assert frozenset(default_ipolicy.keys()) == constants.IPOLICY_ALL_KEYS assert frozenset(default_ipolicy.keys()) == constants.IPOLICY_ALL_KEYS
ret_dict = {} ret_dict = copy.deepcopy(custom_ipolicy)
# Instance specs for key in default_ipolicy:
new_mm = _FillMinMaxISpecs(default_ipolicy[constants.ISPECS_MINMAX], if key not in ret_dict:
custom_ipolicy.get(constants.ISPECS_MINMAX, {})) ret_dict[key] = copy.deepcopy(default_ipolicy[key])
ret_dict[constants.ISPECS_MINMAX] = new_mm elif key == constants.ISPECS_STD:
new_std = FillDict(default_ipolicy[constants.ISPECS_STD], ret_dict[key] = FillDict(default_ipolicy[key], ret_dict[key])
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])
return ret_dict return ret_dict
...@@ -198,13 +180,7 @@ def MakeEmptyIPolicy(): ...@@ -198,13 +180,7 @@ def MakeEmptyIPolicy():
"""Create empty IPolicy dictionary. """Create empty IPolicy dictionary.
""" """
return { return {}
constants.ISPECS_MINMAX: {
constants.ISPECS_MIN: {},
constants.ISPECS_MAX: {},
},
constants.ISPECS_STD: {},
}
class ConfigObject(outils.ValidatedSlots): class ConfigObject(outils.ValidatedSlots):
...@@ -953,6 +929,14 @@ class InstancePolicy(ConfigObject): ...@@ -953,6 +929,14 @@ class InstancePolicy(ConfigObject):
raise errors.ConfigurationError("Invalid keys in ipolicy: %s" % raise errors.ConfigurationError("Invalid keys in ipolicy: %s" %
utils.CommaJoin(wrong_keys)) 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 @classmethod
def CheckISpecSyntax(cls, ipolicy, check_std): def CheckISpecSyntax(cls, ipolicy, check_std):
"""Check the instance policy specs for validity. """Check the instance policy specs for validity.
...@@ -977,6 +961,10 @@ class InstancePolicy(ConfigObject): ...@@ -977,6 +961,10 @@ class InstancePolicy(ConfigObject):
if missing: if missing:
msg = "Missing instance specification: %s" % utils.CommaJoin(missing) msg = "Missing instance specification: %s" % utils.CommaJoin(missing)
raise errors.ConfigurationError(msg) 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: for param in constants.ISPECS_PARAMETERS:
InstancePolicy._CheckISpecParamSyntax(minmaxspecs, stdspec, param, InstancePolicy._CheckISpecParamSyntax(minmaxspecs, stdspec, param,
check_std) check_std)
...@@ -1002,7 +990,7 @@ class InstancePolicy(ConfigObject): ...@@ -1002,7 +990,7 @@ class InstancePolicy(ConfigObject):
""" """
minspec = minmaxspecs[constants.ISPECS_MIN] minspec = minmaxspecs[constants.ISPECS_MIN]
maxspec = minmaxspecs[constants.ISPECS_MAX] maxspec = minmaxspecs[constants.ISPECS_MAX]
min_v = minspec.get(name, 0) min_v = minspec[name]
if check_std: if check_std:
std_v = stdspec.get(name, min_v) std_v = stdspec.get(name, min_v)
...@@ -1011,13 +999,10 @@ class InstancePolicy(ConfigObject): ...@@ -1011,13 +999,10 @@ class InstancePolicy(ConfigObject):
std_v = min_v std_v = min_v
std_msg = "-" std_msg = "-"
max_v = maxspec.get(name, std_v) max_v = maxspec[name]
if min_v > std_v or std_v > max_v: if min_v > std_v or std_v > max_v:
err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" % err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" %
(name, (name, min_v, max_v, std_msg))
minspec.get(name, "-"),
maxspec.get(name, "-"),
std_msg))
raise errors.ConfigurationError(err) raise errors.ConfigurationError(err)
@classmethod @classmethod
......
...@@ -66,9 +66,7 @@ module Ganeti.Objects ...@@ -66,9 +66,7 @@ module Ganeti.Objects
, PartialISpecParams(..) , PartialISpecParams(..)
, fillISpecParams , fillISpecParams
, allISpecParamFields , allISpecParamFields
, FilledMinMaxISpecs(..) , MinMaxISpecs(..)
, PartialMinMaxISpecs(..)
, fillMinMaxISpecs
, FilledIPolicy(..) , FilledIPolicy(..)
, PartialIPolicy(..) , PartialIPolicy(..)
, fillIPolicy , fillIPolicy
...@@ -505,16 +503,7 @@ $(buildParam "ISpec" "ispec" ...@@ -505,16 +503,7 @@ $(buildParam "ISpec" "ispec"
, simpleField C.ispecSpindleUse [t| Int |] , simpleField C.ispecSpindleUse [t| Int |]
]) ])
-- | Partial min-max instance specs. These is not built via buildParam since $(buildObject "MinMaxISpecs" "mmis"
-- 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"
[ renameField "MinSpec" $ simpleField "min" [t| FilledISpecParams |] [ renameField "MinSpec" $ simpleField "min" [t| FilledISpecParams |]
, renameField "MaxSpec" $ simpleField "max" [t| FilledISpecParams |] , renameField "MaxSpec" $ simpleField "max" [t| FilledISpecParams |]
]) ])
...@@ -523,8 +512,9 @@ $(buildObject "FilledMinMaxISpecs" "mmis" ...@@ -523,8 +512,9 @@ $(buildObject "FilledMinMaxISpecs" "mmis"
-- has a special 2-level inheritance mode. -- has a special 2-level inheritance mode.
$(buildObject "PartialIPolicy" "ipolicy" $(buildObject "PartialIPolicy" "ipolicy"
[ optionalField . renameField "MinMaxISpecsP" [ optionalField . renameField "MinMaxISpecsP"
$ simpleField C.ispecsMinmax [t| PartialMinMaxISpecs |] $ simpleField C.ispecsMinmax [t| MinMaxISpecs |]
, renameField "StdSpecP" $ simpleField "std" [t| PartialISpecParams |] , optionalField . renameField "StdSpecP"
$ simpleField "std" [t| PartialISpecParams |]
, optionalField . renameField "SpindleRatioP" , optionalField . renameField "SpindleRatioP"
$ simpleField "spindle-ratio" [t| Double |] $ simpleField "spindle-ratio" [t| Double |]
, optionalField . renameField "VcpuRatioP" , optionalField . renameField "VcpuRatioP"
...@@ -537,24 +527,13 @@ $(buildObject "PartialIPolicy" "ipolicy" ...@@ -537,24 +527,13 @@ $(buildObject "PartialIPolicy" "ipolicy"
-- has a special 2-level inheritance mode. -- has a special 2-level inheritance mode.
$(buildObject "FilledIPolicy" "ipolicy" $(buildObject "FilledIPolicy" "ipolicy"
[ renameField "MinMaxISpecs" [ renameField "MinMaxISpecs"
$ simpleField C.ispecsMinmax [t| FilledMinMaxISpecs |] $ simpleField C.ispecsMinmax [t| MinMaxISpecs |]
, renameField "StdSpec" $ simpleField "std" [t| FilledISpecParams |] , renameField "StdSpec" $ simpleField "std" [t| FilledISpecParams |]
, simpleField "spindle-ratio" [t| Double |] , simpleField "spindle-ratio" [t| Double |]
, simpleField "vcpu-ratio" [t| Double |] , simpleField "vcpu-ratio" [t| Double |]
, simpleField "disk-templates" [t| [DiskTemplate] |] , 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. -- | Custom filler for the ipolicy types.
fillIPolicy :: FilledIPolicy -> PartialIPolicy -> FilledIPolicy fillIPolicy :: FilledIPolicy -> PartialIPolicy -> FilledIPolicy
fillIPolicy (FilledIPolicy { ipolicyMinMaxISpecs = fminmax fillIPolicy (FilledIPolicy { ipolicyMinMaxISpecs = fminmax
...@@ -567,8 +546,10 @@ fillIPolicy (FilledIPolicy { ipolicyMinMaxISpecs = fminmax ...@@ -567,8 +546,10 @@ fillIPolicy (FilledIPolicy { ipolicyMinMaxISpecs = fminmax
, ipolicySpindleRatioP = pspindleRatio , ipolicySpindleRatioP = pspindleRatio
, ipolicyVcpuRatioP = pvcpuRatio , ipolicyVcpuRatioP = pvcpuRatio
, ipolicyDiskTemplatesP = pdiskTemplates}) = , ipolicyDiskTemplatesP = pdiskTemplates}) =
FilledIPolicy { ipolicyMinMaxISpecs = fillMinMaxISpecs fminmax pminmax FilledIPolicy { ipolicyMinMaxISpecs = fromMaybe fminmax pminmax
, ipolicyStdSpec = fillISpecParams fstd pstd , ipolicyStdSpec = case pstd of
Nothing -> fstd
Just p -> fillISpecParams fstd p
, ipolicySpindleRatio = fromMaybe fspindleRatio pspindleRatio , ipolicySpindleRatio = fromMaybe fspindleRatio pspindleRatio
, ipolicyVcpuRatio = fromMaybe fvcpuRatio pvcpuRatio , ipolicyVcpuRatio = fromMaybe fvcpuRatio pvcpuRatio
, ipolicyDiskTemplates = fromMaybe fdiskTemplates , ipolicyDiskTemplates = fromMaybe fdiskTemplates
......
...@@ -143,14 +143,13 @@ genInstWithNets nets = do ...@@ -143,14 +143,13 @@ genInstWithNets nets = do
-- | FIXME: This generates completely random data, without normal -- | FIXME: This generates completely random data, without normal
-- validation rules. -- validation rules.
$(genArbitrary ''PartialISpecParams) $(genArbitrary ''PartialISpecParams)
$(genArbitrary ''PartialMinMaxISpecs)
-- | FIXME: This generates completely random data, without normal -- | FIXME: This generates completely random data, without normal
-- validation rules. -- validation rules.
$(genArbitrary ''PartialIPolicy) $(genArbitrary ''PartialIPolicy)
$(genArbitrary ''FilledISpecParams) $(genArbitrary ''FilledISpecParams)
$(genArbitrary ''FilledMinMaxISpecs) $(genArbitrary ''MinMaxISpecs)
$(genArbitrary ''FilledIPolicy) $(genArbitrary ''FilledIPolicy)
$(genArbitrary ''IpFamily) $(genArbitrary ''IpFamily)
$(genArbitrary ''FilledNDParams) $(genArbitrary ''FilledNDParams)
......
...@@ -1733,81 +1733,81 @@ class TestGetUpdatedIPolicy(unittest.TestCase): ...@@ -1733,81 +1733,81 @@ class TestGetUpdatedIPolicy(unittest.TestCase):
"""Tests for cmdlib._GetUpdatedIPolicy()""" """Tests for cmdlib._GetUpdatedIPolicy()"""
_OLD_CLUSTER_POLICY = { _OLD_CLUSTER_POLICY = {
constants.IPOLICY_VCPU_RATIO: 1.5, constants.IPOLICY_VCPU_RATIO: 1.5,
constants.ISPECS_MINMAX: { constants.ISPECS_MINMAX: constants.ISPECS_MINMAX_DEFAULTS,
constants.ISPECS_MIN: { constants.ISPECS_STD: constants.IPOLICY_DEFAULTS[constants.ISPECS_STD],
constants.ISPEC_MEM_SIZE: 20,
constants.ISPEC_CPU_COUNT: 2,
},
constants.ISPECS_MAX: {},
},
constants.ISPECS_STD: {},
} }
_OLD_GROUP_POLICY = { _OLD_GROUP_POLICY = {
constants.IPOLICY_SPINDLE_RATIO: 2.5, constants.IPOLICY_SPINDLE_RATIO: 2.5,
constants.ISPECS_MINMAX: { constants.ISPECS_MINMAX: {
constants.ISPECS_MIN: { constants.ISPECS_MIN: {
constants.ISPEC_DISK_SIZE: 20, constants.ISPEC_MEM_SIZE: 128,
constants.ISPEC_NIC_COUNT: 2, 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): def _TestSetSpecs(self, old_policy, isgroup):
ispec_key = constants.ISPECS_MIN diff_minmax = {
diff_ispec = { constants.ISPECS_MIN: {
constants.ISPEC_MEM_SIZE: 50, constants.ISPEC_MEM_SIZE: 64,
constants.ISPEC_DISK_SIZE: 30, 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 = { diff_policy = {
constants.ISPECS_MINMAX: { constants.ISPECS_MINMAX: diff_minmax
ispec_key: diff_ispec,
},
} }
if not isgroup: if not isgroup:
diff_std = {
constants.ISPEC_CPU_COUNT: 3,
constants.ISPEC_DISK_COUNT: 3,
}
diff_policy[constants.ISPECS_STD] = diff_std diff_policy[constants.ISPECS_STD] = diff_std
new_policy = cmdlib._GetUpdatedIPolicy(old_policy, diff_policy, new_policy = cmdlib._GetUpdatedIPolicy(old_policy, diff_policy,
group_policy=isgroup) group_policy=isgroup)
self.assertTrue(constants.ISPECS_MINMAX in new_policy) self.assertTrue(constants.ISPECS_MINMAX in new_policy)
new_ispec = new_policy[constants.ISPECS_MINMAX][ispec_key] self.assertEqual(new_policy[constants.ISPECS_MINMAX], diff_minmax)
for key in diff_ispec:
self.assertTrue(key in new_ispec)
self.assertEqual(new_ispec[key], diff_ispec[key])
for key in old_policy: for key in old_policy:
if not key in diff_policy: if not key in diff_policy:
self.assertTrue(key in new_policy) self.assertTrue(key in new_policy)
self.assertEqual(new_policy[key], old_policy[key]) 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: if not isgroup:
new_std = new_policy[constants.ISPECS_STD] new_std = new_policy[constants.ISPECS_STD]
for key in diff_std: for key in diff_std:
self.assertTrue(key in new_std) self.assertTrue(key in new_std)
self.assertEqual(new_std[key], diff_std[key]) 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, diff_policy, isgroup):
def _TestSet(self, old_policy, isgroup):
diff_policy = {
constants.IPOLICY_VCPU_RATIO: 3,
constants.IPOLICY_SPINDLE_RATIO: 1.9,
}
new_policy = cmdlib._GetUpdatedIPolicy(old_policy, diff_policy, new_policy = cmdlib._GetUpdatedIPolicy(old_policy, diff_policy,
group_policy=isgroup) group_policy=isgroup)
for key in diff_policy: for key in diff_policy:
...@@ -1819,9 +1819,15 @@ class TestGetUpdatedIPolicy(unittest.TestCase): ...@@ -1819,9 +1819,15 @@ class TestGetUpdatedIPolicy(unittest.TestCase):
self.assertEqual(new_policy[key], old_policy[key]) self.assertEqual(new_policy[key], old_policy[key])
def testSet(self): 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._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) self._TestSetSpecs(self._OLD_CLUSTER_POLICY, False)
def testUnset(self): def testUnset(self):
...@@ -1838,9 +1844,13 @@ class TestGetUpdatedIPolicy(unittest.TestCase): ...@@ -1838,9 +1844,13 @@ class TestGetUpdatedIPolicy(unittest.TestCase):
self.assertTrue(key in new_policy) self.assertTrue(key in new_policy)
self.assertEqual(new_policy[key], old_policy[key]) 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): def _TestInvalidKeys(self, old_policy, isgroup):
INVALID_KEY = "this_key_shouldnt_be_allowed"
INVALID_DICT = { INVALID_DICT = {
"this_key_shouldnt_be_allowed": 3, INVALID_KEY: 3,
} }
invalid_policy = INVALID_DICT invalid_policy = INVALID_DICT
self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy, self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy,
...@@ -1848,21 +1858,47 @@ class TestGetUpdatedIPolicy(unittest.TestCase): ...@@ -1848,21 +1858,47 @@ class TestGetUpdatedIPolicy(unittest.TestCase):
invalid_ispecs = { invalid_ispecs = {
constants.ISPECS_MINMAX: INVALID_DICT, constants.ISPECS_MINMAX: INVALID_DICT,
} }
self.assertRaises(errors.OpPrereqError, cmdlib._GetUpdatedIPolicy, self.assertRaises(errors.TypeEnforcementError, cmdlib._GetUpdatedIPolicy,
old_policy, invalid_ispecs, group_policy=isgroup) old_policy, invalid_ispecs, group_policy=isgroup)
for key in constants.ISPECS_MINMAX_KEYS: if isgroup:
invalid_ispec = { invalid_for_group = {
constants.ISPECS_MINMAX: { constants.ISPECS_STD: constants.IPOLICY_DEFAULTS[constants.ISPECS_STD],
key: INVALID_DICT,
},
} }
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,
}