From 0fbd466b7fec6efb505868e5ca65f1e3f9b53497 Mon Sep 17 00:00:00 2001 From: Dimitris Aragiorgis <dimara@grnet.gr> Date: Mon, 4 Jun 2012 21:08:36 +0300 Subject: [PATCH] Implement network/nodegroup mappings LUNetworkConnect() connects a network to a nodegroup and defines its netparams (mode and link). Specifically: * Check if network already exists * Check if netparams are valid * Check if already connected to the same nodegroup * Produce errors if any conflicting IPs found * Update the 'networks' slot in NodeGroup config object with the network UUID and netparams requested. E.g. nodegroup_uuid { networks { network_uuid: {mode: 'bridged', link: 'br100'} } } LUNetworkDisconnect() unmaps a network from a nodegroup: * Produce errors if an instance has a NIC with IP inside the network * Remove corresponding entry in 'networks' slot of NodeGroup object Check for conflicting ips can be avoided with corresponding option. Signed-off-by: Dimitris Aragiorgis <dimara@grnet.gr> Reviewed-by: Iustin Pop <iustin@google.com> --- lib/cmdlib.py | 174 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 168 insertions(+), 6 deletions(-) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index d95d36f00..3e7e6bda9 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -15741,19 +15741,181 @@ class LUNetworkQuery(NoHooksLU): class LUNetworkConnect(LogicalUnit): - def BuildHooksNodes(self): - pass + """Connect a network to a nodegroup + + """ + HPATH = "network-connect" + HTYPE = constants.HTYPE_NETWORK + REQ_BGL = False + + def ExpandNames(self): + self.network_name = self.op.network_name + self.group_name = self.op.group_name + self.network_mode = self.op.network_mode + self.network_link = self.op.network_link + + self.network_uuid = self.cfg.LookupNetwork(self.network_name) + self.network = self.cfg.GetNetwork(self.network_uuid) + self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) + self.group = self.cfg.GetNodeGroup(self.group_uuid) + + self.needed_locks = { + locking.LEVEL_INSTANCE: [], + locking.LEVEL_NODEGROUP: [self.group_uuid], + } + self.share_locks[locking.LEVEL_INSTANCE] = 1 + + def DeclareLocks(self, level): + if level == locking.LEVEL_INSTANCE: + assert not self.needed_locks[locking.LEVEL_INSTANCE] + + # Lock instances optimistically, needs verification once group lock has + # been acquired + self.needed_locks[locking.LEVEL_INSTANCE] = \ + self.cfg.GetNodeGroupInstances(self.group_uuid) def BuildHooksEnv(self): - pass + ret = dict() + ret["GROUP_NAME"] = self.group_name + ret["GROUP_NETWORK_NAME"] = self.network_name + ret["GROUP_NETWORK_MODE"] = self.network_mode + ret["GROUP_NETWORK_LINK"] = self.network_link + return ret + + def BuildHooksNodes(self): + nodes = self.cfg.GetNodeGroup(self.group_uuid).members + return (nodes, nodes) + + + def CheckPrereq(self): + l = lambda value: ", ".join("%s: %s/%s" % (i[0], i[1], i[2]) + for i in value) + + if self.network is None: + raise errors.OpPrereqError("Network %s does not exist" % + self.network_name, errors.ECODE_INVAL) + + self.netparams = dict() + self.netparams[constants.NIC_MODE] = self.network_mode + self.netparams[constants.NIC_LINK] = self.network_link + objects.NIC.CheckParameterSyntax(self.netparams) + + #if self.network_mode == constants.NIC_MODE_BRIDGED: + # _CheckNodeGroupBridgesExist(self, self.network_link, self.group_uuid) + self.connected = False + if self.network_uuid in self.group.networks: + self.LogWarning("Network '%s' is already mapped to group '%s'" % + (self.network_name, self.group.name)) + self.connected = True + return + + pool = network.AddressPool(self.network) + if self.op.conflicts_check: + groupinstances = [] + for n in self.cfg.GetNodeGroupInstances(self.group_uuid): + groupinstances.append(self.cfg.GetInstanceInfo(n)) + instances = [(instance.name, idx, nic.ip) + for instance in groupinstances + for idx, nic in enumerate(instance.nics) + if (not nic.network and pool._Contains(nic.ip))] + if instances: + self.LogWarning("Following occurences use IPs from network %s" + " that is about to connect to nodegroup %s: %s" % + (self.network_name, self.group.name, + l(instances))) + raise errors.OpPrereqError("Conflicting IPs found." + " Please remove/modify" + " corresponding NICs", + errors.ECODE_INVAL) + + def Exec(self, feedback_fn): + if self.connected: + return + + self.group.networks[self.network_uuid] = self.netparams + self.cfg.Update(self.group, feedback_fn) class LUNetworkDisconnect(LogicalUnit): - def BuildHooksNodes(self): - pass + """Disconnect a network to a nodegroup + + """ + HPATH = "network-disconnect" + HTYPE = constants.HTYPE_NETWORK + REQ_BGL = False + + def ExpandNames(self): + self.network_name = self.op.network_name + self.group_name = self.op.group_name + + self.network_uuid = self.cfg.LookupNetwork(self.network_name) + self.network = self.cfg.GetNetwork(self.network_uuid) + self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) + self.group = self.cfg.GetNodeGroup(self.group_uuid) + + self.needed_locks = { + locking.LEVEL_INSTANCE: [], + locking.LEVEL_NODEGROUP: [self.group_uuid], + } + self.share_locks[locking.LEVEL_INSTANCE] = 1 + + def DeclareLocks(self, level): + if level == locking.LEVEL_INSTANCE: + assert not self.needed_locks[locking.LEVEL_INSTANCE] + + # Lock instances optimistically, needs verification once group lock has + # been acquired + self.needed_locks[locking.LEVEL_INSTANCE] = \ + self.cfg.GetNodeGroupInstances(self.group_uuid) def BuildHooksEnv(self): - pass + ret = dict() + ret["GROUP_NAME"] = self.group_name + ret["GROUP_NETWORK_NAME"] = self.network_name + return ret + + def BuildHooksNodes(self): + nodes = self.cfg.GetNodeGroup(self.group_uuid).members + return (nodes, nodes) + + + def CheckPrereq(self): + l = lambda value: ", ".join("%s: %s/%s" % (i[0], i[1], i[2]) + for i in value) + + self.connected = True + if self.network_uuid not in self.group.networks: + self.LogWarning("Network '%s' is" + " not mapped to group '%s'" % + (self.network_name, self.group.name)) + self.connected = False + return + + if self.op.conflicts_check: + groupinstances = [] + for n in self.cfg.GetNodeGroupInstances(self.group_uuid): + groupinstances.append(self.cfg.GetInstanceInfo(n)) + instances = [(instance.name, idx, nic.ip) + for instance in groupinstances + for idx, nic in enumerate(instance.nics) + if nic.network == self.network_name] + if instances: + self.LogWarning("Following occurences use IPs from network %s" + " that is about to disconnected from the nodegroup" + " %s: %s" % + (self.network_name, self.group.name, + l(instances))) + raise errors.OpPrereqError("Conflicting IPs." + " Please remove/modify" + " corresponding NICS", + errors.ECODE_INVAL) + + def Exec(self, feedback_fn): + if not self.connected: + return + + del self.group.networks[self.network_uuid] + self.cfg.Update(self.group, feedback_fn) #: Query type implementations -- GitLab