Provide FlowCapableNodeDataChangeListener to openstack.netvirt via NodeCacheManager 82/16482/3
authorFlavio Fernandes <ffernand@redhat.com>
Fri, 13 Mar 2015 10:56:50 +0000 (06:56 -0400)
committerFlavio Fernandes <ffernand@redhat.com>
Fri, 13 Mar 2015 17:39:01 +0000 (17:39 +0000)
With this change, netvirt will have a thread safe cache of all flowCapable nodes.
This is needed for the lbaas handler, so it can efficiently find the nodes it needs
to configure, w/out using ad-sal switch manager.

Patch 2:
- add missing Copyright headers
- add code review comments

Note: NodeUtils has been duplicated and needs to be moved to .utils pkg
This will be taken care in gerrit: https://git.opendaylight.org/gerrit/#/c/16487/

Change-Id: Id3e98e8e4fb735c4a1cba8e325dd7a1c44a6d192
Signed-off-by: Flavio Fernandes <ffernand@redhat.com>
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/FlowCapableNodeDataChangeListener.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/NodeUtils.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/AbstractEvent.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/Activator.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/NodeCacheManagerEvent.java [new file with mode: 0644]
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/NodeCacheManager.java [new file with mode: 0644]
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NodeCacheManagerImpl.java [new file with mode: 0644]
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NodeUtils.java [new file with mode: 0644]

index ae9f06bf0e9810437f11793dcc88421b7f8005ec..93aa0a35944375581ac3b632dfbafe7e9545421a 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 //import org.opendaylight.ovsdb.openstack.netvirt.NodeUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -35,6 +36,8 @@ public class FlowCapableNodeDataChangeListener implements DataChangeListener, Au
     private static final Logger LOG = LoggerFactory.getLogger(FlowCapableNodeDataChangeListener.class);
     private ListenerRegistration<DataChangeListener> registration;
     private List<Node> nodeCache = Lists.newArrayList();
+    private PipelineOrchestrator pipelineOrchestrator = null;
+    private NodeCacheManager nodeCacheManager = null;
 
     public static final InstanceIdentifier<FlowCapableNode> createFlowCapableNodePath () {
         return InstanceIdentifier.builder(Nodes.class)
@@ -59,6 +62,15 @@ public class FlowCapableNodeDataChangeListener implements DataChangeListener, Au
             DataObject> changes) {
 
         LOG.debug("onDataChanged: {}", changes);
+
+        if (pipelineOrchestrator == null) {
+            pipelineOrchestrator =
+                    (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
+        }
+        if (nodeCacheManager == null) {
+            nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
+        }
+
         for( Map.Entry<InstanceIdentifier<?>, DataObject> created : changes.getCreatedData().entrySet()) {
             InstanceIdentifier<?> iID = created.getKey();
             String openflowId = iID.firstKeyOf(Node.class, NodeKey.class).getId().getValue();
@@ -67,18 +79,19 @@ public class FlowCapableNodeDataChangeListener implements DataChangeListener, Au
                     iID.firstIdentifierOf(Node.class),
                     openflowId);
 
-            PipelineOrchestrator pipelineOrchestrator =
-                    (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
-            pipelineOrchestrator.enqueue(openflowId);
+            if (pipelineOrchestrator != null) {
+                pipelineOrchestrator.enqueue(openflowId);
+            }
 
             notifyNodeUpdated(NodeUtils.getOpenFlowNode(openflowId));
         }
 
-        //TODO: how to get the removed node id
-        Map<InstanceIdentifier<?>, DataObject> originalDataObject = changes.getOriginalData();
-        Set<InstanceIdentifier<?>> iID = changes.getRemovedPaths();
-        for (InstanceIdentifier instanceIdentifier : iID) {
-            notifyNodeUpdated(NodeUtils.getOpenFlowNode(null));
+        for (InstanceIdentifier instanceIdentifier : changes.getRemovedPaths()) {
+            DataObject originalDataObject = changes.getOriginalData().get(instanceIdentifier);
+            if (originalDataObject != null && originalDataObject instanceof Node){
+                Node node = (Node) originalDataObject;
+                notifyNodeRemoved(NodeUtils.getOpenFlowNode(node.getId().getValue()));
+            }
         }
     }
 
@@ -93,6 +106,10 @@ public class FlowCapableNodeDataChangeListener implements DataChangeListener, Au
                     (NetworkingProviderManager) ServiceHelper.getGlobalInstance(NetworkingProviderManager.class,
                             this);
             networkingProviderManager.getProvider(openFlowNode).initializeOFFlowRules(openFlowNode);
+
+            if (nodeCacheManager != null) {
+                nodeCacheManager.nodeAdded(openFlowNode.getId().getValue());
+            }
         }
     }
 
@@ -100,6 +117,10 @@ public class FlowCapableNodeDataChangeListener implements DataChangeListener, Au
         LOG.debug("notifyNodeRemoved: Node {} update from Controller's inventory Service",
                 openFlowNode.getId().getValue());
 
