apply checkstyle check during build for neutron-ovsdb
[groupbasedpolicy.git] / neutron-ovsdb / src / main / java / org / opendaylight / groupbasedpolicy / neutron / ovsdb / TerminationPointDataChangeListener.java
old mode 100644 (file)
new mode 100755 (executable)
index fb6951c..a86073f
@@ -10,38 +10,41 @@ package org.opendaylight.groupbasedpolicy.neutron.ovsdb;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 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;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Map.Entry;
+import java.util.Map;
 
 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.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 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;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Uuid;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
@@ -52,17 +55,15 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-
-public class TerminationPointDataChangeListener implements DataChangeListener, AutoCloseable {
+public class TerminationPointDataChangeListener implements DataTreeChangeListener<OvsdbTerminationPointAugmentation>,
+        AutoCloseable {
 
     private static final String NEUTRON_EXTERNAL_ID_KEY = "iface-id";
-    private final ListenerRegistration<DataChangeListener> registration;
+    private final ListenerRegistration<?> registration;
     private final DataBroker dataBroker;
     private final EndpointService epService;
     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointDataChangeListener.class);
@@ -76,15 +77,15 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
             .child(Node.class)
             .child(TerminationPoint.class)
             .augmentation(OvsdbTerminationPointAugmentation.class);
-        registration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid, this,
-                DataChangeScope.ONE);
+        registration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(
+                LogicalDatastoreType.OPERATIONAL, iid), this);
         requiredTunnelTypes = createSupportedTunnelsList();
     }
 
     private List<AbstractTunnelType> createSupportedTunnelsList() {
-        List<AbstractTunnelType> required = new ArrayList<AbstractTunnelType>();
-        // required.add(new VxlanGpeTunnelType());
+        List<AbstractTunnelType> required = new ArrayList<>();
         required.add(new VxlanTunnelType());
+        required.add(new VxlanGpeTunnelType());
         return Collections.unmodifiableList(required);
     }
 
@@ -93,42 +94,36 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
         registration.close();
     }
 
-    @Override
-    public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-
-        /*
-         * TerminationPoint notifications with OVSDB augmentations
-         * vSwitch ports. Iterate through the list of new ports.
-         */
-        for (Entry<InstanceIdentifier<?>, DataObject> entry : change.getCreatedData().entrySet()) {
-            if (entry.getValue() instanceof OvsdbTerminationPointAugmentation) {
-                OvsdbTerminationPointAugmentation ovsdbTp = (OvsdbTerminationPointAugmentation) entry.getValue();
-                InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid = (InstanceIdentifier<OvsdbTerminationPointAugmentation>) entry.getKey();
-                OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker);
-                processOvsdbBridge(ovsdbBridge, ovsdbTp, ovsdbTpIid);
-            }
-        }
-
-        /*
-         * Updates
-         */
-        for (Entry<InstanceIdentifier<?>, DataObject> entry : change.getUpdatedData().entrySet()) {
-            if (entry.getValue() instanceof OvsdbTerminationPointAugmentation) {
-                OvsdbTerminationPointAugmentation ovsdbTp = (OvsdbTerminationPointAugmentation) entry.getValue();
-                InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid = (InstanceIdentifier<OvsdbTerminationPointAugmentation>) entry.getKey();
-                OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker);
-                processOvsdbBridge(ovsdbBridge, ovsdbTp, ovsdbTpIid);
-            }
-        }
+    /*
+     * When vSwitch is deleted, we loose data in operational DS to determine Iid of
+     * corresponding NodeId.
+     */
+    private static final Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, NodeId> NODE_ID_BY_TERMIN_POINT =
+            new HashMap<>();
 
-        /*
-         * Deletions
-         */
-        for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
-            if (iid instanceof OvsdbTerminationPointAugmentation) {
-                /*
-                 * Remove the state from OfOverlay?
-                 */
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<OvsdbTerminationPointAugmentation>> changes) {
+        for (DataTreeModification<OvsdbTerminationPointAugmentation> change: changes) {
+            DataObjectModification<OvsdbTerminationPointAugmentation> rootNode = change.getRootNode();
+            InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid = change.getRootPath().getRootIdentifier();
+            OvsdbTerminationPointAugmentation origOvsdbTp = rootNode.getDataBefore();
+            switch (rootNode.getModificationType()) {
+                case SUBTREE_MODIFIED:
+                case WRITE:
+                    OvsdbTerminationPointAugmentation updatedOvsdbTp = rootNode.getDataAfter();
+                    OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker);
+                    if (origOvsdbTp == null) {
+                        NODE_ID_BY_TERMIN_POINT.put(ovsdbTpIid,
+                                new NodeId(getInventoryNodeIdString(ovsdbBridge, ovsdbTpIid, dataBroker)));
+                    }
+
+                    processOvsdbBridge(ovsdbBridge, updatedOvsdbTp, ovsdbTpIid);
+                    break;
+                case DELETE:
+                    processRemovedTp(NODE_ID_BY_TERMIN_POINT.get(ovsdbTpIid), origOvsdbTp, ovsdbTpIid);
+                    break;
+                default:
+                    break;
             }
         }
     }
