diff --git a/lib/backend.py b/lib/backend.py index b6f7ceb098a6182886f710489c54b66854389dd8..b42ebe7be97a16ccca9f00d6ce7e3c27201034c5 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -77,7 +77,7 @@ _IES_PID_FILE = "pid" _IES_CA_FILE = "ca" #: Valid LVS output line regex -_LVSLINE_REGEX = re.compile("^ *([^|]+)\|([0-9.]+)\|([^|]{6})\|?$") +_LVSLINE_REGEX = re.compile("^ *([^|]+)\|([^|]+)\|([0-9.]+)\|([^|]{6})\|?$") class RPCFail(Exception): @@ -554,7 +554,7 @@ def VerifyNode(what, cluster_name): if constants.NV_LVLIST in what and vm_capable: try: - val = GetVolumeList(what[constants.NV_LVLIST]) + val = GetVolumeList(utils.ListVolumeGroups().keys()) except RPCFail, err: val = str(err) result[constants.NV_LVLIST] = val @@ -622,17 +622,17 @@ def VerifyNode(what, cluster_name): return result -def GetVolumeList(vg_name): +def GetVolumeList(vg_names): """Compute list of logical volumes and their size. - @type vg_name: str - @param vg_name: the volume group whose LVs we should list + @type vg_names: list + @param vg_names: the volume groups whose LVs we should list @rtype: dict @return: dictionary of all partions (key) with value being a tuple of their size (in MiB), inactive and online status:: - {'test1': ('20.06', True, True)} + {'xenvg/test1': ('20.06', True, True)} in case of errors, a string is returned with the error details. @@ -642,7 +642,7 @@ def GetVolumeList(vg_name): sep = '|' result = utils.RunCmd(["lvs", "--noheadings", "--units=m", "--nosuffix", "--separator=%s" % sep, - "-olv_name,lv_size,lv_attr", vg_name]) + "-ovg_name,lv_name,lv_size,lv_attr"] + vg_names) if result.failed: _Fail("Failed to list logical volumes, lvs output: %s", result.output) @@ -652,7 +652,7 @@ def GetVolumeList(vg_name): if not match: logging.error("Invalid line returned from lvs output: '%s'", line) continue - name, size, attr = match.groups() + vg_name, name, size, attr = match.groups() inactive = attr[4] == '-' online = attr[5] == 'o' virtual = attr[0] == 'v' @@ -660,7 +660,7 @@ def GetVolumeList(vg_name): # we don't want to report such volumes as existing, since they # don't really hold data continue - lvs[name] = (size, inactive, online) + lvs[vg_name+"/"+name] = (size, inactive, online) return lvs diff --git a/lib/cmdlib.py b/lib/cmdlib.py index db0e82cd64f70e6415072fe0f3eac65b9676fdb7..ab8cf39fb8f1cd1bb6bd44a7c96c64bac450bd80 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -2399,7 +2399,6 @@ class LUVerifyDisks(NoHooksLU): """ result = res_nodes, res_instances, res_missing = {}, [], {} - vg_name = self.cfg.GetVGName() nodes = utils.NiceSort(self.cfg.GetNodeList()) instances = [self.cfg.GetInstanceInfo(name) for name in self.cfg.GetInstanceList()] @@ -2419,11 +2418,13 @@ class LUVerifyDisks(NoHooksLU): if not nv_dict: return result - node_lvs = self.rpc.call_lv_list(nodes, vg_name) + vg_names = self.rpc.call_vg_list(nodes) + vg_names.Raise("Cannot get list of VGs") for node in nodes: # node_volume - node_res = node_lvs[node] + node_res = self.rpc.call_lv_list([node], + vg_names[node].payload.keys())[node] if node_res.offline: continue msg = node_res.fail_msg @@ -7678,23 +7679,28 @@ class LUCreateInstance(LogicalUnit): _CheckNodesFreeDiskPerVG(self, nodenames, req_sizes) else: # instead, we must check the adoption data - all_lvs = set([i["adopt"] for i in self.disks]) + all_lvs = set([i["vg"] + "/" + i["adopt"] for i in self.disks]) if len(all_lvs) != len(self.disks): raise errors.OpPrereqError("Duplicate volume names given for adoption", errors.ECODE_INVAL) for lv_name in all_lvs: try: - # FIXME: VG must be provided here. Else all LVs with the - # same name will be locked on all VGs. + # FIXME: lv_name here is "vg/lv" need to ensure that other calls + # to ReserveLV uses the same syntax self.cfg.ReserveLV(lv_name, self.proc.GetECId()) except errors.ReservationError: raise errors.OpPrereqError("LV named %s used by another instance" % lv_name, errors.ECODE_NOTUNIQUE) + vg_names = self.rpc.call_vg_list([pnode.name]) + vg_names.Raise("Cannot get VG information from node %s" % pnode.name) + node_lvs = self.rpc.call_lv_list([pnode.name], - self.cfg.GetVGName())[pnode.name] + vg_names[pnode.name].payload.keys() + )[pnode.name] node_lvs.Raise("Cannot get LV information from node %s" % pnode.name) node_lvs = node_lvs.payload + delta = all_lvs.difference(node_lvs.keys()) if delta: raise errors.OpPrereqError("Missing logical volume(s): %s" % @@ -7707,7 +7713,7 @@ class LUCreateInstance(LogicalUnit): errors.ECODE_STATE) # update the size of disk based on what is found for dsk in self.disks: - dsk["size"] = int(float(node_lvs[dsk["adopt"]][0])) + dsk["size"] = int(float(node_lvs[dsk["vg"] + "/" + dsk["adopt"]][0])) _CheckHVParams(self, nodenames, self.op.hypervisor, self.op.hvparams) diff --git a/lib/objects.py b/lib/objects.py index 597469f37893195c21f4c9e67b10a0c9062b8969..6e7c33f39347bfcc781edd46c0706d40ba4df24f 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -768,8 +768,10 @@ class Instance(TaggableObject): @param lvmap: optional dictionary to receive the 'node' : ['lv', ...] data. - @return: None if lvmap arg is given, otherwise, a dictionary - of the form { 'nodename' : ['volume1', 'volume2', ...], ... } + @return: None if lvmap arg is given, otherwise, a dictionary of + the form { 'nodename' : ['volume1', 'volume2', ...], ... }; + volumeN is of the form "vg_name/lv_name", compatible with + GetVolumeList() """ if node == None: @@ -788,7 +790,7 @@ class Instance(TaggableObject): for dev in devs: if dev.dev_type == constants.LD_LV: - lvmap[node].append(dev.logical_id[1]) + lvmap[node].append(dev.logical_id[0]+"/"+dev.logical_id[1]) elif dev.dev_type in constants.LDS_DRBD: if dev.children: diff --git a/qa/qa_cluster.py b/qa/qa_cluster.py index dc5c79b38c1361a4199b03d10345364efac0763f..575d2d7060b200c844c7392c86a042007931dcab 100644 --- a/qa/qa_cluster.py +++ b/qa/qa_cluster.py @@ -136,9 +136,10 @@ def TestClusterReservedLvs(): (False, ["gnt-cluster", "modify", "--reserved-lvs", ""]), (False, ["lvcreate", "-L1G", "-nqa-test", "xenvg"]), (True, CVERIFY), - (False, ["gnt-cluster", "modify", "--reserved-lvs", "qa-test,other-test"]), + (False, ["gnt-cluster", "modify", "--reserved-lvs", + "xenvg/qa-test,.*/other-test"]), (False, CVERIFY), - (False, ["gnt-cluster", "modify", "--reserved-lvs", "qa-.*"]), + (False, ["gnt-cluster", "modify", "--reserved-lvs", ".*/qa-.*"]), (False, CVERIFY), (False, ["gnt-cluster", "modify", "--reserved-lvs", ""]), (True, CVERIFY),