diff --git a/lib/backend.py b/lib/backend.py index 8f53364aceb00a0d846824b2f11ad07de12a2c4e..8426fee78a7dca654b01d19932ba2c01f76c67d0 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -506,6 +506,15 @@ def VerifyNode(what, cluster_name): val = "Error while checking hypervisor: %s" % str(err) tmp[hv_name] = val + if constants.NV_HVPARAMS in what and vm_capable: + result[constants.NV_HVPARAMS] = tmp = [] + for source, hv_name, hvparms in what[constants.NV_HVPARAMS]: + try: + logging.info("Validating hv %s, %s", hv_name, hvparms) + hypervisor.GetHypervisor(hv_name).ValidateParameters(hvparms) + except errors.HypervisorError, err: + tmp.append((source, hv_name, str(err))) + if constants.NV_FILELIST in what: result[constants.NV_FILELIST] = utils.FingerprintFiles( what[constants.NV_FILELIST]) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index c5620186a5b956759ebdb0cf77585fda42847622..6051ee5e6d4e56b329f46e1e76f157a817517d69 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -1397,6 +1397,13 @@ class LUClusterVerify(LogicalUnit): _ErrorIf(test, self.ENODEHV, node, "hypervisor %s verify failure: '%s'", hv_name, hv_result) + hvp_result = nresult.get(constants.NV_HVPARAMS, None) + if ninfo.vm_capable and isinstance(hvp_result, list): + for item, hv_name, hv_result in hvp_result: + _ErrorIf(True, self.ENODEHV, node, + "hypervisor %s parameter verify failure (source %s): %s", + hv_name, item, hv_result) + test = nresult.get(constants.NV_NODESETUP, ["Missing NODESETUP results"]) _ErrorIf(test, self.ENODESETUP, node, "node setup error: %s", @@ -2029,6 +2036,21 @@ class LUClusterVerify(LogicalUnit): return instdisk + def _VerifyHVP(self, hvp_data): + """Verifies locally the syntax of the hypervisor parameters. + + """ + for item, hv_name, hv_params in hvp_data: + msg = ("hypervisor %s parameters syntax check (source %s): %%s" % + (item, hv_name)) + try: + hv_class = hypervisor.GetHypervisor(hv_name) + utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES) + hv_class.CheckParameterSyntax(hv_params) + except errors.GenericError, err: + self._ErrorIf(True, self.ECLUSTERCFG, None, msg % str(err)) + + def BuildHooksEnv(self): """Build hooks env. @@ -2094,12 +2116,32 @@ class LUClusterVerify(LogicalUnit): local_checksums = utils.FingerprintFiles(file_names) + # Compute the set of hypervisor parameters + hvp_data = [] + for hv_name in hypervisors: + hvp_data.append(("cluster", hv_name, cluster.GetHVDefaults(hv_name))) + for os_name, os_hvp in cluster.os_hvp.items(): + for hv_name, hv_params in os_hvp.items(): + if not hv_params: + continue + full_params = cluster.GetHVDefaults(hv_name, os_name=os_name) + hvp_data.append(("os %s" % os_name, hv_name, full_params)) + # TODO: collapse identical parameter values in a single one + for instance in instanceinfo.values(): + if not instance.hvparams: + continue + hvp_data.append(("instance %s" % instance.name, instance.hypervisor, + cluster.FillHV(instance))) + # and verify them locally + self._VerifyHVP(hvp_data) + feedback_fn("* Gathering data (%d nodes)" % len(nodelist)) node_verify_param = { constants.NV_FILELIST: file_names, constants.NV_NODELIST: [node.name for node in nodeinfo if not node.offline], constants.NV_HYPERVISOR: hypervisors, + constants.NV_HVPARAMS: hvp_data, constants.NV_NODENETTEST: [(node.name, node.primary_ip, node.secondary_ip) for node in nodeinfo if not node.offline], diff --git a/lib/constants.py b/lib/constants.py index df51ef38d4863fdbc1da94e2145ffee19d0477a9..37ef696a57cd747fa408ef5af771973d447086ba 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -838,6 +838,7 @@ NV_DRBDLIST = "drbd-list" NV_FILELIST = "filelist" NV_HVINFO = "hvinfo" NV_HYPERVISOR = "hypervisor" +NV_HVPARAMS = "hvparms" NV_INSTANCELIST = "instancelist" NV_LVLIST = "lvlist" NV_MASTERIP = "master-ip" diff --git a/lib/utils/__init__.py b/lib/utils/__init__.py index 5fd66d9b2d5870da35544e8274fdba3322a88681..cdf6a13e26e855f0fe7aee27aecc5c1097211c09 100644 --- a/lib/utils/__init__.py +++ b/lib/utils/__init__.py @@ -82,7 +82,7 @@ def ForceDictType(target, key_types, allowed_values=None): for key in target: if key not in key_types: - msg = "Unknown key '%s'" % key + msg = "Unknown parameter '%s'" % key raise errors.TypeEnforcementError(msg) if target[key] in allowed_values: