X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fcompatibility%2Fsal-compatibility%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fcompatibility%2FInventoryAndReadAdapter.xtend;h=60e43247c2810383f49b05a24699d14c1c1f355b;hp=8ac6f1b0500d1834fa6883de70a7ae3c6eb601bb;hb=405ea7ce68d22bd3d2501857c5253793b581b086;hpb=4f76ea30ad49331ca38ce63925b3fabf8e769731 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 8ac6f1b050..60e43247c2 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 @@ -1,155 +1,343 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * 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 + */ package org.opendaylight.controller.sal.compatibility -import org.opendaylight.controller.sal.reader.IPluginInReadService -import org.opendaylight.controller.sal.core.NodeConnector +import java.util.ArrayList +import java.util.Collections +import java.util.List +import java.util.Set +import java.util.concurrent.CopyOnWriteArrayList; +import org.opendaylight.controller.sal.binding.api.data.DataBrokerService +import org.opendaylight.controller.sal.binding.api.data.DataProviderService +import org.opendaylight.controller.sal.core.Edge import org.opendaylight.controller.sal.core.Node -import org.opendaylight.controller.sal.flowprogrammer.Flow import org.opendaylight.controller.sal.core.NodeTable -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService - -import static extension org.opendaylight.controller.sal.common.util.Arguments.* -import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* -import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.* +import org.opendaylight.controller.sal.core.UpdateType +import org.opendaylight.controller.sal.flowprogrammer.Flow +import org.opendaylight.controller.sal.inventory.IPluginInInventoryService +import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService +import org.opendaylight.controller.sal.reader.FlowOnNode +import org.opendaylight.controller.sal.reader.IPluginInReadService +import org.opendaylight.controller.sal.reader.IPluginOutReadService +import org.opendaylight.controller.sal.reader.NodeConnectorStatistics +import org.opendaylight.controller.sal.reader.NodeDescription +import org.opendaylight.controller.sal.reader.NodeTableStatistics import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService -import org.opendaylight.controller.sal.reader.NodeConnectorStatistics -import org.opendaylight.controller.sal.reader.FlowOnNode -import org.opendaylight.controller.sal.reader.NodeDescription -import org.slf4j.LoggerFactory -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsInputBuilder -import java.util.ArrayList -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsInputBuilder -import org.opendaylight.controller.sal.inventory.IPluginInInventoryService -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener -import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.Link +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated -import java.util.Collections -import org.opendaylight.controller.sal.core.UpdateType +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatistics +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsInputBuilder +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener +import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.controller.sal.topology.IPluginOutTopologyService -import org.opendaylight.controller.sal.topology.IPluginInTopologyService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryListener -import org.opendaylight.controller.sal.core.Edge -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.Link -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkDiscovered -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkOverutilized -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkRemoved -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkUtilizationNormal -import org.opendaylight.controller.sal.topology.TopoEdgeUpdate -import org.opendaylight.controller.sal.discovery.IDiscoveryService +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.slf4j.LoggerFactory + +import static extension org.opendaylight.controller.sal.common.util.Arguments.* +import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* +import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader +import java.util.concurrent.ConcurrentHashMap +import java.util.Map -class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInReadService, IPluginInInventoryService, OpendaylightInventoryListener, FlowTopologyDiscoveryListener { +class InventoryAndReadAdapter implements IPluginInReadService, + IPluginInInventoryService, + OpendaylightInventoryListener, + OpendaylightFlowStatisticsListener, + OpendaylightFlowTableStatisticsListener, + OpendaylightPortStatisticsListener { private static val LOG = LoggerFactory.getLogger(InventoryAndReadAdapter); + private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue; @Property DataBrokerService dataService; @Property - OpendaylightFlowStatisticsService flowStatisticsService; + DataProviderService dataProviderService; @Property - IPluginOutInventoryService inventoryPublisher; + OpendaylightFlowStatisticsService flowStatisticsService; @Property - IPluginOutTopologyService topologyPublisher; + OpendaylightPortStatisticsService nodeConnectorStatisticsService; @Property - IDiscoveryService discoveryPublisher; + OpendaylightFlowTableStatisticsService flowTableStatisticsService; @Property FlowTopologyDiscoveryService topologyDiscovery; + + @Property + List statisticsPublisher = new CopyOnWriteArrayList(); + + @Property + List inventoryPublisher = new CopyOnWriteArrayList(); + + def setInventoryPublisher(IPluginOutInventoryService listener){ + inventoryPublisher.add(listener); + } + + def unsetInventoryPublisher(IPluginOutInventoryService listener){ + inventoryPublisher.remove(listener); + } + + def setReadPublisher(IPluginOutReadService listener) { + statisticsPublisher.add(listener); + } + + def unsetReadPublisher (IPluginOutReadService listener) { + if( listener != null) + statisticsPublisher.remove(listener); + } + + protected def startChange() { + return dataProviderService.beginTransaction; + } - override getTransmitRate(NodeConnector connector) { + override getTransmitRate(org.opendaylight.controller.sal.core.NodeConnector connector) { val nodeConnector = readFlowCapableNodeConnector(connector.toNodeConnectorRef); return nodeConnector.currentSpeed } override readAllFlow(Node node, boolean cached) { - val input = new GetAllFlowStatisticsInputBuilder; - input.setNode(node.toNodeRef); - val result = flowStatisticsService.getAllFlowStatistics(input.build) - val statistics = result.get.result; val output = new ArrayList(); - for (stat : statistics.flowStatistics) { - // FIXME: Create FlowOnNode - } + 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() + // If we assume that md-sal statistics manager will always be running, then its not required + // But if not, then sending request will collect the latest data for adaptor atleast. + val input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder; + input.setNode(node.toNodeRef); + flowStatisticsService.getAllFlowsStatisticsFromAllFlowTables(input.build) + return output; } override readAllNodeConnector(Node node, boolean cached) { - val input = new GetAllNodeConnectorStatisticsInputBuilder(); + + 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); - val result = flowStatisticsService.getAllNodeConnectorStatistics(input.build()); - val statistics = result.get.result.nodeConnectorStatistics; - val ret = new ArrayList(); - for (stat : statistics) { - ret.add(stat.toNodeConnectorStatistics()) - } + nodeConnectorStatisticsService.getAllNodeConnectorsStatistics(input.build()); return ret; } override readAllNodeTable(Node node, boolean cached) { - throw new UnsupportedOperationException("TODO: auto-generated method stub") + 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); + return ret; } override readDescription(Node node, boolean cached) { - val capableNode = readFlowCapableNode(node.toNodeRef) - - val it = new NodeDescription() - manufacturer = capableNode.manufacturer - serialNumber = capableNode.serialNumber - software = capableNode.software - description = capableNode.description - - return it; - } - - override readFlow(Node node, Flow flow, boolean cached) { - val input = flowStatisticsInput(node, flow); - val output = flowStatisticsService.getFlowStatistics(input); - - try { - val statistics = output.get().getResult(); - if (statistics != null) { - val it = new FlowOnNode(flow); - byteCount = statistics.byteCount.value.longValue - durationNanoseconds = statistics.duration.getNanosecond().getValue().intValue(); - durationSeconds = statistics.duration.getSecond().getValue().intValue(); - packetCount = statistics.getPacketCount().getValue().longValue(); - return it; - } - } catch (Exception e) { - LOG.error("Read flow not processed", e); - } - return null; + 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; + } + } + } + } + + //TODO: Refer TODO (main) + val input = new GetFlowStatisticsFromFlowTableInputBuilder; + input.setNode(node.toNodeRef); + input.fieldsFrom(MDFlowMapping.toMDSalflow(targetFlow)); + flowStatisticsService.getFlowStatisticsFromFlowTable(input.build) + + return ret; + } - override readNodeConnector(NodeConnector connector, boolean cached) { - - val getNodeConnectorStatisticsInput = FromSalConversionsUtils.nodeConnectorStatistics(connector); - val future = flowStatisticsService.getNodeConnectorStatistics(getNodeConnectorStatisticsInput); - try { - val rpcResult = future.get(); - val output = rpcResult.getResult(); - - if (output != null) { - return output.toNodeConnectorStatistics; - } - } catch (Exception e) { - LOG.error("Read node connector not processed", e); - } + 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) + val input = new GetNodeConnectorStatisticsInputBuilder(); + input.setNode(connector.node.toNodeRef); + input.setNodeConnectorId(InventoryMapping.toNodeConnectorKey(connector).id); + nodeConnectorStatisticsService.getNodeConnectorStatistics(input.build()); + return nodeConnectorStatistics; + } - return null; + 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) + val input = new GetFlowTablesStatisticsInputBuilder(); + input.setNode(nodeTable.node.toNodeRef); + flowTableStatisticsService.getFlowTablesStatistics(input.build); + + return nodeStats; } override onNodeConnectorRemoved(NodeConnectorRemoved update) { @@ -157,96 +345,271 @@ class InventoryAndReadAdapter implements IPluginInTopologyService, IPluginInRead } override onNodeRemoved(NodeRemoved notification) { - // NOOP + val properties = Collections.emptySet(); + + publishNodeUpdate(notification.nodeRef.toADNode, UpdateType.REMOVED, properties); } override onNodeConnectorUpdated(NodeConnectorUpdated update) { - val properties = Collections.emptySet(); - inventoryPublisher.updateNodeConnector(update.nodeConnectorRef.toADNodeConnector, UpdateType.CHANGED, properties); + var updateType = UpdateType.CHANGED; + if ( this._dataService.readOperationalData(update.nodeConnectorRef.value as InstanceIdentifier) == null ){ + updateType = UpdateType.ADDED; + } + + var nodeConnector = update.nodeConnectorRef.toADNodeConnector + + publishNodeConnectorUpdate(nodeConnector , updateType , update.toADNodeConnectorProperties); } override onNodeUpdated(NodeUpdated notification) { - val properties = Collections.emptySet(); - inventoryPublisher.updateNode(notification.nodeRef.toADNode, UpdateType.CHANGED, properties); + val InstanceIdentifier identifier = notification.nodeRef.value as InstanceIdentifier; + + var updateType = UpdateType.CHANGED; + if ( this._dataService.readOperationalData(identifier) == null ){ + updateType = UpdateType.ADDED; + } + publishNodeUpdate(notification.nodeRef.toADNode, updateType, notification.toADNodeProperties); + + //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 description = notification.nodeRef.toNodeDescription + if(description != null) { + statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,description); + } + } } override getNodeProps() { - - // FIXME: Read from MD-SAL inventory service - return null; + val props = new ConcurrentHashMap>() + + val nodes = readAllMDNodes() + for (node : nodes.node ) { + val fcn = node.getAugmentation(FlowCapableNode) + if(fcn != null) { + val perNodeProps = fcn.toADNodeProperties(node.id) + val perNodePropMap = new ConcurrentHashMap + if(perNodeProps != null ) { + for(perNodeProp : perNodeProps) { + perNodePropMap.put(perNodeProp.name,perNodeProp) + } + } + props.put(new Node(MD_SAL_TYPE, node.id.toADNodeId),perNodePropMap) + } + } + return props; } - - override getNodeConnectorProps(Boolean refresh) { - - // FIXME: Read from MD-SAL Invcentory Service - return null; + + private def readAllMDNodes() { + val nodesRef = InstanceIdentifier.builder(Nodes) + .toInstance + val reader = TypeSafeDataReader.forReader(dataService) + return reader.readOperationalData(nodesRef) + } + + private def readAllMDNodeConnectors(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node) { + val nodeRef = InstanceIdentifier.builder(Nodes) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(node.id)) + .toInstance + val reader = TypeSafeDataReader.forReader(dataService) + return reader.readOperationalData(nodeRef).nodeConnector } - override readNodeTable(NodeTable table, boolean cached) { - throw new UnsupportedOperationException("TODO: auto-generated method stub") + override getNodeConnectorProps(Boolean refresh) { + // Note, because the MD-SAL has a unified data store, we can ignore the Boolean refresh, as we have no secondary + // data store to refresh from + val props = new ConcurrentHashMap>() + val nodes = readAllMDNodes() + for (node : nodes.node) { + val ncs = node.readAllMDNodeConnectors + if(ncs != null) { + for( nc : ncs ) { + val fcnc = nc.getAugmentation(FlowCapableNodeConnector) + if(fcnc != null) { + val ncps = fcnc.toADNodeConnectorProperties + val ncpsm = new ConcurrentHashMap + if(ncps != null) { + for(p : ncps) { + ncpsm.put(p.name,p) + } + } + props.put(nc.id.toADNodeConnector(node.id),ncpsm) + } + } + } + } + return props } private def FlowCapableNode readFlowCapableNode(NodeRef ref) { val dataObject = dataService.readOperationalData(ref.value as InstanceIdentifier); - val node = dataObject.checkInstanceOf( - org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node); - return node.getAugmentation(FlowCapableNode); + if(dataObject != null) { + val node = dataObject.checkInstanceOf( + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node); + return node.getAugmentation(FlowCapableNode); + } + return null; } private def FlowCapableNodeConnector readFlowCapableNodeConnector(NodeConnectorRef ref) { val dataObject = dataService.readOperationalData(ref.value as InstanceIdentifier); val node = dataObject.checkInstanceOf( - org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector); + NodeConnector); return node.getAugmentation(FlowCapableNodeConnector); } - private static def toNodeConnectorStatistics( - org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics output) { - val it = new NodeConnectorStatistics - - collisionCount = output.getCollisionCount().longValue(); - receiveCRCErrorCount = output.getReceiveCrcError().longValue(); - receiveFrameErrorCount = output.getReceiveFrameError().longValue(); - receiveOverRunErrorCount = output.getReceiveOverRunError().longValue(); - - receiveDropCount = output.getReceiveDrops().longValue(); - receiveErrorCount = output.getReceiveErrors().longValue(); - receivePacketCount = output.getPackets().getReceived().longValue(); - receiveByteCount = output.getBytes().getReceived().longValue(); - - transmitDropCount = output.getTransmitDrops().longValue(); - transmitErrorCount = output.getTransmitErrors().longValue(); - transmitPacketCount = output.getPackets().getTransmitted().longValue(); - transmitByteCount = output.getBytes().getTransmitted().longValue(); - return it; + 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; } - override sollicitRefresh() { - topologyDiscovery.solicitRefresh - } - - override onLinkDiscovered(LinkDiscovered notification) { - val update = new TopoEdgeUpdate(notification.toADEdge,Collections.emptySet(),UpdateType.ADDED); - discoveryPublisher.notifyEdge(notification.toADEdge,UpdateType.ADDED,Collections.emptySet()); - topologyPublisher.edgeUpdate(Collections.singletonList(update)) - } - - override onLinkOverutilized(LinkOverutilized notification) { - topologyPublisher.edgeOverUtilized(notification.toADEdge) - } - - override onLinkRemoved(LinkRemoved notification) { - val update = new TopoEdgeUpdate(notification.toADEdge,Collections.emptySet(),UpdateType.REMOVED); - topologyPublisher.edgeUpdate(Collections.singletonList(update)) - } - - override onLinkUtilizationNormal(LinkUtilizationNormal notification) { - topologyPublisher.edgeUtilBackToNormal(notification.toADEdge) - } + 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 + serialNumber = capableNode.serialNumber + software = capableNode.software + description = capableNode.description + + return it; + } + return null; + } def Edge toADEdge(Link link) { new Edge(link.source.toADNodeConnector,link.destination.toADNodeConnector) } - + + /* + * 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() { + 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); + } + } }