-        nodeCache.remove(null);//openFlowNode);
+        nodeCache.remove(openFlowNode);
+
+        if (nodeCacheManager != null) {
+            nodeCacheManager.nodeRemoved(openFlowNode.getId().getValue());
+        }
     }
 }
index e0f7ba12d3aa15ae2c76f6b61a7a95871fd5174e..06444f76733d5a371f4a6becc5188dbdef105b04 100644 (file)
@@ -19,6 +19,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+// TODO: Move this to org.opendaylight.ovsdb.utils
+
 public class NodeUtils {
     protected static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class);
 
index 31320efe985e24cfbd22f5ce7b5c883bbd7042c4..83ed897550af860ad2dd623a08b65aa169db0e55 100644 (file)
@@ -27,7 +27,8 @@ public abstract class AbstractEvent {
         NEUTRON_FWAAS,
         NEUTRON_LOAD_BALANCER,
         NEUTRON_LOAD_BALANCER_POOL,
-        NEUTRON_LOAD_BALANCER_POOL_MEMBER;
+        NEUTRON_LOAD_BALANCER_POOL_MEMBER,
+        NODE;
 
         public static final int size = HandlerType.values().length;
     }
index d8b97e76a12788354ea8b985739c7b134fdaf72e..2a2c228745f69017476f3b3ebf8f71d18130c314 100644 (file)
@@ -46,6 +46,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.MultiTenantAwareRouter;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
@@ -55,6 +56,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.impl.BridgeConfigurationManagerI
 import org.opendaylight.ovsdb.openstack.netvirt.impl.ConfigurationServiceImpl;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.EventDispatcherImpl;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter;
+import org.opendaylight.ovsdb.openstack.netvirt.impl.NodeCacheManagerImpl;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.OpenstackRouter;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.ProviderNetworkManagerImpl;
 import org.opendaylight.ovsdb.openstack.netvirt.impl.SecurityServicesImpl;
@@ -298,6 +300,14 @@ public class Activator extends DependencyActivatorBase {
         manager.add(createComponent()
                 .setInterface(MultiTenantAwareRouter.class.getName(), null)
                 .setImplementation(OpenstackRouter.class));
+
+        Dictionary<String, Object> nodeCacheManagerProperties = new Hashtable<>();
+        nodeCacheManagerProperties.put(Constants.EVENT_HANDLER_TYPE_PROPERTY, AbstractEvent.HandlerType.NODE);
+        manager.add(createComponent()
+                .setInterface(new String[]{NodeCacheManager.class.getName(), AbstractHandler.class.getName()},
+                        nodeCacheManagerProperties)
+                .setImplementation(NodeCacheManagerImpl.class)
+                .add(createServiceDependency().setService(EventDispatcher.class).setRequired(true)));
     }
 
     @Override
diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/NodeCacheManagerEvent.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/NodeCacheManagerEvent.java
new file mode 100644 (file)
index 0000000..e471be2
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Authors : Flavio Fernandes
+ */
+package org.opendaylight.ovsdb.openstack.netvirt;
+
+import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+
+public class NodeCacheManagerEvent extends AbstractEvent {
+
+    private String nodeIdentifier;
+
+    public NodeCacheManagerEvent(String nodeIdentifier, Action action) {
+        super(HandlerType.NODE, action);
+        this.nodeIdentifier = nodeIdentifier;
+    }
+
+    public String getNodeIdentifier() {
+        return nodeIdentifier;
+    }
+
+    @Override
+    public String toString() {
+        return "NodeCacheManagerEvent [action=" + super.getAction()
+               + ", nodeIdentifier=" + nodeIdentifier
+               + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + ((nodeIdentifier == null) ? 0 : nodeIdentifier.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        NodeCacheManagerEvent other = (NodeCacheManagerEvent) obj;
+        if (nodeIdentifier == null) {
+            if (other.nodeIdentifier != null) {
+                return false;
+            }
+        } else if (!nodeIdentifier.equals(other.nodeIdentifier)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/NodeCacheManager.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/NodeCacheManager.java
new file mode 100644 (file)
index 0000000..52f2fd9
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Authors : Flavio Fernandes
+ */
+package org.opendaylight.ovsdb.openstack.netvirt.api;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+
+import java.util.List;
+
+/**
+ * This interface is used to cache ids of nodes that are needed by net-virt.
+ * The nodes are added and removed by an external listener.
+ */
+public interface NodeCacheManager {
+    public void nodeAdded(String nodeIdentifier);
+    public void nodeRemoved(String nodeIdentifier);
+
+    public List<Node> getNodes();
+}
diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NodeCacheManagerImpl.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NodeCacheManagerImpl.java
new file mode 100644 (file)
index 0000000..5ff6214
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Authors : Flavio Fernandes
+ */
+package org.opendaylight.ovsdb.openstack.netvirt.impl;
+
+import com.google.common.collect.Lists;
+import org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent;
+import org.opendaylight.ovsdb.openstack.netvirt.AbstractHandler;
+import org.opendaylight.ovsdb.openstack.netvirt.NodeCacheManagerEvent;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class NodeCacheManagerImpl extends AbstractHandler
+        implements NodeCacheManager {
+
+    private static final Logger logger = LoggerFactory.getLogger(NodeCacheManagerImpl.class);
+    private List<Node> nodeCache = Lists.newArrayList();
+
+
+    @Override
+    public void nodeAdded(String nodeIdentifier) {
+        logger.info("XXX >>>>> enqueue: Node added : {}", nodeIdentifier);
+        logger.debug(">>>>> enqueue: Node added : {}", nodeIdentifier);
+        enqueueEvent(new NodeCacheManagerEvent(nodeIdentifier, Action.ADD));
+    }
+    @Override
+    public void nodeRemoved(String nodeIdentifier) {
+        logger.info("XXX >>>>> enqueue: Node removed : {}", nodeIdentifier);
+        logger.debug(">>>>> enqueue: Node removed : {}", nodeIdentifier);
+        enqueueEvent(new NodeCacheManagerEvent(nodeIdentifier, Action.DELETE));
+    }
+    @Override
+    public List<Node> getNodes() {
+        return nodeCache;
+    }
+
+    void doNodeAdded(Node node) {
+        nodeCache.add(node);
+        logger.info("XXXX added node {}. cache is now {}", node, nodeCache);
+    }
+    void doNodeRemoved(Node node) {
+        nodeCache.remove(node);
+        logger.info("XXXX removed node {}. cache is now {}", node, nodeCache);
+    }
+
+    /**
+     * Process the event.
+     *
+     * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
+     * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
+     */
+    @Override
+    public void processEvent(AbstractEvent abstractEvent) {
+        if (!(abstractEvent instanceof NodeCacheManagerEvent)) {
+            logger.error("Unable to process abstract event " + abstractEvent);
+            return;
+        }
+        NodeCacheManagerEvent ev = (NodeCacheManagerEvent) abstractEvent;
+        logger.debug(">>>>> dequeue: {}", ev);
+        switch (ev.getAction()) {
+            case ADD:
+                doNodeAdded(NodeUtils.getOpenFlowNode(ev.getNodeIdentifier()));
+                break;
+            case DELETE:
+                doNodeRemoved(NodeUtils.getOpenFlowNode(ev.getNodeIdentifier()));
+                break;
+            case UPDATE:
+                break;
+            default:
+                logger.warn("Unable to process event action " + ev.getAction());
+                break;
+        }
+    }
+}
diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NodeUtils.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NodeUtils.java
new file mode 100644 (file)
index 0000000..a6e4ec0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Authors : Sam Hague
+ */
+package org.opendaylight.ovsdb.openstack.netvirt.impl;
+
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// TODO: Move this to org.opendaylight.ovsdb.utils
+
+public class NodeUtils {
+    protected static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class);
+
+    public static String getId (String identifier) {
+        String id = identifier;
+
+        String[] pair = identifier.split("\\|");
+        if (pair[0].equals("OVS")) {
+            id = pair[1];
+        }
+        return id;
+    }
+
+    public static Node getOpenFlowNode (String identifier) {
+        NodeId nodeId = new NodeId(identifier);
+        NodeKey nodeKey = new NodeKey(nodeId);
+        Node node = new NodeBuilder()
+                .setId(nodeId)
+                .setKey(nodeKey)
+                .build();
+
+        return node;
+    }
+
+    public static Node getMdsalNode (org.opendaylight.controller.sal.core.Node salNode) {
+        String identifier = salNode.getNodeIDString();
+
+        NodeId nodeId = new NodeId("OVS" + "|" + identifier);
+        NodeKey nodeKey = new NodeKey(nodeId);
+        Node node = new NodeBuilder()
+                .setId(nodeId)
+                .setKey(nodeKey)
+                .build();
+
+        return node;
+    }
+
+    public static org.opendaylight.controller.sal.core.Node getSalNode (Node mdsalNode) {
+        String identifier = NodeUtils.getId(mdsalNode.getId().getValue());
+        org.opendaylight.controller.sal.core.Node node = null;
+
+        try {
+            node = new org.opendaylight.controller.sal.core.Node("OVS", identifier);
+        } catch (ConstructionException e) {
+            LOG.error("Failed to allocate sal Node", e);
+        }
+
+        return node;
+    }
+
+    public static List<org.opendaylight.controller.sal.core.Node> getSalNodes (List<Node> mdsalNodes) {
+        List<org.opendaylight.controller.sal.core.Node> nodes = new ArrayList<>();
+
+        for (Node mdsalNode : mdsalNodes) {
+            nodes.add(NodeUtils.getSalNode(mdsalNode));
+        }
+        return nodes;
+    }
+}