Merge "BUG3685, BUG3686"
[groupbasedpolicy.git] / neutron-ovsdb / src / main / java / org / opendaylight / groupbasedpolicy / neutron / ovsdb / TerminationPointDataChangeListener.java
old mode 100644 (file)
new mode 100755 (executable)
index 4a6dfa6..a078e2c
@@ -9,19 +9,21 @@
 package org.opendaylight.groupbasedpolicy.neutron.ovsdb;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.getProviderMapping;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.processNodeNotification;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.lookupEndpoint;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointRemoveLocation;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointWithLocation;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.checkOfOverlayConfig;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeConnectorIdString;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeIdString;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.removeTunnelsOfOverlayConfig;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.updateOfOverlayConfig;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronHelper.getEpKeyFromNeutronMapper;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.createTunnelPort;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getManagerNode;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getOvsdbBridgeFromTerminationPoint;
 import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getTopologyNode;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.processNodeNotification;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.getProviderMapping;
 import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
 
 import java.util.ArrayList;
@@ -32,6 +34,7 @@ import java.util.Map.Entry;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -82,8 +85,8 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
 
     private List<AbstractTunnelType> createSupportedTunnelsList() {
         List<AbstractTunnelType> required = new ArrayList<AbstractTunnelType>();
-        // required.add(new VxlanGpeTunnelType());
         required.add(new VxlanTunnelType());
+        required.add(new VxlanGpeTunnelType());
         return Collections.unmodifiableList(required);
     }
 
@@ -124,10 +127,15 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
          * Deletions
          */
         for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
-            if (iid instanceof OvsdbTerminationPointAugmentation) {
-                /*
-                 * Remove the state from OfOverlay?
-                 */
+            DataObject old = change.getOriginalData().get(iid);
+            if (old instanceof OvsdbTerminationPointAugmentation) {
+                OvsdbTerminationPointAugmentation ovsdbTp = (OvsdbTerminationPointAugmentation) old;
+                @SuppressWarnings("unchecked")
+                InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid = (InstanceIdentifier<OvsdbTerminationPointAugmentation>) iid;
+                OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker);
+                if (ovsdbBridge != null) {
+                    processRemovedTp(ovsdbBridge, ovsdbTp, ovsdbTpIid);
+                }
             }
         }
     }
@@ -205,13 +213,13 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
 
         /*
          * Check if Neutron External port was announed in Node before TerminationPoint it refers to
-         * was actually instantiated. This may or may not have external information in the future, hence
+         * was actually instantiated. This may or may not have external information in the future,
+         * hence
          * not process as IF/ELSE externalID.
          */
         ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
         Optional<Node> node = readFromDs(LogicalDatastoreType.OPERATIONAL, nodeIid, transaction);
