diff --git a/lib/cmdlib.py b/lib/cmdlib.py index cbd49868f4dfd359d41b91f62101c1d10631fc34..1afff359e440561540dcf85bcaf27271ee0762ca 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -1016,6 +1016,26 @@ def _CheckInstanceState(lu, instance, req_states, msg=None): (instance.name, msg), errors.ECODE_STATE) +def _CheckMinMaxSpecs(name, ipolicy, value): + """Checks if value is in the desired range. + + @param name: name of the parameter for which we perform the check + @param ipolicy: dictionary containing min, max and std values + @param value: actual value that we want to use + @return: None or element not meeting the criteria + + + """ + if value in [None, constants.VALUE_AUTO]: + return None + max_v = ipolicy[constants.MAX_ISPECS].get(name, value) + min_v = ipolicy[constants.MIN_ISPECS].get(name, value) + if value > max_v or min_v > value: + return ("%s value %s is not in range [%s, %s]" % + (name, value, min_v, max_v)) + return None + + def _ExpandItemName(fn, name, kind): """Expand an item name. @@ -2115,6 +2135,34 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors): msg = "cannot reach the master IP" _ErrorIf(True, constants.CV_ENODENET, node, msg) + def _VerifyInstancePolicy(self, instance): + """Verify instance specs against instance policy set on node group level. + + + """ + cluster = self.cfg.GetClusterInfo() + full_beparams = cluster.FillBE(instance) + ipolicy = cluster.SimpleFillIPolicy(self.group_info.ipolicy) + + mem_size = full_beparams.get(constants.BE_MAXMEM, None) + cpu_count = full_beparams.get(constants.BE_VCPUS, None) + disk_count = len(instance.disks) + disk_sizes = [disk.size for disk in instance.disks] + nic_count = len(instance.nics) + + test_settings = [ + (constants.MEM_SIZE_SPEC, mem_size), + (constants.CPU_COUNT_SPEC, cpu_count), + (constants.DISK_COUNT_SPEC, disk_count), + (constants.NIC_COUNT_SPEC, nic_count), + ] + map((lambda d: (constants.DISK_SIZE_SPEC, d)), disk_sizes) + + for (name, value) in test_settings: + test_result = _CheckMinMaxSpecs(name, ipolicy, value) + self._ErrorIf(test_result is not None, + constants.CV_EINSTANCEPOLICY, instance.name, + test_result) + def _VerifyInstance(self, instance, instanceconfig, node_image, diskstatus): """Verify an instance. @@ -2129,6 +2177,8 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors): node_vol_should = {} instanceconfig.MapLVsByNode(node_vol_should) + self._VerifyInstancePolicy(instanceconfig) + for node in node_vol_should: n_img = node_image[node] if n_img.offline or n_img.rpc_fail or n_img.lvm_fail: diff --git a/lib/constants.py b/lib/constants.py index 27a993cfe4b499ad9f5e33d2ec79d19d0090cc4f..0d796572d12133e0dfe87dbfc7701c15f6ee590d 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -1276,6 +1276,9 @@ CV_EINSTANCEWRONGNODE = \ CV_EINSTANCESPLITGROUPS = \ (CV_TINSTANCE, "EINSTANCESPLITGROUPS", "Instance with primary and secondary nodes in different groups") +CV_EINSTANCEPOLICY = \ + (CV_TINSTANCE, "EINSTANCEPOLICY", + "Instance does not meet policy") CV_ENODEDRBD = \ (CV_TNODE, "ENODEDRBD", "Error parsing the DRBD status file") CV_ENODEDRBDHELPER = \ @@ -1329,6 +1332,7 @@ CV_ALL_ECODES = frozenset([ CV_EINSTANCEFAULTYDISK, CV_EINSTANCEWRONGNODE, CV_EINSTANCESPLITGROUPS, + CV_EINSTANCEPOLICY, CV_ENODEDRBD, CV_ENODEDRBDHELPER, CV_ENODEFILECHECK,