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>
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;
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)
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();
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()));
+ }
}
}
(NetworkingProviderManager) ServiceHelper.getGlobalInstance(NetworkingProviderManager.class,
this);
networkingProviderManager.getProvider(openFlowNode).initializeOFFlowRules(openFlowNode);
+
+ if (nodeCacheManager != null) {
+ nodeCacheManager.nodeAdded(openFlowNode.getId().getValue());
+ }
}
}
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());
+ }
}
}
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);
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;
}
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;
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;
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
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}