X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/0f7098f3dd15dd2f5e4b09c9bc851e10aeddb07f..a2e885ee62cdbf304cc93a0837bd78f8acebd472:/lib/cmdlib.py diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 18395a4..08b6bf0 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -5797,7 +5797,9 @@ class LUInstanceRename(LogicalUnit): rename_file_storage = True self.cfg.RenameInstance(inst.name, self.op.new_name) - # Change the instance lock. This is definitely safe while we hold the BGL + # Change the instance lock. This is definitely safe while we hold the BGL. + # Otherwise the new lock would have to be added in acquired mode. + assert self.REQ_BGL self.context.glm.remove(locking.LEVEL_INSTANCE, old_name) self.context.glm.add(locking.LEVEL_INSTANCE, self.op.new_name) @@ -11170,8 +11172,8 @@ class TagsLU(NoHooksLU): # pylint: disable-msg=W0223 This is an abstract class which is the parent of all the other tags LUs. """ - def ExpandNames(self): + self.group_uuid = None self.needed_locks = {} if self.op.kind == constants.TAG_NODE: self.op.name = _ExpandNodeName(self.cfg, self.op.name) @@ -11179,6 +11181,8 @@ class TagsLU(NoHooksLU): # pylint: disable-msg=W0223 elif self.op.kind == constants.TAG_INSTANCE: self.op.name = _ExpandInstanceName(self.cfg, self.op.name) self.needed_locks[locking.LEVEL_INSTANCE] = self.op.name + elif self.op.kind == constants.TAG_NODEGROUP: + self.group_uuid = self.cfg.LookupNodeGroup(self.op.name) # FIXME: Acquire BGL for cluster tag operations (as of this writing it's # not possible to acquire the BGL based on opcode parameters) @@ -11193,6 +11197,8 @@ class TagsLU(NoHooksLU): # pylint: disable-msg=W0223 self.target = self.cfg.GetNodeInfo(self.op.name) elif self.op.kind == constants.TAG_INSTANCE: self.target = self.cfg.GetInstanceInfo(self.op.name) + elif self.op.kind == constants.TAG_NODEGROUP: + self.target = self.cfg.GetNodeGroup(self.group_uuid) else: raise errors.OpPrereqError("Wrong tag type requested (%s)" % str(self.op.kind), errors.ECODE_INVAL) @@ -11248,6 +11254,8 @@ class LUTagsSearch(NoHooksLU): tgts.extend([("/instances/%s" % i.name, i) for i in ilist]) nlist = cfg.GetAllNodesInfo().values() tgts.extend([("/nodes/%s" % n.name, n) for n in nlist]) + tgts.extend(("/nodegroup/%s" % n.name, n) + for n in cfg.GetAllNodeGroupsInfo().values()) results = [] for path, target in tgts: for tag in target.GetTags(): @@ -11885,8 +11893,61 @@ class IAllocator(object): if not isinstance(rdict["result"], list): raise errors.OpExecError("Can't parse iallocator results: 'result' key" " is not a list") + + if self.mode == constants.IALLOCATOR_MODE_RELOC: + assert self.relocate_from is not None + assert self.required_nodes == 1 + + node2group = dict((name, ndata["group"]) + for (name, ndata) in self.in_data["nodes"].items()) + + fn = compat.partial(self._NodesToGroups, node2group, + self.in_data["nodegroups"]) + + request_groups = fn(self.relocate_from) + result_groups = fn(rdict["result"]) + + if result_groups != request_groups: + raise errors.OpExecError("Groups of nodes returned by iallocator (%s)" + " differ from original groups (%s)" % + (utils.CommaJoin(result_groups), + utils.CommaJoin(request_groups))) + self.out_data = rdict + @staticmethod + def _NodesToGroups(node2group, groups, nodes): + """Returns a list of unique group names for a list of nodes. + + @type node2group: dict + @param node2group: Map from node name to group UUID + @type groups: dict + @param groups: Group information + @type nodes: list + @param nodes: Node names + + """ + result = set() + + for node in nodes: + try: + group_uuid = node2group[node] + except KeyError: + # Ignore unknown node + pass + else: + try: + group = groups[group_uuid] + except KeyError: + # Can't find group, let's use UUID + group_name = group_uuid + else: + group_name = group["name"] + + result.add(group_name) + + return sorted(result) + class LUTestAllocator(NoHooksLU): """Run allocator tests.