-        if (node.isPresent()
-                && node.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
+        if (node.isPresent() && node.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
             OvsdbNodeAugmentation ovsdbNodeAug = node.get().getAugmentation(OvsdbNodeAugmentation.class);
             if (getProviderMapping(ovsdbNodeAug) != null) {
                 processNodeNotification(ovsdbNodeAug);
@@ -224,11 +232,73 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
          * In that case, we need to update the Inventory Node's OfOverlay
          * augmentation with missing information
          */
+        AbstractTunnelType tunnel = getTunnelType(ovsdbTp, requiredTunnelTypes);
+        if (tunnel != null) {
+            updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, tunnel, dataBroker);
+        }
+        if (externalId != null) {
+            ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
+            updateEndpointWithLocation(ep, nodeIdString, nodeConnectorIdString, rwTx);
+        }
+    }
+
+    /**
+     * If removed termination point was a tunnel port,
+     * removes attached tunnels (namely Vxlan-type) from OVSDB bridge;
+     * else removes location info from TP
+     *
+     * @param ovsdbBridge {@link OvsdbBridgeAugmentation}
+     * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+     * @param ovsdbTpIid termination point's IID {@link InstanceIdentifier}
+     */
+    private void processRemovedTp(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp,
+            InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid) {
+
+        checkNotNull(ovsdbBridge);
+        if (ovsdbBridge.getBridgeName().getValue().equals(ovsdbTp.getName())) {
+            LOG.debug("Termination Point {} same as Bridge {}. Not processing.", ovsdbTp.getName(),
+                    ovsdbBridge.getBridgeName().getValue());
+            return;
+        }
+
+        String nodeIdString = getInventoryNodeIdString(ovsdbBridge, ovsdbTpIid, dataBroker);
+        if (nodeIdString == null) {
+            LOG.debug("nodeIdString for TerminationPoint {} was null.", ovsdbTp);
+            return;
+        }
+
         if (isTunnelPort(ovsdbTp, requiredTunnelTypes)) {
-            updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, requiredTunnelTypes, dataBroker);
+            removeTunnelsOfOverlayConfig(nodeIdString, requiredTunnelTypes, dataBroker);
+        } else {
+            deleteLocationForTp(ovsdbTp);
         }
+    }
+
+    /**
+     * Delete location on EP for given TP
+     *
+     * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+     */
+    private void deleteLocationForTp(OvsdbTerminationPointAugmentation ovsdbTp) {
+        String externalId = getNeutronPortUuid(ovsdbTp);
         if (externalId != null) {
-            updateEndpointWithLocation(ep, nodeIdString, nodeConnectorIdString, ovsdbTp.getName(), epService);
+            EndpointKey epKey = getEpKeyFromNeutronMapper(new Uuid(externalId), dataBroker);
+            if (epKey == null) {
+                LOG.debug("TerminationPoint {} with external ID {} is not in Neutron Map.", ovsdbTp, externalId);
+                return;
+            }
+            ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
+            Endpoint ep = lookupEndpoint(epKey, readOnlyTransaction);
+            readOnlyTransaction.close();
+            if (ep == null) {
+                LOG.warn(
+                        "TerminationPoint {} with external ID {} is in Neutron Map, but corresponding Endpoint {} isn't in Endpoint Repository.",
+                        ovsdbTp, externalId, epKey);
+                return;
+            }
+            updateEndpointRemoveLocation(ep, dataBroker.newReadWriteTransaction());
+        } else {
+            LOG.debug("TerminationPoint {} has no external ID, not processing.", ovsdbTp);
         }
     }
 
@@ -236,8 +306,29 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
      * Check to see if the {@link OvsdbTerminationPointAugmentation} is also a Tunnel port that we
      * care about.
      *
-     * @param ovsdbTp
-     * @param requiredTunnelTypes
+     * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+     * @param requiredTunnelTypes {@link List} of tunnel types
+     */
+    private static AbstractTunnelType getTunnelType(OvsdbTerminationPointAugmentation ovsdbTp,
+            List<AbstractTunnelType> requiredTunnelTypes) {
+        if (ovsdbTp.getInterfaceType() != null) {
+            for (AbstractTunnelType tunnelType : requiredTunnelTypes) {
+                if (tunnelType.isValidTunnelPort(ovsdbTp)) {
+                    return tunnelType;
+                }
+            }
+        }
+        return null;
+    }
+
+    /*
+     * Check to see if the {@link OvsdbTerminationPointAugmentation}
+     * is also a Tunnel port that we care about.
+     *
+     * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+     *
+     * @param requiredTunnelTypes {@link List} of tunnel types
+     *
      * @return true if it's a required tunnel port, false if it isn't
      */
     private boolean isTunnelPort(OvsdbTerminationPointAugmentation ovsdbTp, List<AbstractTunnelType> requiredTunnelTypes) {
@@ -277,8 +368,8 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
      * Check to see if all tunnel ports are present, and if not,
      * create them.
      *
-     * @param tpIid
-     * @return
+     * @param nodeIid {@link InstanceIdentifier}
+     * @param dataBroker {@link DataBroker}
      */
     private void createTunnelPorts(InstanceIdentifier<Node> nodeIid, DataBroker dataBroker) {
 
@@ -306,7 +397,7 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
                     break;
                 }
             }
-            if (tunnelPresent == false) {
+            if (!tunnelPresent) {
                 createTunnelPort(nodeIid, node, tunnelType, dataBroker);
             }
         }