From: Tony Tkacik Date: Sat, 15 Feb 2014 01:37:07 +0000 (+0000) Subject: Merge "Do not rely od DataStore for all connected nodes" X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~449 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=fa1fa1e80351e6f86e81f95d5c50a0521d0cbb93;hp=4987483d864bb1cac421db27150690f956b9d3e5 Merge "Do not rely od DataStore for all connected nodes" --- diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java index 2123f6b9eb..ee571b83e1 100644 --- a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java +++ b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java @@ -13,4 +13,12 @@ package org.opendaylight.controller.configuration; * Container configuration service */ public interface IConfigurationContainerService extends IConfigurationServiceCommon { + + /** + * Bundle will call this function to ask ContainerConfigurationService to provide the + * directory location of container + * + * @return The path to active container directory + */ + String getConfigurationRoot(); } diff --git a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationService.java b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationService.java index e4d55d11fb..4c0f3a2da5 100644 --- a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationService.java +++ b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationService.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.configuration.internal; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; @@ -25,6 +26,7 @@ import org.opendaylight.controller.clustering.services.IClusterServices; import org.opendaylight.controller.configuration.ConfigurationEvent; import org.opendaylight.controller.configuration.ConfigurationObject; import org.opendaylight.controller.configuration.IConfigurationAware; +import org.opendaylight.controller.configuration.IConfigurationContainerService; import org.opendaylight.controller.configuration.IConfigurationService; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.IObjectReader; @@ -46,7 +48,7 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate private static final Logger logger = LoggerFactory .getLogger(ConfigurationService.class); public static final String SAVE_EVENT_CACHE = "config.event.save"; - private static final Object ROOT = GlobalConstants.STARTUPHOME.toString(); + private static final String ROOT = GlobalConstants.STARTUPHOME.toString(); private IClusterGlobalServices clusterServices; private ConcurrentMap configEvent; private Set configurationAwareList = Collections @@ -105,21 +107,66 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate return saveConfigurationsInternal(); } + + private List getContainerDirectoryList() { + List containerList = new ArrayList(); + for (IConfigurationAware configurationAware : this.configurationAwareList) { + if (configurationAware instanceof IConfigurationContainerService) { + String containerFilePath = ((ContainerConfigurationService)configurationAware).getConfigurationRoot(); + containerList.add(containerFilePath); + } + } + return containerList; + } + + private void createContainerDirectory(IConfigurationAware configurationAware) { + String containerFilePath = ((ContainerConfigurationService) configurationAware).getConfigurationRoot(); + if (!new File(containerFilePath).exists()) { + boolean created = new File(containerFilePath).mkdir(); + if (!created) { + logger.error("Failed to create startup config directory: {}", containerFilePath); + } + } + } + + private void clearStaleContainerDirectories() { + List activeContainers = getContainerDirectoryList(); + for (File file : new File(ROOT).listFiles()) { + if (file.isDirectory() && !activeContainers.contains(file.toPath() + File.separator)) { + logger.trace("Removing directory for container {}", file.getName()); + for (File innerFile : file.listFiles()) { + innerFile.delete(); + } + boolean removed = file.delete(); + if (!removed) { + logger.warn("Failed to remove stale directory: {}", file.getName()); + } + } + } + } + + private Status saveConfigurationsInternal() { boolean success = true; for (IConfigurationAware configurationAware : configurationAwareList) { + if (configurationAware instanceof IConfigurationContainerService) { + // Create directory for new containers + createContainerDirectory(configurationAware); + } Status status = configurationAware.saveConfiguration(); if (!status.isSuccess()) { success = false; - logger.warn("Failed to save config for {}", - configurationAware.getClass().getName()); + logger.warn("Failed to save config for {}", configurationAware.getClass().getName()); } } + // Remove startup directories of containers that were removed from + // the configuration but not saved + clearStaleContainerDirectories(); + if (success) { return new Status(StatusCode.SUCCESS); } else { - return new Status(StatusCode.INTERNALERROR, - "Failed to Save All Configurations"); + return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations"); } } diff --git a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ContainerConfigurationService.java b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ContainerConfigurationService.java index 9c1d391daa..3e067254ed 100644 --- a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ContainerConfigurationService.java +++ b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ContainerConfigurationService.java @@ -9,7 +9,6 @@ package org.opendaylight.controller.configuration.internal; -import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Dictionary; @@ -52,14 +51,10 @@ public class ContainerConfigurationService implements IConfigurationContainerSer private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class); private IClusterContainerServices clusterServices; private ConcurrentMap containerConfigEvent; - /* - * Collection containing the configuration objects. - * This is configuration world: container names (also the map key) - * are maintained as they were configured by user, same case - */ + // Directory which contains the startup files for this container + private String root; private Set configurationAwareList = Collections .synchronizedSet(new HashSet()); - private String root; private ObjectReader objReader; private ObjectWriter objWriter; @@ -93,14 +88,9 @@ public class ContainerConfigurationService implements IConfigurationContainerSer void init(Component c) { Dictionary props = c.getServiceProperties(); - String containerName = (props != null) ? (String) props.get("containerName") : GlobalConstants.DEFAULT.toString(); - root = String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName); - if (!new File(root).exists()) { - boolean created = new File(root).mkdir(); - if (!created) { - logger.error("Failed to create startup config directory for container {}", containerName); - } - } + String containerName = (props != null) ? (String) props.get("containerName") : + GlobalConstants.DEFAULT.toString(); + root = String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName); } public void start() { @@ -119,17 +109,18 @@ public class ContainerConfigurationService implements IConfigurationContainerSer * Function called by the dependency manager before Container is Stopped and Destroyed. */ public void containerStop() { - // Remove container directory along with its startup files - File[] files = new File(root).listFiles(); - for (File file : files) { - file.delete(); - } - new File(root).delete(); + // Do nothing + } + + @Override + public String getConfigurationRoot() { + return root; } @Override public Status saveConfiguration() { boolean success = true; + for (IConfigurationContainerAware configurationAware : configurationAwareList) { logger.trace("Save Config triggered for {}", configurationAware.getClass().getSimpleName()); diff --git a/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java b/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java index ad897fd689..0fee183b67 100644 --- a/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java +++ b/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java @@ -9,7 +9,6 @@ package org.opendaylight.controller.containermanager.internal; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; @@ -751,26 +750,6 @@ public class ContainerManager extends Authorization implements IContaine return status; } - private void removeComponentsStartUpfiles(String containerName) { - String startupLocation = String.format("./%s", GlobalConstants.STARTUPHOME.toString()); - String containerPrint = String.format("_%s.", containerName.toLowerCase(Locale.ENGLISH)); - - File directory = new File(startupLocation); - String[] fileList = directory.list(); - - logger.trace("Deleting startup configuration files for container {}", containerName); - if (fileList != null) { - for (String fileName : fileList) { - if (fileName.contains(containerPrint)) { - String fullPath = String.format("%s/%s", startupLocation, fileName); - File file = new File(fullPath); - boolean done = file.delete(); - logger.trace("{} {}", (done ? "Deleted: " : "Failed to delete: "), fileName); - } - } - } - } - /** * Create and initialize default all resource group and create association * with default well known users and profiles, if not already learnt from @@ -1013,19 +992,6 @@ public class ContainerManager extends Authorization implements IContaine notifyContainerModeChange(delete, notifyLocal); // Notify listeners notifyContainerAwareListeners(container, delete); - - /* - * This is a quick fix until configuration service becomes the - * centralized configuration management place. Here container manager - * will remove the startup files for all the bundles that are present in - * the container being deleted. Do the cleanup here in Container manger - * as do not want to put this temporary code in Configuration manager - * yet which is ODL. - */ - if (delete) { - // TODO: remove when Config Mgr takes over - removeComponentsStartUpfiles(containerName); - } } private void notifyContainerEntryChangeInternal(String containerName, List ncList, UpdateType update, boolean notifyLocal) { diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend index a6fc4b0a23..a59c2c1636 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend @@ -251,6 +251,7 @@ package class SalCompatibilityProvider implements BindingAwareProvider { topology.dataService = session.getSALService(DataProviderService) tpProvider.dataService = session.getSALService(DataProviderService) + inventory.start(); tpProvider.start(); diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend index fac12ee10d..8a0874ee31 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend @@ -199,9 +199,11 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi } private def Future> internalModifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) { - val flowId = getCache().remove(oldFlow); + var flowId = getCache().remove(oldFlow); if(flowId == null){ - throw new IllegalArgumentException("oldFlow is unknown"); + LOG.error("oldFlow not found in cache : " + oldFlow.hashCode); + flowId = UUID.randomUUID(); + getCache().put(oldFlow, flowId); } getCache().put(newFlow, flowId); @@ -212,7 +214,9 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi private def Future> internalRemoveFlowAsync(Node node, Flow adflow, long rid){ val flowId = getCache().remove(adflow); if(flowId == null){ - throw new IllegalArgumentException("adflow is unknown"); + //throw new IllegalArgumentException("adflow not found in cache : " + adflow.hashCode); + LOG.error("adflow not found in cache : " + adflow.hashCode); + return null; } val flow = adflow.toMDFlow(flowId.toString()); val modification = this._dataBrokerService.beginTransaction(); @@ -227,6 +231,10 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi } private def toFutureStatus(Future> future){ + if(future == null){ + return toStatus(true); + } + try { val result = future.get(); return toStatus(result); diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend index 60e43247c2..0c211fd0aa 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend @@ -11,6 +11,9 @@ import java.util.ArrayList import java.util.Collections import java.util.List import java.util.Set +import java.util.ArrayList; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.Lock; import java.util.concurrent.CopyOnWriteArrayList; import org.opendaylight.controller.sal.binding.api.data.DataBrokerService import org.opendaylight.controller.sal.binding.api.data.DataProviderService @@ -76,17 +79,18 @@ import static extension org.opendaylight.controller.sal.compatibility.NodeMappin import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader import java.util.concurrent.ConcurrentHashMap import java.util.Map +import java.util.HashMap class InventoryAndReadAdapter implements IPluginInReadService, - IPluginInInventoryService, - OpendaylightInventoryListener, - OpendaylightFlowStatisticsListener, - OpendaylightFlowTableStatisticsListener, - OpendaylightPortStatisticsListener { + IPluginInInventoryService, + OpendaylightInventoryListener, + OpendaylightFlowStatisticsListener, + OpendaylightFlowTableStatisticsListener, + OpendaylightPortStatisticsListener { private static val LOG = LoggerFactory.getLogger(InventoryAndReadAdapter); - private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue; + private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue; @Property DataBrokerService dataService; @@ -111,21 +115,34 @@ class InventoryAndReadAdapter implements IPluginInReadService, @Property List inventoryPublisher = new CopyOnWriteArrayList(); - def setInventoryPublisher(IPluginOutInventoryService listener){ + private final InventoryNotificationProvider inventoryNotificationProvider = new InventoryNotificationProvider(); + + private final Map> nodeToNodeConnectorsMap = new ConcurrentHashMap>(); + + private final Lock nodeToNodeConnectorsLock = new ReentrantLock(); + + + def start(){ + inventoryNotificationProvider.dataProviderService = dataProviderService; + inventoryNotificationProvider.inventoryPublisher = inventoryPublisher; + // inventoryNotificationProvider.start(); + } + + def setInventoryPublisher(IPluginOutInventoryService listener){ inventoryPublisher.add(listener); - } + } - def unsetInventoryPublisher(IPluginOutInventoryService listener){ + def unsetInventoryPublisher(IPluginOutInventoryService listener){ inventoryPublisher.remove(listener); - } + } def setReadPublisher(IPluginOutReadService listener) { - statisticsPublisher.add(listener); + statisticsPublisher.add(listener); } def unsetReadPublisher (IPluginOutReadService listener) { - if( listener != null) - statisticsPublisher.remove(listener); + if( listener != null) + statisticsPublisher.remove(listener); } protected def startChange() { @@ -140,33 +157,33 @@ class InventoryAndReadAdapter implements IPluginInReadService, override readAllFlow(Node node, boolean cached) { val output = new ArrayList(); - val tableRef = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) - .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance(); - - val it = this.startChange(); - - val table= it.readConfigurationData(tableRef) as Table; - - if(table != null){ - LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size); - - for(flow : table.flow){ - - val adsalFlow = ToSalConversionsUtils.toFlow(flow,node); - val statsFromDataStore = flow.getAugmentation(FlowStatisticsData); - - if(statsFromDataStore != null){ - val it = new FlowOnNode(adsalFlow); - byteCount = statsFromDataStore.flowStatistics.byteCount.value.longValue; - packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue; - durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue; - durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue; - - output.add(it); - } - } - } + val tableRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) + .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance(); + + val it = this.startChange(); + + val table= it.readConfigurationData(tableRef) as Table; + + if(table != null){ + LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size); + + for(flow : table.flow){ + + val adsalFlow = ToSalConversionsUtils.toFlow(flow,node); + val statsFromDataStore = flow.getAugmentation(FlowStatisticsData); + + if(statsFromDataStore != null){ + val it = new FlowOnNode(adsalFlow); + byteCount = statsFromDataStore.flowStatistics.byteCount.value.longValue; + packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue; + durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue; + durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue; + + output.add(it); + } + } + } //TODO (main): Shell we send request to the switch? It will make async request to the switch. // Once plugin receive response, it will let adaptor know through onFlowStatisticsUpdate() @@ -180,35 +197,35 @@ class InventoryAndReadAdapter implements IPluginInReadService, } override readAllNodeConnector(Node node, boolean cached) { - - val ret = new ArrayList(); - val nodeRef = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) - .toInstance(); - - val provider = this.startChange(); - - val dsNode= provider.readConfigurationData(nodeRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; - - if(dsNode != null){ - - for (dsNodeConnector : dsNode.nodeConnector){ - val nodeConnectorRef = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) - .child(NodeConnector, dsNodeConnector.key) - .toInstance(); - - val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector; - - if(nodeConnectorFromDS != null){ - val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics; - - ret.add(toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,dsNode.id,dsNodeConnector.id)); - } - } - } - - //TODO: Refer TODO (main) + + val ret = new ArrayList(); + val nodeRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) + .toInstance(); + + val provider = this.startChange(); + + val dsNode= provider.readConfigurationData(nodeRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; + + if(dsNode != null){ + + for (dsNodeConnector : dsNode.nodeConnector){ + val nodeConnectorRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) + .child(NodeConnector, dsNodeConnector.key) + .toInstance(); + + val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector; + + if(nodeConnectorFromDS != null){ + val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics; + + ret.add(toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,dsNode.id,dsNodeConnector.id)); + } + } + } + + //TODO: Refer TODO (main) val input = new GetAllNodeConnectorsStatisticsInputBuilder(); input.setNode(node.toNodeRef); nodeConnectorStatisticsService.getAllNodeConnectorsStatistics(input.build()); @@ -216,23 +233,23 @@ class InventoryAndReadAdapter implements IPluginInReadService, } override readAllNodeTable(Node node, boolean cached) { - val ret = new ArrayList(); - - val dsFlowCapableNode= readFlowCapableNode(node.toNodeRef) - - if(dsFlowCapableNode != null){ - - for (table : dsFlowCapableNode.table){ - - val tableStats = table.getAugmentation(FlowTableStatisticsData); - - if(tableStats != null){ - ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node)); - } - } - } - - //TODO: Refer TODO (main) + val ret = new ArrayList(); + + val dsFlowCapableNode= readFlowCapableNode(node.toNodeRef) + + if(dsFlowCapableNode != null){ + + for (table : dsFlowCapableNode.table){ + + val tableStats = table.getAugmentation(FlowTableStatisticsData); + + if(tableStats != null){ + ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node)); + } + } + } + + //TODO: Refer TODO (main) val input = new GetFlowTablesStatisticsInputBuilder(); input.setNode(node.toNodeRef); flowTableStatisticsService.getFlowTablesStatistics(input.build); @@ -241,39 +258,39 @@ class InventoryAndReadAdapter implements IPluginInReadService, override readDescription(Node node, boolean cached) { return toNodeDescription(node.toNodeRef); - } + } override readFlow(Node node, Flow targetFlow, boolean cached) { - var FlowOnNode ret= null; - - val tableRef = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) - .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance(); - - val it = this.startChange(); - - val table= it.readConfigurationData(tableRef) as Table; - - if(table != null){ - LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size); - - for(mdsalFlow : table.flow){ - if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){ - val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData); - - if(statsFromDataStore != null){ - LOG.debug("Found matching flow in the data store flow table "); - val it = new FlowOnNode(targetFlow); - byteCount = statsFromDataStore.flowStatistics.byteCount.value.longValue; - packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue; - durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue; - durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue; - - ret = it; - } - } - } - } + var FlowOnNode ret= null; + + val tableRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node)) + .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance(); + + val it = this.startChange(); + + val table= it.readConfigurationData(tableRef) as Table; + + if(table != null){ + LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size); + + for(mdsalFlow : table.flow){ + if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){ + val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData); + + if(statsFromDataStore != null){ + LOG.debug("Found matching flow in the data store flow table "); + val it = new FlowOnNode(targetFlow); + byteCount = statsFromDataStore.flowStatistics.byteCount.value.longValue; + packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue; + durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue; + durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue; + + ret = it; + } + } + } + } //TODO: Refer TODO (main) val input = new GetFlowStatisticsFromFlowTableInputBuilder; @@ -282,30 +299,30 @@ class InventoryAndReadAdapter implements IPluginInReadService, flowStatisticsService.getFlowStatisticsFromFlowTable(input.build) return ret; - + } override readNodeConnector(org.opendaylight.controller.sal.core.NodeConnector connector, boolean cached) { - var NodeConnectorStatistics nodeConnectorStatistics = null; - - val nodeConnectorRef = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(connector.node)) - .child(NodeConnector, InventoryMapping.toNodeConnectorKey(connector)) - .toInstance(); - val provider = this.startChange(); - - val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector; - - if(nodeConnectorFromDS != null){ - val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics; - if(nodeConnectorStatsFromDs != null) { - nodeConnectorStatistics = toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics, - InventoryMapping.toNodeKey(connector.node).id, - InventoryMapping.toNodeConnectorKey(connector).id); - } - } - - //TODO: Refer TODO (main) + var NodeConnectorStatistics nodeConnectorStatistics = null; + + val nodeConnectorRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(connector.node)) + .child(NodeConnector, InventoryMapping.toNodeConnectorKey(connector)) + .toInstance(); + val provider = this.startChange(); + + val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector; + + if(nodeConnectorFromDS != null){ + val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics; + if(nodeConnectorStatsFromDs != null) { + nodeConnectorStatistics = toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics, + InventoryMapping.toNodeKey(connector.node).id, + InventoryMapping.toNodeConnectorKey(connector).id); + } + } + + //TODO: Refer TODO (main) val input = new GetNodeConnectorStatisticsInputBuilder(); input.setNode(connector.node.toNodeRef); input.setNodeConnectorId(InventoryMapping.toNodeConnectorKey(connector).id); @@ -314,25 +331,25 @@ class InventoryAndReadAdapter implements IPluginInReadService, } override readNodeTable(NodeTable nodeTable, boolean cached) { - var NodeTableStatistics nodeStats = null - - val tableRef = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(nodeTable.node)) - .augmentation(FlowCapableNode).child(Table, new TableKey(nodeTable.ID as Short)).toInstance(); - - val it = this.startChange(); - - val table= it.readConfigurationData(tableRef) as Table; - - if(table != null){ - val tableStats = table.getAugmentation(FlowTableStatisticsData); - - if(tableStats != null){ - nodeStats = toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node); - } - } - - //TODO: Refer TODO (main) + var NodeTableStatistics nodeStats = null + + val tableRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(nodeTable.node)) + .augmentation(FlowCapableNode).child(Table, new TableKey(nodeTable.ID as Short)).toInstance(); + + val it = this.startChange(); + + val table= it.readConfigurationData(tableRef) as Table; + + if(table != null){ + val tableStats = table.getAugmentation(FlowTableStatisticsData); + + if(tableStats != null){ + nodeStats = toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node); + } + } + + //TODO: Refer TODO (main) val input = new GetFlowTablesStatisticsInputBuilder(); input.setNode(nodeTable.node.toNodeRef); flowTableStatisticsService.getFlowTablesStatistics(input.build); @@ -341,19 +358,22 @@ class InventoryAndReadAdapter implements IPluginInReadService, } override onNodeConnectorRemoved(NodeConnectorRemoved update) { - // NOOP + // Never received } override onNodeRemoved(NodeRemoved notification) { val properties = Collections.emptySet(); + removeNodeConnectors(notification.nodeRef.value); + publishNodeUpdate(notification.nodeRef.toADNode, UpdateType.REMOVED, properties); } override onNodeConnectorUpdated(NodeConnectorUpdated update) { var updateType = UpdateType.CHANGED; - if ( this._dataService.readOperationalData(update.nodeConnectorRef.value as InstanceIdentifier) == null ){ + if(!isKnownNodeConnector(update.nodeConnectorRef.value)){ updateType = UpdateType.ADDED; + recordNodeConnector(update.nodeConnectorRef.value); } var nodeConnector = update.nodeConnectorRef.toADNodeConnector @@ -369,16 +389,16 @@ class InventoryAndReadAdapter implements IPluginInReadService, updateType = UpdateType.ADDED; } publishNodeUpdate(notification.nodeRef.toADNode, updateType, notification.toADNodeProperties); - - //Notify the listeners of IPluginOutReadService - + + //Notify the listeners of IPluginOutReadService + for (statsPublisher : statisticsPublisher){ - val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; + val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; val description = notification.nodeRef.toNodeDescription if(description != null) { - statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,description); - } - } + statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,description); + } + } } override getNodeProps() { @@ -461,50 +481,50 @@ class InventoryAndReadAdapter implements IPluginInReadService, private def toNodeConnectorStatistics( org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics nodeConnectorStatistics, NodeId nodeId, NodeConnectorId nodeConnectorId) { - - val it = new NodeConnectorStatistics(); - - receivePacketCount = nodeConnectorStatistics.packets.received.longValue; - transmitPacketCount = nodeConnectorStatistics.packets.transmitted.longValue; - - receiveByteCount = nodeConnectorStatistics.bytes.received.longValue; - transmitByteCount = nodeConnectorStatistics.bytes.transmitted.longValue; - - receiveDropCount = nodeConnectorStatistics.receiveDrops.longValue; - transmitDropCount = nodeConnectorStatistics.transmitDrops.longValue; - - receiveErrorCount = nodeConnectorStatistics.receiveErrors.longValue; - transmitErrorCount = nodeConnectorStatistics.transmitErrors.longValue; - - receiveFrameErrorCount = nodeConnectorStatistics.receiveFrameError.longValue; - receiveOverRunErrorCount = nodeConnectorStatistics.receiveOverRunError.longValue; - receiveCRCErrorCount = nodeConnectorStatistics.receiveCrcError.longValue; - collisionCount = nodeConnectorStatistics.collisionCount.longValue; - - val nodeConnectorRef = InstanceIdentifier.builder(Nodes) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(nodeId)) - .child(NodeConnector,new NodeConnectorKey(nodeConnectorId)).toInstance; - - nodeConnector = NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef)); - - return it; - } - - private def toNodeTableStatistics( - FlowTableStatistics tableStats, - Short tableId,Node node){ - var it = new NodeTableStatistics(); - - activeCount = tableStats.activeFlows.value.intValue; - lookupCount = tableStats.packetsLookedUp.value.intValue; - matchedCount = tableStats.packetsMatched.value.intValue; - name = tableId.toString; - nodeTable = new NodeTable(NodeMapping.MD_SAL_TYPE,tableId,node); - return it; - } - - private def toNodeDescription(NodeRef nodeRef){ - val capableNode = readFlowCapableNode(nodeRef); + + val it = new NodeConnectorStatistics(); + + receivePacketCount = nodeConnectorStatistics.packets.received.longValue; + transmitPacketCount = nodeConnectorStatistics.packets.transmitted.longValue; + + receiveByteCount = nodeConnectorStatistics.bytes.received.longValue; + transmitByteCount = nodeConnectorStatistics.bytes.transmitted.longValue; + + receiveDropCount = nodeConnectorStatistics.receiveDrops.longValue; + transmitDropCount = nodeConnectorStatistics.transmitDrops.longValue; + + receiveErrorCount = nodeConnectorStatistics.receiveErrors.longValue; + transmitErrorCount = nodeConnectorStatistics.transmitErrors.longValue; + + receiveFrameErrorCount = nodeConnectorStatistics.receiveFrameError.longValue; + receiveOverRunErrorCount = nodeConnectorStatistics.receiveOverRunError.longValue; + receiveCRCErrorCount = nodeConnectorStatistics.receiveCrcError.longValue; + collisionCount = nodeConnectorStatistics.collisionCount.longValue; + + val nodeConnectorRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(nodeId)) + .child(NodeConnector,new NodeConnectorKey(nodeConnectorId)).toInstance; + + nodeConnector = NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef)); + + return it; + } + + private def toNodeTableStatistics( + FlowTableStatistics tableStats, + Short tableId,Node node){ + var it = new NodeTableStatistics(); + + activeCount = tableStats.activeFlows.value.intValue; + lookupCount = tableStats.packetsLookedUp.value.intValue; + matchedCount = tableStats.packetsMatched.value.intValue; + name = tableId.toString; + nodeTable = new NodeTable(NodeMapping.MD_SAL_TYPE,tableId,node); + return it; + } + + private def toNodeDescription(NodeRef nodeRef){ + val capableNode = readFlowCapableNode(nodeRef); if(capableNode !=null) { val it = new NodeDescription() manufacturer = capableNode.manufacturer @@ -515,101 +535,148 @@ class InventoryAndReadAdapter implements IPluginInReadService, return it; } return null; - } + } def Edge toADEdge(Link link) { new Edge(link.source.toADNodeConnector,link.destination.toADNodeConnector) } - - /* - * OpendaylightFlowStatisticsListener interface implementation - */ - override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) { + + /* + * OpendaylightFlowStatisticsListener interface implementation + */ + override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) { //Ignoring this notification as there does not seem to be a way to bubble this up to AD-SAL - } - - override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) { - - val adsalFlowsStatistics = new ArrayList(); - val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; - - for(flowStats : notification.flowAndStatisticsMapList){ - if(flowStats.tableId == 0) - adsalFlowsStatistics.add(toFlowOnNode(flowStats,nodeRef.toADNode)); - } - - for (statsPublisher : statisticsPublisher){ - statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics); - } - - } - /* - * OpendaylightFlowTableStatisticsListener interface implementation - */ - override onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) { - var adsalFlowTableStatistics = new ArrayList(); - - for(stats : notification.flowTableAndStatisticsMap){ - if (stats.tableId.value == 0){ - val it = new NodeTableStatistics(); - activeCount = stats.activeFlows.value.intValue; - lookupCount = stats.packetsLookedUp.value.longValue; - matchedCount = stats.packetsMatched.value.longValue; - - adsalFlowTableStatistics.add(it); - } - } - for (statsPublisher : statisticsPublisher){ - val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; - statsPublisher.nodeTableStatisticsUpdated(nodeRef.toADNode,adsalFlowTableStatistics); - } - } - - /* - * OpendaylightPortStatisticsUpdate interface implementation - */ - override onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) { - - val adsalPortStatistics = new ArrayList(); - - for(nodeConnectorStatistics : notification.nodeConnectorStatisticsAndPortNumberMap){ - adsalPortStatistics.add(toNodeConnectorStatistics(nodeConnectorStatistics,notification.id,nodeConnectorStatistics.nodeConnectorId)); - } - - for (statsPublisher : statisticsPublisher){ - val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; - statsPublisher.nodeConnectorStatisticsUpdated(nodeRef.toADNode,adsalPortStatistics); - } - - } - - private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap,Node node){ - - val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap,node)); - - byteCount = flowAndStatsMap.byteCount.value.longValue; - packetCount = flowAndStatsMap.packetCount.value.longValue; - durationSeconds = flowAndStatsMap.duration.second.value.intValue; - durationNanoseconds = flowAndStatsMap.duration.nanosecond.value.intValue; - - return it; - } - - override getConfiguredNotConnectedNodes() { + } + + override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) { + + val adsalFlowsStatistics = new ArrayList(); + val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; + + for(flowStats : notification.flowAndStatisticsMapList){ + if(flowStats.tableId == 0) + adsalFlowsStatistics.add(toFlowOnNode(flowStats,nodeRef.toADNode)); + } + + for (statsPublisher : statisticsPublisher){ + statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics); + } + + } + /* + * OpendaylightFlowTableStatisticsListener interface implementation + */ + override onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) { + var adsalFlowTableStatistics = new ArrayList(); + + for(stats : notification.flowTableAndStatisticsMap){ + if (stats.tableId.value == 0){ + val it = new NodeTableStatistics(); + activeCount = stats.activeFlows.value.intValue; + lookupCount = stats.packetsLookedUp.value.longValue; + matchedCount = stats.packetsMatched.value.longValue; + + adsalFlowTableStatistics.add(it); + } + } + for (statsPublisher : statisticsPublisher){ + val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; + statsPublisher.nodeTableStatisticsUpdated(nodeRef.toADNode,adsalFlowTableStatistics); + } + } + + /* + * OpendaylightPortStatisticsUpdate interface implementation + */ + override onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) { + + val adsalPortStatistics = new ArrayList(); + + for(nodeConnectorStatistics : notification.nodeConnectorStatisticsAndPortNumberMap){ + adsalPortStatistics.add(toNodeConnectorStatistics(nodeConnectorStatistics,notification.id,nodeConnectorStatistics.nodeConnectorId)); + } + + for (statsPublisher : statisticsPublisher){ + val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance; + statsPublisher.nodeConnectorStatisticsUpdated(nodeRef.toADNode,adsalPortStatistics); + } + + } + + private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap,Node node){ + + val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap,node)); + + byteCount = flowAndStatsMap.byteCount.value.longValue; + packetCount = flowAndStatsMap.packetCount.value.longValue; + durationSeconds = flowAndStatsMap.duration.second.value.intValue; + durationNanoseconds = flowAndStatsMap.duration.nanosecond.value.intValue; + + return it; + } + + override getConfiguredNotConnectedNodes() { return Collections.emptySet(); - } + } + + + private def publishNodeUpdate(Node node, UpdateType updateType, Set properties){ + for( publisher : inventoryPublisher){ + publisher.updateNode(node, updateType, properties); + } + } + + private def publishNodeConnectorUpdate(org.opendaylight.controller.sal.core.NodeConnector nodeConnector, UpdateType updateType, Set properties){ + for( publisher : inventoryPublisher){ + publisher.updateNodeConnector(nodeConnector, updateType, properties); + } + } + + private def isKnownNodeConnector(InstanceIdentifier nodeConnectorIdentifier){ + if(nodeConnectorIdentifier.path.size() < 3) { + return false; + } + val nodePath = nodeConnectorIdentifier.path.get(1); + val nodeConnectorPath = nodeConnectorIdentifier.getPath().get(2); - private def publishNodeUpdate(Node node, UpdateType updateType, Set properties){ - for( publisher : inventoryPublisher){ - publisher.updateNode(node, updateType, properties); - } - } + val nodeConnectors = nodeToNodeConnectorsMap.get(nodePath); - private def publishNodeConnectorUpdate(org.opendaylight.controller.sal.core.NodeConnector nodeConnector, UpdateType updateType, Set properties){ - for( publisher : inventoryPublisher){ - publisher.updateNodeConnector(nodeConnector, updateType, properties); - } - } + if(nodeConnectors == null){ + return false; + } + return nodeConnectors.contains(nodeConnectorPath); + } + + + private def recordNodeConnector(InstanceIdentifier nodeConnectorIdentifier){ + if(nodeConnectorIdentifier.path.size() < 3) { + return false; + } + + val nodePath = nodeConnectorIdentifier.path.get(1); + val nodeConnectorPath = nodeConnectorIdentifier.getPath().get(2); + + nodeToNodeConnectorsLock.lock(); + + try { + var nodeConnectors = nodeToNodeConnectorsMap.get(nodePath); + + if(nodeConnectors == null){ + nodeConnectors = new ArrayList(); + nodeToNodeConnectorsMap.put(nodePath, nodeConnectors); + } + + nodeConnectors.add(nodeConnectorPath); + } finally { + nodeToNodeConnectorsLock.unlock(); + } + } + + private def removeNodeConnectors(InstanceIdentifier nodeIdentifier){ + val nodePath = nodeIdentifier.path.get(1); + + nodeToNodeConnectorsMap.remove(nodePath); + } } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryNotificationProvider.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryNotificationProvider.java new file mode 100644 index 0000000000..23a98ff39a --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryNotificationProvider.java @@ -0,0 +1,59 @@ +package org.opendaylight.controller.sal.compatibility; + +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class InventoryNotificationProvider implements AutoCloseable{ + + private ListenerRegistration nodeConnectorDataChangeListenerRegistration; + + private NodeConnectorDataChangeListener nodeConnectorDataChangeListener; + + private DataProviderService dataProviderService; + + private List inventoryPublisher; + + private final static Logger LOG = LoggerFactory.getLogger(NodeConnectorDataChangeListener.class); + + public void start(){ + + LOG.info("InventoryNotificationProvider started"); + + if(dataProviderService != null + && inventoryPublisher!= null){ + + if(nodeConnectorDataChangeListener == null){ + InstanceIdentifier nodeConnectorPath = InstanceIdentifier.builder(Nodes.class).child(Node.class).child(NodeConnector.class).build(); + nodeConnectorDataChangeListener = new NodeConnectorDataChangeListener(); + nodeConnectorDataChangeListener.setInventoryPublisher(inventoryPublisher); + nodeConnectorDataChangeListenerRegistration = dataProviderService.registerDataChangeListener(nodeConnectorPath, nodeConnectorDataChangeListener); + } + + } + } + + @Override + public void close() throws Exception { + if(nodeConnectorDataChangeListenerRegistration != null){ + nodeConnectorDataChangeListenerRegistration.close(); + } + } + + public void setDataProviderService(DataProviderService dataProviderService) { + this.dataProviderService = dataProviderService; + } + + public void setInventoryPublisher(List inventoryPublisher) { + this.inventoryPublisher = inventoryPublisher; + } +} diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeConnectorDataChangeListener.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeConnectorDataChangeListener.java new file mode 100644 index 0000000000..eebba74244 --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeConnectorDataChangeListener.java @@ -0,0 +1,77 @@ +package org.opendaylight.controller.sal.compatibility; + +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.controller.sal.core.ConstructionException; +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.IPluginOutInventoryService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +// org.opendaylight.controller.sal.compatibility.NodeConnectorDataChangeListener +public class NodeConnectorDataChangeListener implements DataChangeListener{ + private final static Logger LOG = LoggerFactory.getLogger(NodeConnectorDataChangeListener.class); + + private List inventoryPublisher; + + public List getInventoryPublisher() { + return this.inventoryPublisher; + } + + public void setInventoryPublisher(final List inventoryPublisher) { + this.inventoryPublisher = inventoryPublisher; + } + + @Override + public void onDataChanged(DataChangeEvent, DataObject> change) { + final Map,DataObject> createdOperationalData = change.getCreatedOperationalData(); + final Map,DataObject> updatedOperationalData = change.getUpdatedOperationalData(); + + final Set,DataObject>> createdEntries = createdOperationalData.entrySet(); + final Set,DataObject>> updatedEntries = new HashSet<>(); + + updatedEntries.addAll(updatedOperationalData.entrySet()); + updatedEntries.removeAll(createdEntries); + + for(final Map.Entry,DataObject> entry : createdEntries){ + publishNodeConnectorUpdate(entry, UpdateType.ADDED); + } + + for(final Map.Entry,DataObject> entry : updatedEntries){ + publishNodeConnectorUpdate(entry, UpdateType.CHANGED); + } + } + + private void publishNodeConnectorUpdate(final Map.Entry,DataObject> entry, final UpdateType updateType) { + if (entry.getKey().getTargetType().equals(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector.class)) { + NodeConnectorRef nodeConnectorRef = new NodeConnectorRef(entry.getKey()); + NodeConnector nodeConnector = null; + try { + nodeConnector = NodeMapping.toADNodeConnector(nodeConnectorRef); + } catch (ConstructionException e) { + e.printStackTrace(); + } + HashSet _aDNodeConnectorProperties = NodeMapping.toADNodeConnectorProperties((org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector) entry.getValue()); + this.publishNodeConnectorUpdate(nodeConnector, updateType, _aDNodeConnectorProperties); + } + } + + private void publishNodeConnectorUpdate(final NodeConnector nodeConnector, final UpdateType updateType, final Set properties) { + LOG.debug("Publishing NodeConnector " + updateType.toString() + " nodeConnector Id = " + nodeConnector.getNodeConnectorIdAsString()); + + List _inventoryPublisher = getInventoryPublisher(); + for (final IPluginOutInventoryService publisher : _inventoryPublisher) { + publisher.updateNodeConnector(nodeConnector, updateType, properties); + } + } +} diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend index 1a66b3ba16..43f48a50e5 100644 --- a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend +++ b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend @@ -64,6 +64,8 @@ class FlowCapableInventoryProvider implements AutoCloseable { class NodeChangeCommiter implements OpendaylightInventoryListener { + static val LOG = LoggerFactory.getLogger(NodeChangeCommiter); + @Property val FlowCapableInventoryProvider manager; @@ -76,6 +78,9 @@ class NodeChangeCommiter implements OpendaylightInventoryListener { // Check path val it = manager.startChange() + + LOG.debug("removing node connector : " + ref.value.toString()); + removeOperationalData(ref.value as InstanceIdentifier); commit() } @@ -93,6 +98,8 @@ class NodeChangeCommiter implements OpendaylightInventoryListener { data.addAugmentation(FlowCapableNodeConnector, augment) } + LOG.debug("updating node connector : " + ref.value.toString()); + putOperationalData(ref.value as InstanceIdentifier, data.build()); commit() } @@ -101,6 +108,8 @@ class NodeChangeCommiter implements OpendaylightInventoryListener { val ref = node.nodeRef; val it = manager.startChange() + LOG.debug("removing node : " + ref.value.toString()); + removeOperationalData(ref.value as InstanceIdentifier); commit() } @@ -117,6 +126,8 @@ class NodeChangeCommiter implements OpendaylightInventoryListener { data.addAugmentation(FlowCapableNode, augment) } + LOG.debug("updating node : " + ref.value.toString()); + putOperationalData(ref.value as InstanceIdentifier, data.build()) commit() } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java index 5b947a5922..e48ebbc057 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java @@ -149,8 +149,6 @@ public class BindingIndependentConnector implements // private RpcProviderRegistryImpl baRpcRegistryImpl; - private org.opendaylight.controller.sal.dom.broker.spi.RpcRouter biRouter; - private NotificationProviderService baNotifyService; private NotificationPublishService domNotificationService; @@ -319,9 +317,6 @@ public class BindingIndependentConnector implements // baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance()); baRpcRegistryImpl.registerGlobalRpcRegistrationListener(domToBindingRpcManager.getInstance()); } - if (biRpcRegistry instanceof org.opendaylight.controller.sal.dom.broker.spi.RpcRouter) { - biRouter = (org.opendaylight.controller.sal.dom.broker.spi.RpcRouter) biRpcRegistry; - } rpcForwarding = true; } } @@ -804,10 +799,10 @@ public class BindingIndependentConnector implements // @Override public Future> forwardToDomBroker(DataObject input) { - if(biRouter != null) { + if(biRpcRegistry != null) { CompositeNode xml = mappingService.toDataDom(input); CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.> of(xml)); - RpcResult result = biRouter.invokeRpc(rpc, wrappedXml); + RpcResult result = biRpcRegistry.invokeRpc(rpc, wrappedXml); Object baResultValue = null; if (result.getResult() != null) { baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), result.getResult()); @@ -867,10 +862,10 @@ public class BindingIndependentConnector implements // @Override public Future> forwardToDomBroker(DataObject input) { - if(biRouter != null) { + if(biRpcRegistry != null) { CompositeNode xml = mappingService.toDataDom(input); CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.>of(xml)); - RpcResult result = biRouter.invokeRpc(rpc, wrappedXml); + RpcResult result = biRpcRegistry.invokeRpc(rpc, wrappedXml); Object baResultValue = null; RpcResult baResult = Rpcs.getRpcResult(result.isSuccessful(), null, result.getErrors()); return Futures.>immediateFuture(baResult); diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java index bfa4f36c18..274f084f01 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java @@ -42,7 +42,7 @@ public class RoutingUtils { private final Map> removal; private final Map> announcement; - public RouteChangeImpl(ImmutableMap> removal, ImmutableMap> announcement) { + public RouteChangeImpl(ImmutableMap> announcement, ImmutableMap> removal) { super(); this.removal = removal; this.announcement = announcement; diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java index 24cb99f8c3..8a9d167865 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java @@ -14,7 +14,7 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; -public interface RpcProvisionRegistry extends BrokerService, RouteChangePublisher { +public interface RpcProvisionRegistry extends RpcImplementation, BrokerService, RouteChangePublisher { /** * Registers an implementation of the rpc. diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend index aa5138a04d..8f734d7d4c 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend @@ -73,7 +73,7 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable { return session; } - protected def Future> invokeRpc(QName rpc, CompositeNode input) { + protected def Future> invokeRpcAsync(QName rpc, CompositeNode input) { val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable>); return result; } @@ -135,5 +135,13 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable { override > registerRouteChangeListener(L listener) { return router.registerRouteChangeListener(listener); } + + override invokeRpc(QName rpc,CompositeNode input){ + return router.invokeRpc(rpc,input) + } + + override getSupportedRpcs() { + return router.getSupportedRpcs(); + } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend index e4808e9bd6..813f52b67d 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend @@ -37,7 +37,7 @@ class ConsumerContextImpl implements ConsumerSession { } override rpc(QName rpc, CompositeNode input) { - return broker.invokeRpc(rpc, input); + return broker.invokeRpcAsync(rpc, input); } override T getService(Class service) { diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java index 5a3e060a3c..a8bdddb510 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java @@ -219,4 +219,6 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv L listener) { return rpcs.registerRouteChangeListener(listener); } + + } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/RpcProvisionRegistryProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/RpcProvisionRegistryProxy.java index e375e14cf2..e218a95782 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/RpcProvisionRegistryProxy.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/RpcProvisionRegistryProxy.java @@ -16,9 +16,13 @@ import org.opendaylight.controller.sal.core.api.RpcRegistrationListener; import org.opendaylight.controller.sal.core.api.RpcRoutingContext; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.osgi.framework.ServiceReference; +import java.util.Set; + public class RpcProvisionRegistryProxy extends AbstractBrokerServiceProxy implements RpcProvisionRegistry { @@ -45,4 +49,15 @@ public class RpcProvisionRegistryProxy extends AbstractBrokerServiceProxy> ListenerRegistration registerRouteChangeListener(L listener) { return getDelegate().registerRouteChangeListener(listener); } + + + @Override + public Set getSupportedRpcs() { + return getDelegate().getSupportedRpcs(); + } + + @Override + public RpcResult invokeRpc(QName rpc, CompositeNode input) { + return getDelegate().invokeRpc(rpc,input); + } } diff --git a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java index fec6bbe6b4..d2016b1f63 100644 --- a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java +++ b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java @@ -48,7 +48,7 @@ public class SimpleBroadcastHandlerImpl implements IBroadcastHandler, IListenDat protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - BroadcastMode mode = BroadcastMode.BROADCAST_TO_NONINTERNAL; + BroadcastMode mode = BroadcastMode.DISABLED; @Override public PacketResult receiveDataPacket(RawPacket inPkt) { diff --git a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java index 19f45e63c5..615bb4df83 100644 --- a/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java +++ b/opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java @@ -1004,7 +1004,8 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa } } - boolean proactiveForwarding = false; + boolean forwardingModeChanged = false; + // copy node properties from config if (nodeConfigList != null) { String nodeId = node.toString(); @@ -1014,7 +1015,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa propMap.putAll(nodeProperties); if (nodeProperties.get(ForwardingMode.name) != null) { ForwardingMode mode = (ForwardingMode) nodeProperties.get(ForwardingMode.name); - proactiveForwarding = mode.isProactive(); + forwardingModeChanged = mode.isProactive(); } } } @@ -1023,28 +1024,35 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa Property defaultMode = new ForwardingMode(ForwardingMode.REACTIVE_FORWARDING); propMap.put(ForwardingMode.name, defaultMode); } - boolean result = false; - if (propMapCurr == null) { - if (nodeProps.putIfAbsent(node, propMap) == null) { - result = true; - } + + boolean propsAdded = false; + // Attempt initial add + if (nodeProps.putIfAbsent(node, propMap) == null) { + propsAdded = true; + + /* Notify listeners only for initial node addition + * to avoid expensive tasks triggered by redundant notifications + */ + notifyNode(node, UpdateType.ADDED, propMap); } else { - result = nodeProps.replace(node, propMapCurr, propMap); + + propsAdded = nodeProps.replace(node, propMapCurr, propMap); + + // check whether forwarding mode changed + if (propMapCurr.get(ForwardingMode.name) != null) { + ForwardingMode mode = (ForwardingMode) propMapCurr.get(ForwardingMode.name); + forwardingModeChanged ^= mode.isProactive(); + } } - if (!result) { - log.debug("Cluster conflict: Conflict while adding the node properties. Node: {} Properties: {}", - node.getID(), props); + if (!propsAdded) { + log.debug("Cluster conflict while adding node {}. Overwriting with latest props: {}", node.getID(), props); addNodeProps(node, propMap); } - // check if span ports are configed + // check if span ports are configured addSpanPorts(node); - - // notify node listeners - notifyNode(node, UpdateType.ADDED, propMap); - // notify proactive mode forwarding - if (proactiveForwarding) { + if (forwardingModeChanged) { notifyModeChange(node, true); } } @@ -1054,7 +1062,12 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa if (nodeProps == null) { return; } - nodeProps.remove(node); + + if (nodeProps.remove(node) == null) { + log.debug("Received redundant node REMOVED udate for {}. Skipping..", node); + return; + } + nodeConnectorNames.remove(node); Set removeNodeConnectorSet = new HashSet(); for (Map.Entry> entry : nodeConnectorProps.entrySet()) { @@ -1149,6 +1162,13 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa switch (type) { case ADDED: + // Skip redundant ADDED update (e.g. cluster switch-over) + if (nodeConnectorProps.containsKey(nodeConnector)) { + log.debug("Redundant nodeconnector ADDED for {}, props {} for container {}", + nodeConnector, props, containerName); + update = false; + } + if (props != null) { for (Property prop : props) { addNodeConnectorProp(nodeConnector, prop); @@ -1158,6 +1178,7 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa addNodeConnectorProp(nodeConnector, null); } + addSpanPort(nodeConnector); break; case CHANGED: @@ -2026,9 +2047,9 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa // only add if span is configured on this nodeConnector for (SpanConfig conf : getSpanConfigList(nodeConnector.getNode())) { if (conf.getPortArrayList().contains(nodeConnector)) { - List ncLists = new ArrayList(); - ncLists.add(nodeConnector); - addSpanPorts(nodeConnector.getNode(), ncLists); + List ncList = new ArrayList(); + ncList.add(nodeConnector); + addSpanPorts(nodeConnector.getNode(), ncList); return; } }