package org.opendaylight.ovsdb.neutron;
+import java.math.BigInteger;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentHashMap;
-
public class NodeConfiguration {
static final Logger logger = LoggerFactory.getLogger(NodeConfiguration.class);
private static final int MAX_VLAN = 4096;
return mappedVlan;
}
+ public int reclaimInternalVlan (String networkId) {
+ Integer mappedVlan = tenantVlanMap.get(networkId);
+ if (mappedVlan != null) {
+ tenantVlanMap.remove(mappedVlan);
+ internalVlans.add(mappedVlan);
+ return mappedVlan;
+ }
+ return 0;
+ }
+
public void internalVlanInUse (int vlan) {
internalVlans.remove(vlan);
}
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.NodeConnector;
SouthboundEvent.Action action) {
if (action == SouthboundEvent.Action.DELETE) {
if (Interface.NAME.getName().equalsIgnoreCase(tableName)) {
- Interface intf = (Interface)row;
- NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
+ Interface deletedIntf = (Interface)row;
+ NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(deletedIntf);
if (network != null && !network.getRouterExternal()) {
- List<NeutronPort> ports = network.getPortsOnNetwork();
- if (ports != null) {
- int novaCounter = 0;
- for (NeutronPort port : ports) {
- String portOwner = port.getDeviceOwner();
- if (portOwner.equalsIgnoreCase("compute:nova")) novaCounter++;
- }
- /*
- * Make sure we don't delete the tunnel unless there are no more
- * compute nodes using it
- */
- if (novaCounter<=1) {
- this.deleteTunnels(node, uuid, intf);
+ try {
+ ConcurrentMap<String, Table<?>> interfaces = this.ovsdbConfigService.getRows(node, Interface.NAME.getName());
+ if (interfaces != null) {
+ boolean isLastInstanceOnNode = true;
+ for (String intfUUID : interfaces.keySet()) {
+ if (intfUUID.equals(uuid)) continue;
+ Interface intf = (Interface) interfaces.get(intfUUID);
+ NeutronNetwork neutronNetwork = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
+ if (neutronNetwork != null && neutronNetwork.equals(network)) isLastInstanceOnNode = false;
+ }
+ this.handleInterfaceDelete(node, uuid, deletedIntf, isLastInstanceOnNode);
}
+ } catch (Exception e) {
+ logger.error("Error fetching Interface Rows for node " + node, e);
}
}
}
network.getProviderSegmentationID(), node, intf);
}
}
- private void deleteTunnels (Node node, String uuid, Interface intf) {
+ private void handleInterfaceDelete (Node node, String uuid, Interface intf, boolean isLastInstanceOnNode) {
if (AdminConfigManager.getManager().getTunnelEndPoint(node) == null) {
logger.error("Tunnel end-point configuration missing. Please configure it in Open_vSwitch Table");
return;
}
NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
if (network != null) {
- ProviderNetworkManager.getManager().deleteTunnels(network.getProviderNetworkType(),
- network.getProviderSegmentationID(), node, intf);
+ if (isLastInstanceOnNode) {
+ TenantNetworkManager.getManager().reclaimTennantNetworkInternalVlan(node, uuid, network);
+ }
+ ProviderNetworkManager.getManager().handleInterfaceDelete(network.getProviderNetworkType(),
+ network.getProviderSegmentationID(), node, intf, isLastInstanceOnNode);
}
}
import org.opendaylight.ovsdb.lib.table.Port;
import org.opendaylight.ovsdb.lib.table.internal.Table;
import org.opendaylight.ovsdb.neutron.provider.ProviderNetworkManager;
+import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
return nodeConfigurationCache.get(nodeUuid);
}
+ public void reclaimTennantNetworkInternalVlan(Node node, String portUUID, NeutronNetwork network) {
+ String nodeUuid = getNodeUUID(node);
+ if (nodeUuid == null) {
+ logger.error("Unable to get UUID for Node {}", node);
+ return;
+ }
+
+ NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+ // Cache miss
+ if (nodeConfiguration == null)
+ {
+ logger.error("Configuration data unavailable for Node {} ", node);
+ return;
+ }
+
+ int vlan = nodeConfiguration.reclaimInternalVlan(network.getID());
+ if (vlan <= 0) {
+ logger.error("Unable to get an internalVlan for Network {}", network);
+ return;
+ }
+ logger.debug("Removed Vlan {} on {}", vlan, portUUID);
+ }
+
+ public void networkCreated (String networkId) {
+ IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+ List<Node> nodes = connectionService.getNodes();
+
+ for (Node node : nodes) {
+ this.networkCreated(node, networkId);
+ }
+
+ }
+
private String getNodeUUID(Node node) {
String nodeUuid = new String();
OVSDBConfigService ovsdbConfigService = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
}
@Override
- public Status deleteTunnels(String tunnelType, String tunnelKey, Node srcNode, Interface intf) {
+ public Status handleInterfaceDelete(String tunnelType, String tunnelKey, Node srcNode, Interface intf, boolean isLastInstanceOnNode) {
+ Status status = new Status(StatusCode.SUCCESS);
+
IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
List<Node> nodes = connectionService.getNodes();
nodes.remove(srcNode);
for (Node dstNode : nodes) {
- Status status;
InetAddress src = AdminConfigManager.getManager().getTunnelEndPoint(srcNode);
InetAddress dst = AdminConfigManager.getManager().getTunnelEndPoint(dstNode);
this.removeTunnelRules(tunnelType, tunnelKey, dst, srcNode, intf, true);
- status = deleteTunnelPort(srcNode, tunnelType, src, dst, tunnelKey);
+ if (isLastInstanceOnNode) {
+ status = deleteTunnelPort(srcNode, tunnelType, src, dst, tunnelKey);
+ }
this.removeTunnelRules(tunnelType, tunnelKey, src, dstNode, intf, false);
- if (status.isSuccess()) {
+ if (status.isSuccess() && isLastInstanceOnNode) {
deleteTunnelPort(dstNode, tunnelType, dst, src, tunnelKey);
}
}
- return new Status(StatusCode.SUCCESS);
+ return status;
}
private String getTunnelName(String tunnelType, String key, InetAddress dst) {
String tunnelPortUUID = this.getTunnelPortUuid(node, portName, bridgeUUID);
Status status = ovsdbTable.deleteRow(node, Port.NAME.getName(), tunnelPortUUID);
if (!status.isSuccess()) {
- logger.error("Failed to delete Tunnel port {} in {}", portName, bridgeUUID);
+ logger.error("Failed to delete Tunnel port {} in {} status : {}", portName, bridgeUUID, status);
return status;
}
}
@Override
- public Status deleteTunnels(String tunnelType, String tunnelKey, Node source, Interface intf) {
+ public Status handleInterfaceDelete(String tunnelType, String tunnelKey, Node source, Interface intf,
+ boolean isLastInstanceOnNode) {
// TODO Auto-generated method stub
return null;
}
public abstract boolean hasPerTenantTunneling();
public abstract Status handleInterfaceUpdate(String tunnelType, String tunnelKey);
public abstract Status handleInterfaceUpdate(String tunnelType, String tunnelKey, Node source, Interface intf);
- public abstract Status deleteTunnels(String tunnelType, String tunnelKey, Node source, Interface intf);
+ public abstract Status handleInterfaceDelete(String tunnelType, String tunnelKey, Node source, Interface intf, boolean isLastInstanceOnNode);
/*
* Initialize the Flow rules given the OVSDB node.
* This method provides a set of common functionalities to initialize the Flow rules of an OVSDB node