@@ -171,7 +166,7 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
          */
 
         if (externalId != null) {
-            EndpointKey epKey = getEpKeyFromNeutronMapper(new Uuid(externalId), dataBroker);
+            EndpointKey epKey = getEpKeyFromNeutronMapper(new UniqueId(externalId), dataBroker);
             if (epKey == null) {
                 LOG.debug("TerminationPoint {} with external ID {} is not in Neutron Map", ovsdbTp, externalId);
                 return;
@@ -179,9 +174,8 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
             ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
             ep = lookupEndpoint(epKey, transaction);
             if (ep == null) {
-                LOG.warn(
-                        "TerminationPoint {} with external ID {} is in Neutron Map, but corresponding Endpoint {} isn't in Endpoint Repository",
-                        ovsdbTp, externalId, epKey);
+                LOG.warn("TerminationPoint {} with external ID {} is in Neutron Map, "
+                    + "but corresponding Endpoint {} isn't in Endpoint Repository", ovsdbTp, externalId, epKey);
                 return;
             }
             /*
@@ -191,7 +185,7 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
              * OfOverlay augmentation. If it hasn't, go see if the
              * tunnel ports exist, and if not, go and create them.
              */
-            if (checkOfOverlayConfig(nodeIdString, requiredTunnelTypes, dataBroker) != true) {
+            if (!checkOfOverlayConfig(nodeIdString, requiredTunnelTypes, dataBroker)) {
                 checkNotNull(nodeIid);
                 /*
                  * Check to see if we need to create a
@@ -204,29 +198,14 @@ 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
-         * 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) {
-            OvsdbNodeAugmentation ovsdbNodeAug = node.get().getAugmentation(OvsdbNodeAugmentation.class);
-            if (getProviderMapping(ovsdbNodeAug) != null) {
-                processNodeNotification(ovsdbNodeAug);
-
-            }
-        } else {
-        }
         /*
          * This may be a notification for a tunnel we just created.
          * In that case, we need to update the Inventory Node's OfOverlay
          * augmentation with missing information
          */
-        if (isTunnelPort(ovsdbTp, requiredTunnelTypes)) {
-            updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, requiredTunnelTypes, dataBroker);
+        AbstractTunnelType tunnel = getTunnelType(ovsdbTp, requiredTunnelTypes);
+        if (tunnel != null) {
+            updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, tunnel, dataBroker);
         }
         if (externalId != null) {
             ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
@@ -234,15 +213,82 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
         }
     }
 
+    /**
+     * If removed termination point was a tunnel port,
+     * removes attached tunnels (namely Vxlan-type) from OVSDB bridge,
+     * else removes location info from TP.
+     *
+     * @param nodeId {@link NodeId}
+     * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+     * @param ovsdbTpIid termination point's IID {@link InstanceIdentifier}
+     */
+    private void processRemovedTp(NodeId nodeId, OvsdbTerminationPointAugmentation ovsdbTp,
+            InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid) {
+        if (isTunnelPort(ovsdbTp, requiredTunnelTypes)) {
+            removeTunnelsOfOverlayConfig(nodeId.getValue(), 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) {
+            EndpointKey epKey = getEpKeyFromNeutronMapper(new UniqueId(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);
+        }
+    }
+
     /**
      * 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) {
+    private boolean isTunnelPort(OvsdbTerminationPointAugmentation ovsdbTp,
+            List<AbstractTunnelType> requiredTunnelTypes) {
         if (ovsdbTp.getInterfaceType() != null) {
             for (AbstractTunnelType tunnelType : requiredTunnelTypes) {
                 if (tunnelType.isValidTunnelPort(ovsdbTp)) {
@@ -257,7 +303,7 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
      * Get the Neutron Port UUID from an {@link OvsdbTerminationPointAugmentation}.
      * The Neutron Port UUID is stored as an "external-id" in the termination point.
      *
-     * @param ovsdbTp The OVSDB Termination Point augmentation
+     * @param ovsdbTp The {@link OvsdbTerminationPointAugmentation}
      * @return The String representation of the Neutron Port UUID, null if not present
      */
     private String getNeutronPortUuid(OvsdbTerminationPointAugmentation ovsdbTp) {
@@ -279,8 +325,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) {
 
@@ -308,7 +354,7 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
                     break;
                 }
             }
-            if (tunnelPresent == false) {
+            if (!tunnelPresent) {
                 createTunnelPort(nodeIid, node, tunnelType, dataBroker);
             }
         }
@@ -327,8 +373,9 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
          */
         OvsdbNodeAugmentation managerNode = getManagerNode(ovsdbBridge, dataBroker);
 
-        if (managerNode == null)
+        if (managerNode == null) {
             return null;
+        }
 
         if (managerNode.getConnectionInfo() != null) {
             return managerNode.getConnectionInfo().getRemoteIp();