Commit 918eb80b authored by Agata Murawska's avatar Agata Murawska
Browse files

Introduce instance policy on cluster level


Signed-off-by: default avatarAgata Murawska <agatamurawska@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent fcf5b670
......@@ -426,6 +426,17 @@ class ConfigWriter:
except errors.ConfigurationError, err:
result.append("%s has invalid nicparams: %s" % (owner, err))
def _helper_ipolicy(owner, params):
try:
objects.InstancePolicy.CheckParameterSyntax(params)
except errors.ConfigurationError, err:
result.append("%s has invalid instance policy: %s" % (owner, err))
def _helper_ispecs(owner, params):
for key, value in params.iteritems():
fullkey = "ipolicy/" + key
_helper(owner, fullkey, value, constants.ISPECS_PARAMETER_TYPES)
# check cluster parameters
_helper("cluster", "beparams", cluster.SimpleFillBE({}),
constants.BES_PARAMETER_TYPES)
......@@ -434,6 +445,8 @@ class ConfigWriter:
_helper_nic("cluster", cluster.SimpleFillNIC({}))
_helper("cluster", "ndparams", cluster.SimpleFillND({}),
constants.NDS_PARAMETER_TYPES)
_helper_ipolicy("cluster", cluster.SimpleFillIPolicy({}))
_helper_ispecs("cluster", cluster.SimpleFillIPolicy({}))
# per-instance checks
for instance_name in data.instances:
......
......@@ -921,6 +921,33 @@ BES_PARAMETER_COMPAT.update(BES_PARAMETER_TYPES)
BES_PARAMETERS = frozenset(BES_PARAMETER_TYPES.keys())
# instance specs
MEM_SIZE_SPEC = "memory-size"
CPU_COUNT_SPEC = "cpu-count"
DISK_COUNT_SPEC = "disk-count"
DISK_SIZE_SPEC = "disk-size"
NIC_COUNT_SPEC = "nic-count"
ISPECS_PARAMETER_TYPES = {
MEM_SIZE_SPEC: VTYPE_INT,
CPU_COUNT_SPEC: VTYPE_INT,
DISK_COUNT_SPEC: VTYPE_INT,
DISK_SIZE_SPEC: VTYPE_INT,
NIC_COUNT_SPEC: VTYPE_INT,
}
ISPECS_PARAMETERS = frozenset(ISPECS_PARAMETER_TYPES.keys())
MIN_ISPECS = "min"
MAX_ISPECS = "max"
STD_ISPECS = "std"
IPOLICY_PARAMETERS = frozenset([
MIN_ISPECS,
MAX_ISPECS,
STD_ISPECS
])
# Node parameter names
ND_OOB_PROGRAM = "oob_program"
......@@ -1783,6 +1810,30 @@ NICC_DEFAULTS = {
NIC_LINK: DEFAULT_BRIDGE,
}
IPOLICY_DEFAULTS = {
MIN_ISPECS: {
MEM_SIZE_SPEC: 128,
CPU_COUNT_SPEC: 1,
DISK_COUNT_SPEC: 1,
DISK_SIZE_SPEC: 1024,
NIC_COUNT_SPEC: 1,
},
MAX_ISPECS: {
MEM_SIZE_SPEC: 128,
CPU_COUNT_SPEC: 1,
DISK_COUNT_SPEC: 1,
DISK_SIZE_SPEC: 1024,
NIC_COUNT_SPEC: 1,
},
STD_ISPECS: {
MEM_SIZE_SPEC: 128,
CPU_COUNT_SPEC: 1,
DISK_COUNT_SPEC: 1,
DISK_SIZE_SPEC: 1024,
NIC_COUNT_SPEC: 1,
}
}
MASTER_POOL_SIZE_DEFAULT = 10
CONFD_PROTOCOL_VERSION = 1
......
......@@ -79,6 +79,18 @@ def FillDict(defaults_dict, custom_dict, skip_keys=None):
return ret_dict
def FillDictOfDicts(defaults_dict, custom_dict, skip_keys=None):
"""Run FillDict for each key in dictionary.
"""
ret_dict = {}
for key in defaults_dict.keys():
ret_dict[key] = FillDict(defaults_dict[key],
custom_dict.get(key, {}),
skip_keys=skip_keys)
return ret_dict
def UpgradeGroupedParams(target, defaults):
"""Update all groups for the target parameter.
......@@ -136,6 +148,17 @@ def UpgradeDiskParams(diskparams):
return result
def MakeEmptyIPolicy():
"""Create empty IPolicy dictionary.
"""
return dict([
(constants.MIN_ISPECS, dict()),
(constants.MAX_ISPECS, dict()),
(constants.STD_ISPECS, dict()),
])
class ConfigObject(object):
"""A generic config object.
......@@ -780,6 +803,44 @@ class Disk(ConfigObject):
# add here config upgrade for this disk
class InstancePolicy(ConfigObject):
"""Config object representing instance policy limits dictionary."""
__slots__ = ["min", "max", "std"]
@classmethod
def CheckParameterSyntax(cls, ipolicy):
""" Check the instance policy for validity.
"""
for param in constants.ISPECS_PARAMETERS:
InstancePolicy.CheckISpecSyntax(ipolicy, param)
@classmethod
def CheckISpecSyntax(cls, ipolicy, name):
"""Check the instance policy for validity on a given key.
We check if the instance policy makes sense for a given key, that is
if ipolicy[min][name] <= ipolicy[std][name] <= ipolicy[max][name].
@type ipolicy: dict
@param ipolicy: dictionary with min, max, std specs
@type name: string
@param name: what are the limits for
@raise errors.ConfigureError: when specs for given name are not valid
"""
min_v = ipolicy[constants.MIN_ISPECS].get(name, 0)
std_v = ipolicy[constants.STD_ISPECS].get(name, min_v)
max_v = ipolicy[constants.MAX_ISPECS].get(name, std_v)
err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" %
(name,
ipolicy[constants.MIN_ISPECS].get(name, "-"),
ipolicy[constants.MAX_ISPECS].get(name, "-"),
ipolicy[constants.STD_ISPECS].get(name, "-")))
if min_v > std_v or std_v > max_v:
raise errors.ConfigurationError(err)
class Instance(TaggableObject):
"""Config object representing an instance."""
__slots__ = [
......@@ -1238,6 +1299,7 @@ class Cluster(TaggableObject):
"shared_file_storage_dir",
"enabled_hypervisors",
"hvparams",
"ipolicy",
"os_hvp",
"beparams",
"osparams",
......@@ -1354,6 +1416,10 @@ class Cluster(TaggableObject):
self.diskparams = UpgradeDiskParams(self.diskparams)
# instance policy added before 2.6
if self.ipolicy is None:
self.ipolicy = MakeEmptyIPolicy()
@property
def primary_hypervisor(self):
"""The first hypervisor is the primary.
......@@ -1537,6 +1603,18 @@ class Cluster(TaggableObject):
"""
return FillDict(self.ndparams, ndparams)
def SimpleFillIPolicy(self, ipolicy):
""" Fill instance policy dict with defaults.
@type ipolicy: dict
@param ipolicy: the dict to fill
@rtype: dict
@return: a copy of passed ipolicy with missing keys filled from
the cluster defaults
"""
return FillDictOfDicts(self.ipolicy, ipolicy)
class BlockDevStatus(ConfigObject):
"""Config object representing the status of a block device."""
......
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