From 4b8ee62fd8f0fd6fb9b1ffed543e08e989b543e0 Mon Sep 17 00:00:00 2001 From: Giovanni Meo Date: Thu, 22 Aug 2013 22:53:26 +0200 Subject: [PATCH] Fix Connection manager to retrieve inventory when is up When ConnectionManager comes up, it's very much possible that may have missed some inventory updates, so it needs to retrieve them to make sure holes are covered, this is seen during integration test with the stub protocol plugin, hence also make sure stub protocol plugin provides the necessary hooks. Change-Id: I41d5c71dd70aad909f7a75e0f596ec69a212400c Signed-off-by: Giovanni Meo --- .../connectionmanager/internal/Activator.java | 8 ++++ .../internal/ConnectionManager.java | 39 +++++++++++++++- .../stub/internal/Activator.java | 26 ++++++++++- .../stub/internal/InventoryService.java | 44 ++++++++++++++++++- 4 files changed, 113 insertions(+), 4 deletions(-) diff --git a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/Activator.java b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/Activator.java index 4bee253765..c0d1b50a46 100644 --- a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/Activator.java +++ b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/Activator.java @@ -25,6 +25,7 @@ import org.apache.felix.dm.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; +import org.opendaylight.controller.sal.inventory.IInventoryService; import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates; public class Activator extends ComponentActivatorAbstractBase { @@ -37,6 +38,7 @@ public class Activator extends ComponentActivatorAbstractBase { * ComponentActivatorAbstractBase. * */ + @Override public void init() { } @@ -45,6 +47,7 @@ public class Activator extends ComponentActivatorAbstractBase { * cleanup done by ComponentActivatorAbstractBase * */ + @Override public void destroy() { } @@ -61,6 +64,7 @@ public class Activator extends ComponentActivatorAbstractBase { * @return The list of implementations the bundle will support, * in Global version */ + @Override protected Object[] getGlobalImplementations() { Object[] res = { ConnectionManager.class }; return res; @@ -74,6 +78,7 @@ public class Activator extends ComponentActivatorAbstractBase { * @param imp implementation to be configured * @param containerName container on which the configuration happens */ + @Override protected void configureGlobalInstance(Component c, Object imp) { if (imp.equals(ConnectionManager.class)) { Dictionary props = new Hashtable(); @@ -100,6 +105,9 @@ public class Activator extends ComponentActivatorAbstractBase { c.add(createServiceDependency().setService(IConnectionService.class) .setCallbacks("setConnectionService", "unsetConnectionService") .setRequired(true)); + c.add(createServiceDependency().setService(IInventoryService.class, "(scope=Global)") + .setCallbacks("setInventoryService", "unsetInventoryService") + .setRequired(true)); } } } diff --git a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java index fdba533b5b..e2d8f6b03b 100644 --- a/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java +++ b/opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java @@ -32,7 +32,6 @@ import java.util.concurrent.LinkedBlockingQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.eclipse.osgi.framework.console.CommandInterpreter; import org.eclipse.osgi.framework.console.CommandProvider; import org.opendaylight.controller.clustering.services.ICacheUpdateAware; @@ -49,6 +48,7 @@ import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.core.UpdateType; +import org.opendaylight.controller.sal.inventory.IInventoryService; import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; @@ -66,6 +66,7 @@ public class ConnectionManager implements IConnectionManager, IConnectionListene private IConnectionService connectionService; private Thread connectionEventThread; private BlockingQueue connectionEvents; + private IInventoryService inventoryService; public void setClusterServices(IClusterGlobalServices i) { this.clusterServices = i; @@ -87,12 +88,48 @@ public class ConnectionManager implements IConnectionManager, IConnectionListene } } + public void setInventoryService(IInventoryService service) { + logger.trace("Got inventory service set request {}", service); + this.inventoryService = service; + } + + public void unsetInventoryService(IInventoryService service) { + logger.trace("Got a service UNset request"); + this.inventoryService = null; + } + + private void getInventories() { + Map> nodeProp = this.inventoryService.getNodeProps(); + for (Map.Entry> entry : nodeProp.entrySet()) { + Node node = entry.getKey(); + logger.debug("getInventories for node:{}", new Object[] { node }); + Map propMap = entry.getValue(); + Set props = new HashSet(); + for (Property property : propMap.values()) { + props.add(property); + } + updateNode(node, UpdateType.ADDED, props); + } + + Map> nodeConnectorProp = this.inventoryService.getNodeConnectorProps(); + for (Map.Entry> entry : nodeConnectorProp.entrySet()) { + Map propMap = entry.getValue(); + Set props = new HashSet(); + for (Property property : propMap.values()) { + props.add(property); + } + updateNodeConnector(entry.getKey(), UpdateType.ADDED, props); + } + } + public void started() { connectionEventThread = new Thread(new EventHandler(), "ConnectionEvent Thread"); connectionEventThread.start(); registerWithOSGIConsole(); notifyClusterViewChanged(); + // Should pull the Inventory updates in case we missed it + getInventories(); } public void init() { diff --git a/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java index 76c38664d4..79edd93c67 100644 --- a/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java +++ b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/Activator.java @@ -40,6 +40,7 @@ public class Activator extends ComponentActivatorAbstractBase { * are done by the ComponentActivatorAbstractBase. * */ + @Override public void init() { Node.NodeIDType.registerIDType("STUB", Integer.class); NodeConnector.NodeConnectorIDType.registerIDType("STUB", Integer.class, "STUB"); @@ -50,6 +51,7 @@ public class Activator extends ComponentActivatorAbstractBase { * ComponentActivatorAbstractBase * */ + @Override public void destroy() { Node.NodeIDType.unRegisterIDType("STUB"); NodeConnector.NodeConnectorIDType.unRegisterIDType("STUB"); @@ -64,6 +66,7 @@ public class Activator extends ComponentActivatorAbstractBase { * instantiated in order to get an fully working implementation * Object */ + @Override public Object[] getImplementations() { Object[] res = { ReadService.class, InventoryService.class }; return res; @@ -84,6 +87,7 @@ public class Activator extends ComponentActivatorAbstractBase { * per-container different behavior if needed, usually should not * be the case though. */ + @Override public void configureInstance(Component c, Object imp, String containerName) { if (imp.equals(ReadService.class)) { // export the service to be used by SAL @@ -104,11 +108,18 @@ public class Activator extends ComponentActivatorAbstractBase { } } + @Override public Object[] getGlobalImplementations() { - Object[] res = { FlowProgrammerService.class, StubNodeFactory.class, StubNodeConnectorFactory.class }; + Object[] res = + { + FlowProgrammerService.class, + StubNodeFactory.class, + StubNodeConnectorFactory.class, + InventoryService.class }; return res; } + @Override public void configureGlobalInstance(Component c, Object imp){ if (imp.equals(FlowProgrammerService.class)) { // export the service to be used by SAL @@ -136,6 +147,17 @@ public class Activator extends ComponentActivatorAbstractBase { props.put("protocolName", "STUB"); c.setInterface(INodeConnectorFactory.class.getName(), props); } - + if (imp.equals(InventoryService.class)) { + // export the service to be used by SAL + Dictionary props = new Hashtable(); + // Set the protocolPluginType property which will be used + // by SAL + props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB"); + props.put("scope", "Global"); + c.setInterface(IPluginInInventoryService.class.getName(), props); + c.add(createServiceDependency().setService(IPluginOutInventoryService.class, "(scope=Global)") + .setCallbacks("setPluginOutInventoryServices", "unsetPluginOutInventoryServices") + .setRequired(true)); + } } } diff --git a/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/InventoryService.java b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/InventoryService.java index 22a4343f33..b94ffec1dd 100644 --- a/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/InventoryService.java +++ b/opendaylight/protocol_plugins/stub/src/main/java/org/opendaylight/controller/protocol_plugins/stub/internal/InventoryService.java @@ -12,11 +12,11 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; import org.apache.felix.dm.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.opendaylight.controller.sal.core.Actions; import org.opendaylight.controller.sal.core.Bandwidth; import org.opendaylight.controller.sal.core.Buffers; @@ -29,7 +29,9 @@ import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.core.State; import org.opendaylight.controller.sal.core.Tables; import org.opendaylight.controller.sal.core.TimeStamp; +import org.opendaylight.controller.sal.core.UpdateType; import org.opendaylight.controller.sal.inventory.IPluginInInventoryService; +import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService; import org.opendaylight.controller.sal.utils.NodeCreator; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; @@ -55,6 +57,22 @@ public class InventoryService implements IPluginInInventoryService { // global // container // only + private final Set pluginOutInventoryServices = + new CopyOnWriteArraySet(); + + public void setPluginOutInventoryServices(IPluginOutInventoryService service) { + logger.trace("Got a service set request {}", service); + if (this.pluginOutInventoryServices != null) { + this.pluginOutInventoryServices.add(service); + } + } + + public void unsetPluginOutInventoryServices(IPluginOutInventoryService service) { + logger.trace("Got a service UNset request"); + if (this.pluginOutInventoryServices != null) { + this.pluginOutInventoryServices.remove(service); + } + } /** * Function called by the dependency manager when all the required @@ -173,6 +191,29 @@ public class InventoryService implements IPluginInInventoryService { void start() { } + /** + * Method called when the plugin has exposed it's services, this will be + * used to publish the updates so connection manager can think the + * connection is local + */ + void started() { + // update sal and discovery + for (IPluginOutInventoryService service : pluginOutInventoryServices) { + for (Node node : nodeProps.keySet()) { + Set props = new HashSet(nodeProps.get(node) + .values()); + service.updateNode(node, UpdateType.ADDED, props); + logger.trace("Adding Node {} with props {}", node, props); + } + for (NodeConnector nc : nodeConnectorProps.keySet()) { + Set props = new HashSet(nodeConnectorProps.get(nc) + .values()); + service.updateNodeConnector(nc, UpdateType.ADDED, props); + logger.trace("Adding NodeConnectors {} with props {}", nc, props); + } + } + } + /** * Function called by the dependency manager before the services exported by * the component are unregistered, this will be followed by a "destroy ()" @@ -180,6 +221,7 @@ public class InventoryService implements IPluginInInventoryService { * */ void stop() { + pluginOutInventoryServices.clear(); } /** -- 2.36.6