From 2c74d3b1109043024a1e251766ed6fcc39ffedf1 Mon Sep 17 00:00:00 2001 From: shweta Date: Tue, 2 Apr 2019 14:23:46 +0200 Subject: [PATCH] Prepare NetworkModel to support ordm 2.2.x devices Adapt topology modifications from change 80051 https://git.opendaylight.org/gerrit/#/c/80051/ They initially supported 2.2 openroadm devices and have been adapted to support openroadm 2.2.1 devices. Change-Id: Ia659c19b4f695d2054c0757b101d9e895108f957 Signed-off-by: Gilles Thouenon Co-authored-by: Gilles Thouenon Co-authored-by: Christophe Betoule --- .../OpenRoadmInterfacesImpl.java | 3 +- .../networkmodel/NetConfTopologyListener.java | 35 +- .../networkmodel/NetworkModelProvider.java | 29 +- .../networkmodel/NetworkUtilsImpl.java | 24 +- .../transportpce/networkmodel/OrdLink.java | 21 +- .../networkmodel/R2RLinkDiscovery.java | 70 +- .../networkmodel/Rdm2XpdrLink.java | 48 +- .../networkmodel/listeners/LldpListener.java | 14 +- .../service/NetworkModelService.java | 10 +- .../service/NetworkModelServiceImpl.java | 196 ++-- .../networkmodel/util/ClliNetwork.java | 24 +- .../networkmodel/util/InfoSubtree.java | 143 +++ .../networkmodel/util/LinkIdUtil.java | 1 + .../networkmodel/util/OpenRoadmFactory.java | 60 ++ .../networkmodel/util/OpenRoadmNetwork.java | 62 +- ...opology.java => OpenRoadmTopology121.java} | 321 +++---- .../util/OpenRoadmTopology22.java | 862 ++++++++++++++++++ .../networkmodel/util/TopologyUtils.java | 124 +++ .../blueprint/networkmodel-blueprint.xml | 37 +- 19 files changed, 1639 insertions(+), 445 deletions(-) create mode 100644 networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/InfoSubtree.java create mode 100644 networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmFactory.java rename networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/{OpenRoadmTopology.java => OpenRoadmTopology121.java} (77%) create mode 100644 networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology22.java create mode 100644 networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/TopologyUtils.java diff --git a/common/src/main/java/org/opendaylight/transportpce/common/openroadminterfaces/OpenRoadmInterfacesImpl.java b/common/src/main/java/org/opendaylight/transportpce/common/openroadminterfaces/OpenRoadmInterfacesImpl.java index 1a74081b0..75cc1c6d6 100644 --- a/common/src/main/java/org/opendaylight/transportpce/common/openroadminterfaces/OpenRoadmInterfacesImpl.java +++ b/common/src/main/java/org/opendaylight/transportpce/common/openroadminterfaces/OpenRoadmInterfacesImpl.java @@ -29,7 +29,8 @@ public class OpenRoadmInterfacesImpl implements OpenRoadmInterfaces { MappingUtils mappingUtils; public OpenRoadmInterfacesImpl(DeviceTransactionManager deviceTransactionManager, MappingUtils mappingUtils, - OpenRoadmInterfacesImpl121 openRoadmInterfacesImpl121, OpenRoadmInterfacesImpl221 openRoadmInterfacesImpl221) { + OpenRoadmInterfacesImpl121 openRoadmInterfacesImpl121, + OpenRoadmInterfacesImpl221 openRoadmInterfacesImpl221) { this.deviceTransactionManager = deviceTransactionManager; this.mappingUtils = mappingUtils; this.openRoadmInterfacesImpl121 = openRoadmInterfacesImpl121; diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java index 58830f511..5dca0d67f 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java @@ -37,15 +37,12 @@ import org.opendaylight.transportpce.networkmodel.listeners.DeOperationsListener import org.opendaylight.transportpce.networkmodel.listeners.DeOperationsListener221; import org.opendaylight.transportpce.networkmodel.listeners.DeviceListener; import org.opendaylight.transportpce.networkmodel.listeners.DeviceListener221; -import org.opendaylight.transportpce.networkmodel.listeners.LldpListener; -import org.opendaylight.transportpce.networkmodel.listeners.LldpListener221; import org.opendaylight.transportpce.networkmodel.listeners.TcaListener; import org.opendaylight.transportpce.networkmodel.listeners.TcaListener221; import org.opendaylight.transportpce.networkmodel.service.NetworkModelService; import org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev161014.OrgOpenroadmAlarmListener; import org.opendaylight.yang.gen.v1.http.org.openroadm.de.operations.rev161014.OrgOpenroadmDeOperationsListener; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceListener; -import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.OrgOpenroadmLldpListener; import org.opendaylight.yang.gen.v1.http.org.openroadm.tca.rev161014.OrgOpenroadmTcaListener; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInputBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService; @@ -66,16 +63,16 @@ public class NetConfTopologyListener implements DataTreeChangeListener { private static final Logger LOG = LoggerFactory.getLogger(NetConfTopologyListener.class); private final NetworkModelService networkModelService; - private final R2RLinkDiscovery linkDiscovery; + //private final R2RLinkDiscovery linkDiscovery; private final DataBroker dataBroker; private final DeviceTransactionManager deviceTransactionManager; private final Map registrations; private final Map registrations22; public NetConfTopologyListener(final NetworkModelService networkModelService, final DataBroker dataBroker, - final R2RLinkDiscovery linkDiscovery, DeviceTransactionManager deviceTransactionManager) { + DeviceTransactionManager deviceTransactionManager) { this.networkModelService = networkModelService; - this.linkDiscovery = linkDiscovery; + //this.linkDiscovery = linkDiscovery; this.dataBroker = dataBroker; this.deviceTransactionManager = deviceTransactionManager; this.registrations = new ConcurrentHashMap<>(); @@ -120,10 +117,10 @@ public class NetConfTopologyListener implements DataTreeChangeListener { final ListenerRegistration accessDeviceNotificationListenerRegistration = notificationService.get().registerNotificationListener(deviceListener); - final OrgOpenroadmLldpListener lldpListener = new LldpListener(this.linkDiscovery, nodeId); - LOG.info("Registering notification listener on OrgOpenroadmLldpListener for node: {}", nodeId); - final ListenerRegistration accessLldpNotificationListenerRegistration = - notificationService.get().registerNotificationListener(lldpListener); +// final OrgOpenroadmLldpListener lldpListener = new LldpListener(this.linkDiscovery, nodeId); +// LOG.info("Registering notification listener on OrgOpenroadmLldpListener for node: {}", nodeId); +// final ListenerRegistration accessLldpNotificationListenerRegistration = +// notificationService.get().registerNotificationListener(lldpListener); final OrgOpenroadmTcaListener tcaListener = new TcaListener(); LOG.info("Registering notification listener on OrgOpenroadmTcaListener for node: {}", nodeId); @@ -180,12 +177,12 @@ public class NetConfTopologyListener implements DataTreeChangeListener { .OrgOpenroadmDeviceListener> accessDeviceNotificationListenerRegistration = notificationService.get().registerNotificationListener(deviceListener); - final org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev181019.OrgOpenroadmLldpListener - lldpListener = new LldpListener221(linkDiscovery, nodeId); - LOG.info("Registering notification listener on OrgOpenroadmLldpListener for node: {}", nodeId); - final ListenerRegistration accessLldpNotificationListenerRegistration = - notificationService.get().registerNotificationListener(lldpListener); +// final org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev181019.OrgOpenroadmLldpListener +// lldpListener = new LldpListener221(linkDiscovery, nodeId); +// LOG.info("Registering notification listener on OrgOpenroadmLldpListener for node: {}", nodeId); +// final ListenerRegistration accessLldpNotificationListenerRegistration = +// notificationService.get().registerNotificationListener(lldpListener); final org.opendaylight.yang.gen.v1.http.org.openroadm.tca.rev181019.OrgOpenroadmTcaListener tcaListener = new TcaListener221(); @@ -218,7 +215,7 @@ public class NetConfTopologyListener implements DataTreeChangeListener { NodeRegistration22 nodeRegistration22 = new NodeRegistration22(nodeId, accessAlarmNotificationListenerRegistration, accessDeOperationasNotificationListenerRegistration, accessDeviceNotificationListenerRegistration, - accessLldpNotificationListenerRegistration, accessTcaNotificationListenerRegistration); + null, accessTcaNotificationListenerRegistration); registrations22.put(nodeId, nodeRegistration22); } @@ -251,7 +248,7 @@ public class NetConfTopologyListener implements DataTreeChangeListener { if (rootNode.getDataBefore() != null) { String nodeId = rootNode.getDataBefore().key().getNodeId().getValue(); LOG.info("Node {} deleted", nodeId); - this.networkModelService.deleteOpenROADMnode(nodeId); + this.networkModelService.deleteOpenRoadmnode(nodeId); onDeviceDisConnected(nodeId); } else { LOG.error("rootNode.getDataBefore is null !"); @@ -284,7 +281,7 @@ public class NetConfTopologyListener implements DataTreeChangeListener { break; case Connecting: case UnableToConnect: - this.networkModelService.setOpenROADMnodeStatus(nodeId, connectionStatus); + this.networkModelService.setOpenRoadmNodeStatus(nodeId, connectionStatus); onDeviceDisConnected(nodeId); break; default: diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkModelProvider.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkModelProvider.java index ff946da7d..9680c3784 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkModelProvider.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkModelProvider.java @@ -13,9 +13,10 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.transportpce.common.InstanceIdentifiers; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.networkmodel.util.ClliNetwork; +import org.opendaylight.transportpce.networkmodel.util.OpenRoadmFactory; import org.opendaylight.transportpce.networkmodel.util.OpenRoadmNetwork; -import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.TransportpceNetworkutilsService; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yangtools.concepts.ListenerRegistration; @@ -26,22 +27,25 @@ public class NetworkModelProvider { private static final Logger LOG = LoggerFactory.getLogger(NetworkModelProvider.class); + private NetworkTransactionService networkTransactionService; private final DataBroker dataBroker; private final RpcProviderRegistry rpcProviderRegistry; private final TransportpceNetworkutilsService networkutilsService; private final NetConfTopologyListener topologyListener; - private final OpenRoadmTopology openRoadmTopology; + private final OpenRoadmFactory openRoadmFactory; private ListenerRegistration dataTreeChangeListenerRegistration; private BindingAwareBroker.RpcRegistration networkutilsServiceRpcRegistration; - public NetworkModelProvider(final DataBroker dataBroker, final RpcProviderRegistry rpcProviderRegistry, + public NetworkModelProvider(NetworkTransactionService networkTransactionService, + final DataBroker dataBroker, final RpcProviderRegistry rpcProviderRegistry, final TransportpceNetworkutilsService networkutilsService, final NetConfTopologyListener topologyListener, - OpenRoadmTopology openRoadmTopology) { + OpenRoadmFactory openRoadmFactory) { + this.networkTransactionService = networkTransactionService; this.dataBroker = dataBroker; this.rpcProviderRegistry = rpcProviderRegistry; this.networkutilsService = networkutilsService; this.topologyListener = topologyListener; - this.openRoadmTopology = openRoadmTopology; + this.openRoadmFactory = openRoadmFactory; } /** @@ -51,17 +55,18 @@ public class NetworkModelProvider { LOG.info("NetworkModelProvider Session Initiated"); ClliNetwork.createClliLayer(dataBroker); OpenRoadmNetwork.createOpenRoadmNetworkLayer(dataBroker); - openRoadmTopology.createTopoLayer(dataBroker); + openRoadmFactory.createTopoLayerVersionControl(networkTransactionService); dataTreeChangeListenerRegistration = - dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, - InstanceIdentifiers.NETCONF_TOPOLOGY_II.child(Node.class)), topologyListener); + dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, + InstanceIdentifiers.NETCONF_TOPOLOGY_II.child(Node.class)), topologyListener); networkutilsServiceRpcRegistration = - rpcProviderRegistry.addRpcImplementation(TransportpceNetworkutilsService.class, networkutilsService); + rpcProviderRegistry.addRpcImplementation(TransportpceNetworkutilsService.class, networkutilsService); } - /** - * Method called when the blueprint container is destroyed. - */ + + /** + * Method called when the blueprint container is destroyed. + */ public void close() { LOG.info("NetworkModelProvider Closed"); if (dataTreeChangeListenerRegistration != null) { diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkUtilsImpl.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkUtilsImpl.java index afadd0ff5..4f57a042c 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkUtilsImpl.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetworkUtilsImpl.java @@ -9,13 +9,14 @@ package org.opendaylight.transportpce.networkmodel; import com.google.common.base.Optional; import com.google.common.util.concurrent.ListenableFuture; + import java.util.concurrent.ExecutionException; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; -import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology; +import org.opendaylight.transportpce.networkmodel.util.OpenRoadmFactory; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.DeleteLinkInput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.DeleteLinkOutput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.DeleteLinkOutputBuilder; @@ -46,11 +47,11 @@ public class NetworkUtilsImpl implements TransportpceNetworkutilsService { private static final Logger LOG = LoggerFactory.getLogger(NetworkUtilsImpl.class); private final DataBroker dataBroker; - private final OpenRoadmTopology openRoadmTopology; + private final OpenRoadmFactory openRoadmFactory; - public NetworkUtilsImpl(DataBroker dataBroker, OpenRoadmTopology openRoadmTopology) { + public NetworkUtilsImpl(DataBroker dataBroker, OpenRoadmFactory openRoadmFactory) { this.dataBroker = dataBroker; - this.openRoadmTopology = openRoadmTopology; + this.openRoadmFactory = openRoadmFactory; } @Override @@ -58,9 +59,11 @@ public class NetworkUtilsImpl implements TransportpceNetworkutilsService { LinkId linkId = new LinkId(input.getLinkId()); // Building link instance identifier - InstanceIdentifier.InstanceIdentifierBuilder linkIID = InstanceIdentifier.builder(Network.class, - new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) - .augmentation(Network1.class).child(Link.class, new LinkKey(linkId)); + InstanceIdentifier.InstanceIdentifierBuilder linkIID = InstanceIdentifier + .builder(Network.class, + new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .augmentation(Network1.class).child(Link.class, new LinkKey(linkId)); + //Check if link exists try { @@ -100,7 +103,7 @@ public class NetworkUtilsImpl implements TransportpceNetworkutilsService { @Override public ListenableFuture> initRoadmNodes(InitRoadmNodesInput input) { boolean createRdmLinks = OrdLink.createRdm2RdmLinks(input, - this.openRoadmTopology,this.dataBroker); + this.openRoadmFactory,this.dataBroker); if (createRdmLinks) { return RpcResultBuilder .success(new InitRoadmNodesOutputBuilder().setResult( @@ -114,8 +117,9 @@ public class NetworkUtilsImpl implements TransportpceNetworkutilsService { @Override public ListenableFuture> initXpdrRdmLinks(InitXpdrRdmLinksInput input) { // Assigns user provided input in init-network-view RPC to nodeId + LOG.info("Xpdr to Roadm links rpc called"); boolean createXpdrRdmLinks = Rdm2XpdrLink.createXpdrRdmLinks(input.getLinksInput(), - this.openRoadmTopology,this.dataBroker); + this.openRoadmFactory,this.dataBroker); if (createXpdrRdmLinks) { return RpcResultBuilder .success(new InitXpdrRdmLinksOutputBuilder().setResult("Xponder Roadm Link created successfully")) @@ -128,7 +132,7 @@ public class NetworkUtilsImpl implements TransportpceNetworkutilsService { @Override public ListenableFuture> initRdmXpdrLinks(InitRdmXpdrLinksInput input) { boolean createRdmXpdrLinks = Rdm2XpdrLink.createRdmXpdrLinks(input.getLinksInput(), - this.openRoadmTopology,this.dataBroker); + this.openRoadmFactory,this.dataBroker); if (createRdmXpdrLinks) { return RpcResultBuilder .success(new InitRdmXpdrLinksOutputBuilder().setResult("Roadm Xponder links created successfully")) diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/OrdLink.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/OrdLink.java index 1f83df4f5..3bbd15147 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/OrdLink.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/OrdLink.java @@ -14,7 +14,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; import org.opendaylight.transportpce.networkmodel.util.LinkIdUtil; -import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology; +import org.opendaylight.transportpce.networkmodel.util.OpenRoadmFactory; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.InitRoadmNodesInput; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1Builder; @@ -37,48 +37,47 @@ final class OrdLink { private static final Logger LOG = LoggerFactory.getLogger(OrdLink.class); /**Method to create OMS links if not discovered by LLDP. This is helpful - to create test topologies using simulators**/ + to create test topologies using simulators**/ public static boolean createRdm2RdmLinks(InitRoadmNodesInput input, - OpenRoadmTopology openRoadmTopology, DataBroker dataBroker) { + OpenRoadmFactory openRoadmFactory, DataBroker dataBroker) { LinkId oppositeLinkId = LinkIdUtil.getRdm2RdmOppositeLinkId(input); //For setting up attributes for openRoadm augment Link1Builder link1Builder = new Link1Builder(); - link1Builder.setLinkType(OpenroadmLinkType.ROADMTOROADM); OMSAttributesBuilder omsAttributesBuilder = new OMSAttributesBuilder(); omsAttributesBuilder.setOppositeLink(oppositeLinkId); link1Builder.setOMSAttributes(omsAttributesBuilder.build()); //For opposite link augment org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder oppsiteLinkBuilder = - new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); oppsiteLinkBuilder.setOppositeLink(oppositeLinkId); - + link1Builder.setLinkType(OpenroadmLinkType.ROADMTOROADM); String srcNode = new StringBuilder(input.getRdmANode()).append("-DEG").append(input.getDegANum()).toString(); String srcTp = input.getTerminationPointA(); String destNode = new StringBuilder(input.getRdmZNode()).append("-DEG").append(input.getDegZNum()).toString(); String destTp = input.getTerminationPointZ(); //IETF link builder - LinkBuilder linkBuilder = openRoadmTopology.createLink(srcNode, destNode, srcTp, destTp); + LinkBuilder linkBuilder = openRoadmFactory.createLink(srcNode, destNode, srcTp, destTp); linkBuilder.addAugmentation(Link1.class,link1Builder.build()); - linkBuilder.addAugmentation(org.opendaylight.yang.gen.v1.http - .org.openroadm.opposite.links.rev170929.Link1.class,oppsiteLinkBuilder.build()); + linkBuilder.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1 + .class, oppsiteLinkBuilder.build()); LinkId linkId = LinkIdUtil.buildLinkId(srcNode, srcTp, destNode, destTp); // Building link instance identifier InstanceIdentifier.InstanceIdentifierBuilder linkIID = InstanceIdentifier.builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) - .augmentation(Network1.class).child(Link.class, new LinkKey(linkId)); + .augmentation(Network1.class).child(Link.class, new LinkKey(linkId)); WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, linkIID.build(), linkBuilder.build()); try { writeTransaction.submit().get(); LOG.info("A new link with linkId: {} added into {} layer.", - linkId.getValue(), NetworkUtils.OVERLAY_NETWORK_ID); + linkId.getValue(), NetworkUtils.OVERLAY_NETWORK_ID); return true; } catch (InterruptedException | ExecutionException e) { LOG.warn("Failed to create Roadm 2 Roadm Link for topo layer "); diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/R2RLinkDiscovery.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/R2RLinkDiscovery.java index e7784647e..1bd71a616 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/R2RLinkDiscovery.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/R2RLinkDiscovery.java @@ -18,8 +18,9 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.transportpce.common.Timeouts; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces; -import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology; +import org.opendaylight.transportpce.networkmodel.util.OpenRoadmFactory; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.InitRoadmNodesInputBuilder; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev170228.Network; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev170228.network.Nodes; @@ -42,24 +43,27 @@ public class R2RLinkDiscovery { private static final Logger LOG = LoggerFactory.getLogger(R2RLinkDiscovery.class); private final DataBroker dataBroker; + private final NetworkTransactionService networkTransactionService; private final DeviceTransactionManager deviceTransactionManager; - private final OpenRoadmTopology openRoadmTopology; + private final OpenRoadmFactory openRoadmFactory; private final OpenRoadmInterfaces openRoadmInterfaces; public R2RLinkDiscovery(final DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager, - OpenRoadmTopology openRoadmTopology, OpenRoadmInterfaces openRoadmInterfaces) { + OpenRoadmFactory openRoadmFactory, OpenRoadmInterfaces openRoadmInterfaces, + NetworkTransactionService networkTransactionService) { this.dataBroker = dataBroker; this.deviceTransactionManager = deviceTransactionManager; - this.openRoadmTopology = openRoadmTopology; + this.openRoadmFactory = openRoadmFactory; this.openRoadmInterfaces = openRoadmInterfaces; + this.networkTransactionService = networkTransactionService; } public boolean readLLDP(NodeId nodeId) { InstanceIdentifier protocolsIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(Protocols.class); + .child(Protocols.class); Optional protocolObject = this.deviceTransactionManager.getDataFromDevice(nodeId.getValue(), - LogicalDatastoreType.OPERATIONAL, protocolsIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); + LogicalDatastoreType.OPERATIONAL, protocolsIID, Timeouts.DEVICE_READ_TIMEOUT, + Timeouts.DEVICE_READ_TIMEOUT_UNIT); if (!protocolObject.isPresent() || (protocolObject.get().augmentation(Protocols1.class) == null)) { LOG.warn("LLDP subtree is missing : isolated openroadm device"); return false; @@ -69,7 +73,7 @@ public class R2RLinkDiscovery { for (IfName ifName : nbrList.getIfName()) { if (ifName.getRemoteSysName() == null) { LOG.warn("LLDP subtree neighbour is empty for nodeId: {}, ifName: {}", - nodeId.getValue(),ifName.getIfName()); + nodeId.getValue(),ifName.getIfName()); } else { Optional mps = this.deviceTransactionManager.getDeviceMountPoint(ifName.getRemoteSysName()); if (!mps.isPresent()) { @@ -79,7 +83,7 @@ public class R2RLinkDiscovery { // the neighbor node. } else { if (!createR2RLink(nodeId, ifName.getIfName(), ifName.getRemoteSysName(), - ifName.getRemotePortId())) { + ifName.getRemotePortId())) { LOG.error("Link Creation failed between {} and {} nodes.", nodeId, ifName.getRemoteSysName()); return false; } @@ -91,14 +95,14 @@ public class R2RLinkDiscovery { public Direction getDegreeDirection(Integer degreeCounter, NodeId nodeId) { InstanceIdentifier nodesIID = InstanceIdentifier.builder(Network.class) - .child(Nodes.class, new NodesKey(nodeId.getValue())).build(); + .child(Nodes.class, new NodesKey(nodeId.getValue())).build(); try (ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction()) { Optional nodesObject = readTx.read(LogicalDatastoreType.CONFIGURATION, nodesIID) - .get().toJavaUtil(); + .get().toJavaUtil(); if (nodesObject.isPresent() && (nodesObject.get().getMapping() != null)) { List mappingList = nodesObject.get().getMapping(); mappingList = mappingList.stream().filter(mp -> mp.getLogicalConnectionPoint().contains("DEG" - + degreeCounter)).collect(Collectors.toList()); + + degreeCounter)).collect(Collectors.toList()); if (mappingList.size() == 1) { return Direction.Bidirectional; } else if (mappingList.size() > 1) { @@ -166,26 +170,26 @@ public class R2RLinkDiscovery { nodeId.getValue(), srcDegId, srcTpTx, destNodeId, destDegId, destTpRx); InitRoadmNodesInputBuilder r2rlinkBuilderAToZ = new InitRoadmNodesInputBuilder(); r2rlinkBuilderAToZ.setRdmANode(nodeId.getValue()).setDegANum(srcDegId.shortValue()) - .setTerminationPointA(srcTpTx).setRdmZNode(destNodeId.getValue()).setDegZNum(destDegId.shortValue()) - .setTerminationPointZ(destTpRx); - if (!OrdLink.createRdm2RdmLinks(r2rlinkBuilderAToZ.build(), this.openRoadmTopology, this.dataBroker)) { + .setTerminationPointA(srcTpTx).setRdmZNode(destNodeId.getValue()).setDegZNum(destDegId.shortValue()) + .setTerminationPointZ(destTpRx); + if (!OrdLink.createRdm2RdmLinks(r2rlinkBuilderAToZ.build(), this.openRoadmFactory, this.dataBroker)) { LOG.error("OMS Link creation failed between node: {} and nodeId: {} in A->Z direction", nodeId.getValue(), - destNodeId.getValue()); + destNodeId.getValue()); return false; } // Z->A LOG.debug( - "Found a neighbor SrcNodeId: {} , SrcDegId: {}" - + ", SrcTPId: {}, DestNodeId:{} , DestDegId: {}, DestTPId: {}", - destNodeId, destDegId, destTpTx, nodeId.getValue(), srcDegId, srcTpRx); + "Found a neighbor SrcNodeId: {} , SrcDegId: {}" + + ", SrcTPId: {}, DestNodeId:{} , DestDegId: {}, DestTPId: {}", + destNodeId, destDegId, destTpTx, nodeId.getValue(), srcDegId, srcTpRx); InitRoadmNodesInputBuilder r2rlinkBuilderZToA = new InitRoadmNodesInputBuilder(); r2rlinkBuilderZToA.setRdmANode(destNodeId.getValue()).setDegANum(destDegId.shortValue()) - .setTerminationPointA(destTpTx).setRdmZNode(nodeId.getValue()).setDegZNum(srcDegId.shortValue()) - .setTerminationPointZ(srcTpRx); - if (!OrdLink.createRdm2RdmLinks(r2rlinkBuilderZToA.build(), this.openRoadmTopology, this.dataBroker)) { + .setTerminationPointA(destTpTx).setRdmZNode(nodeId.getValue()).setDegZNum(srcDegId.shortValue()) + .setTerminationPointZ(srcTpRx); + if (!OrdLink.createRdm2RdmLinks(r2rlinkBuilderZToA.build(), this.openRoadmFactory, this.dataBroker)) { LOG.error("OMS Link creation failed between node: {} and nodeId: {} in Z->A direction", - destNodeId.getValue(), nodeId.getValue()); + destNodeId.getValue(), nodeId.getValue()); return false; } return true; @@ -236,22 +240,24 @@ public class R2RLinkDiscovery { destTpTx = "DEG" + destDegId + "-TTP-TX"; destTpRx = "DEG" + destDegId + "-TTP-RX"; } - return this.openRoadmTopology.deleteLink(nodeId.getValue(), destNodeId.getValue(), - srcDegId, destDegId, srcTpTx, destTpRx) - && this.openRoadmTopology.deleteLink(destNodeId.getValue(), nodeId.getValue(), - destDegId, srcDegId, destTpTx, srcTpRx); + return this.openRoadmFactory.deleteLink(nodeId.getValue() + "-" + srcDegId.toString(), + destNodeId.getValue() + "-" + destDegId.toString(), + srcTpTx.toString(), destTpRx.toString(),networkTransactionService) + && this.openRoadmFactory.deleteLink(destNodeId.getValue() + "-" + destDegId.toString(), + nodeId.getValue() + "-" + srcDegId.toString(), destTpTx, srcTpRx, + networkTransactionService); } private Integer getDegFromInterface(NodeId nodeId, String interfaceName) { InstanceIdentifier nodesIID = InstanceIdentifier.builder(Network.class) - .child(Nodes.class, new NodesKey(nodeId.getValue())).build(); + .child(Nodes.class, new NodesKey(nodeId.getValue())).build(); try (ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction()) { Optional nodesObject = readTx.read(LogicalDatastoreType.CONFIGURATION, nodesIID) - .get().toJavaUtil(); + .get().toJavaUtil(); if (nodesObject.isPresent() && (nodesObject.get().getCpToDegree() != null)) { List cpToDeg = nodesObject.get().getCpToDegree(); Stream cpToDegStream = cpToDeg.stream().filter(cp -> cp.getInterfaceName() != null) - .filter(cp -> cp.getInterfaceName().equals(interfaceName)); + .filter(cp -> cp.getInterfaceName().equals(interfaceName)); if (cpToDegStream != null) { Optional firstCpToDegree = cpToDegStream.findFirst(); if (firstCpToDegree.isPresent() && (firstCpToDegree != null)) { @@ -263,11 +269,11 @@ public class R2RLinkDiscovery { } } else { LOG.warn("CircuitPack stream couldnt find anything for nodeId: {} and interfaceName: {}", - nodeId.getValue(),interfaceName); + nodeId.getValue(),interfaceName); } } else { LOG.warn("Could not find mapping for Interface {} for nodeId {}", interfaceName, - nodeId.getValue()); + nodeId.getValue()); } } catch (InterruptedException | ExecutionException ex) { LOG.error("Unable to read mapping for Interface : {} for nodeId {}", interfaceName, nodeId, ex); diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/Rdm2XpdrLink.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/Rdm2XpdrLink.java index 9b748824f..192a3eef9 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/Rdm2XpdrLink.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/Rdm2XpdrLink.java @@ -15,10 +15,12 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.transportpce.common.NetworkUtils; -import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology; +import org.opendaylight.transportpce.networkmodel.util.LinkIdUtil; +import org.opendaylight.transportpce.networkmodel.util.OpenRoadmFactory; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.links.input.grouping.LinksInput; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1Builder; +//import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1Builder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmLinkType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkBuilder; @@ -31,23 +33,25 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + final class Rdm2XpdrLink { private static final Logger LOG = LoggerFactory.getLogger(Rdm2XpdrLink.class); - public static boolean createXpdrRdmLinks(LinksInput linksInput, OpenRoadmTopology openRoadmTopology, - DataBroker dataBroker) { + public static boolean createXpdrRdmLinks(LinksInput linksInput, OpenRoadmFactory openRoadmFactory, + DataBroker dataBroker) { String srcNode = - new StringBuilder(linksInput.getXpdrNode()).append("-XPDR").append(linksInput.getXpdrNum()).toString(); + new StringBuilder(linksInput.getXpdrNode()).append("-XPDR").append(linksInput.getXpdrNum()).toString(); String srcTp = new StringBuilder("XPDR").append(linksInput.getXpdrNum()).append("-NETWORK") - .append(linksInput.getNetworkNum()).toString(); + .append(linksInput.getNetworkNum()).toString(); String destNode = - new StringBuilder(linksInput.getRdmNode()).append("-SRG").append(linksInput.getSrgNum()).toString(); + new StringBuilder(linksInput.getRdmNode()).append("-SRG").append(linksInput.getSrgNum()).toString(); String destTp = linksInput.getTerminationPointNum(); Network topoNetowkLayer = createNetworkBuilder(srcNode, srcTp, destNode, destTp, false, - openRoadmTopology).build(); - InstanceIdentifier.InstanceIdentifierBuilder nwIID = InstanceIdentifier.builder(Network.class, + openRoadmFactory).build(); + InstanceIdentifier.InstanceIdentifierBuilder nwIID = + InstanceIdentifier.builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))); WriteTransaction wrtx = dataBroker.newWriteOnlyTransaction(); wrtx.merge(LogicalDatastoreType.CONFIGURATION, nwIID.build(), topoNetowkLayer); @@ -67,18 +71,19 @@ final class Rdm2XpdrLink { } public static boolean createRdmXpdrLinks(LinksInput linksInput, - OpenRoadmTopology openRoadmTopology, DataBroker dataBroker) { + OpenRoadmFactory openRoadmFactory, DataBroker dataBroker) { String srcNode = - new StringBuilder(linksInput.getRdmNode()).append("-SRG").append(linksInput.getSrgNum()).toString(); + new StringBuilder(linksInput.getRdmNode()).append("-SRG").append(linksInput.getSrgNum()).toString(); String srcTp = linksInput.getTerminationPointNum(); String destNode = - new StringBuilder(linksInput.getXpdrNode()).append("-XPDR").append(linksInput.getXpdrNum()).toString(); + new StringBuilder(linksInput.getXpdrNode()).append("-XPDR").append(linksInput.getXpdrNum()).toString(); String destTp = new StringBuilder("XPDR").append(linksInput.getXpdrNum()).append("-NETWORK") - .append(linksInput.getNetworkNum()).toString(); + .append(linksInput.getNetworkNum()).toString(); Network topoNetowkLayer = createNetworkBuilder(srcNode, srcTp, destNode, destTp, true, - openRoadmTopology).build(); - InstanceIdentifier.InstanceIdentifierBuilder nwIID = InstanceIdentifier.builder(Network.class, + openRoadmFactory).build(); + InstanceIdentifier.InstanceIdentifierBuilder nwIID = + InstanceIdentifier.builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))); WriteTransaction wrtx = dataBroker.newWriteOnlyTransaction(); wrtx.merge(LogicalDatastoreType.CONFIGURATION, nwIID.build(), topoNetowkLayer); @@ -95,17 +100,26 @@ final class Rdm2XpdrLink { } private static NetworkBuilder createNetworkBuilder(String srcNode, String srcTp, String destNode, String destTp, - boolean isXponderInput, OpenRoadmTopology openRoadmTopology) { + boolean isXponderInput, OpenRoadmFactory openRoadmFactory) { NetworkId nwId = new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID); NetworkBuilder nwBuilder = new NetworkBuilder(); nwBuilder.setNetworkId(nwId); nwBuilder.withKey(new NetworkKey(nwId)); +// Link1Builder lnk1bldr = new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network +// .rev181130.Link1Builder(); Link1Builder lnk1bldr = new Link1Builder(); - LinkBuilder linkBuilder = openRoadmTopology.createLink(srcNode, destNode, srcTp, destTp); + LinkBuilder linkBuilder = openRoadmFactory.createLink(srcNode, destNode, srcTp, destTp); lnk1bldr.setLinkType(isXponderInput ? OpenroadmLinkType.XPONDERINPUT : OpenroadmLinkType.XPONDEROUTPUT); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2bldr = new org + .opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); linkBuilder.addAugmentation(Link1.class, lnk1bldr.build()); + linkBuilder.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1 + .class, lnk2bldr.build()); + LOG.info("Link id in the linkbldr {}", linkBuilder.getLinkId()); - LOG.info("Link with oppo link {}", linkBuilder.augmentation(Link1.class)); + LOG.info("Link with oppo link {}", linkBuilder.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm + .opposite.links.rev170929.Link1.class)); Network1Builder nwBldr1 = new Network1Builder(); nwBldr1.setLink(ImmutableList.of(linkBuilder.build())); nwBuilder.addAugmentation(Network1.class, nwBldr1.build()); diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/LldpListener.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/LldpListener.java index 276ca0e72..e76ad2995 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/LldpListener.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/LldpListener.java @@ -8,7 +8,6 @@ package org.opendaylight.transportpce.networkmodel.listeners; -import org.opendaylight.transportpce.networkmodel.R2RLinkDiscovery; import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.LldpNbrInfoChange; import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.OrgOpenroadmLldpListener; import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceNotificationType; @@ -19,11 +18,10 @@ import org.slf4j.LoggerFactory; public class LldpListener implements OrgOpenroadmLldpListener { private static final Logger LOG = LoggerFactory.getLogger(LldpListener.class); - private final R2RLinkDiscovery linkDiscovery; + //private final R2RLinkDiscovery linkDiscovery; private final NodeId nodeId; - public LldpListener(final R2RLinkDiscovery linkDiscovery, final String nodeId) { - this.linkDiscovery = linkDiscovery; + public LldpListener(final String nodeId) { this.nodeId = new NodeId(nodeId); } @@ -35,13 +33,13 @@ public class LldpListener implements OrgOpenroadmLldpListener { public void onLldpNbrInfoChange(LldpNbrInfoChange notification) { LOG.info("Notification {} received {}", LldpNbrInfoChange.QNAME, notification); if (notification.getNotificationType().equals(ResourceNotificationType.ResourceCreation)) { - linkDiscovery.createR2RLink(nodeId,notification.getResource(), + /*linkDiscovery.createR2RLink(nodeId,notification.getResource(), notification.getNbrInfo().getRemoteSysName(), - notification.getNbrInfo().getRemotePortId()); + notification.getNbrInfo().getRemotePortId());*/ } else if (notification.getNotificationType().equals(ResourceNotificationType.ResourceDeletion)) { - linkDiscovery.deleteR2RLink(nodeId,notification.getResource(), + /*linkDiscovery.deleteR2RLink(nodeId,notification.getResource(), notification.getNbrInfo().getRemoteSysName(), - notification.getNbrInfo().getRemotePortId()); + notification.getNbrInfo().getRemotePortId());*/ } } } diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelService.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelService.java index f3242a1e4..d4d890c70 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelService.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelService.java @@ -14,9 +14,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev15 */ public interface NetworkModelService { + /** - * Create new OpenROADM node in all OpenROADM topologies. - * + * Create new OpenROADM node in all OpenROADM topologies. * @param nodeId * unique node ID of new OpenROADM node * @param nodeVersion @@ -27,10 +27,10 @@ public interface NetworkModelService { /** * Delete OpenROADM node mapping and topologies. * - * @param nodeId unique node ID of OpenROADM node + * @param nodeId unique node ID of OpenROADM node. * */ - void deleteOpenROADMnode(String nodeId); + void deleteOpenRoadmnode(String nodeId); /** * Set/update connection status of OpenROADM node. @@ -40,6 +40,6 @@ public interface NetworkModelService { * @param connectionStatus * connection status of the node */ - void setOpenROADMnodeStatus(String nodeId, NetconfNodeConnectionStatus.ConnectionStatus connectionStatus); + void setOpenRoadmNodeStatus(String nodeId, NetconfNodeConnectionStatus.ConnectionStatus connectionStatus); } diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelServiceImpl.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelServiceImpl.java index 39d892112..73bcecd5d 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelServiceImpl.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/service/NetworkModelServiceImpl.java @@ -9,23 +9,19 @@ package org.opendaylight.transportpce.networkmodel.service; import java.util.HashMap; import java.util.concurrent.ExecutionException; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; import org.opendaylight.transportpce.common.mapping.PortMapping; -import org.opendaylight.transportpce.networkmodel.R2RLinkDiscovery; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.networkmodel.dto.TopologyShard; import org.opendaylight.transportpce.networkmodel.util.ClliNetwork; +import org.opendaylight.transportpce.networkmodel.util.OpenRoadmFactory; import org.opendaylight.transportpce.networkmodel.util.OpenRoadmNetwork; -import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkId; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NodeId; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.Node; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NodeKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Network1; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.Link; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus; @@ -38,20 +34,21 @@ public class NetworkModelServiceImpl implements NetworkModelService { private static final Logger LOG = LoggerFactory.getLogger(NetworkModelServiceImpl.class); private static final boolean CREATE_MISSING_PARENTS = true; - private final DataBroker dataBroker; - private final R2RLinkDiscovery linkDiscovery; + private NetworkTransactionService networkTransactionService; + //private final R2RLinkDiscoveryFactoryMethod linkDiscovery; private final DeviceTransactionManager deviceTransactionManager; - private final OpenRoadmTopology openRoadmTopology; + private final OpenRoadmFactory openRoadmFactory; private final PortMapping portMapping; private HashMap topologyShardMountedDevice; - public NetworkModelServiceImpl(final DataBroker dataBroker, final R2RLinkDiscovery linkDiscovery, - DeviceTransactionManager deviceTransactionManager, - OpenRoadmTopology openRoadmTopology, PortMapping portMapping) { - this.dataBroker = dataBroker; - this.linkDiscovery = linkDiscovery; + public NetworkModelServiceImpl(final NetworkTransactionService networkTransactionService, + DeviceTransactionManager deviceTransactionManager, + OpenRoadmFactory openRoadmFactory, PortMapping portMapping) { + + this.networkTransactionService = networkTransactionService; + //this.linkDiscovery = linkDiscovery; this.deviceTransactionManager = deviceTransactionManager; - this.openRoadmTopology = openRoadmTopology; + this.openRoadmFactory = openRoadmFactory; this.portMapping = portMapping; this.topologyShardMountedDevice = new HashMap(); } @@ -64,81 +61,89 @@ public class NetworkModelServiceImpl implements NetworkModelService { } @Override - public void createOpenROADMnode(String nodeId, String nodeVersion) { + public void createOpenROADMnode(String nodeId, String openRoadmVersion) { try { LOG.info("createOpenROADMNode: {} ", nodeId); - boolean isPortMapping = this.portMapping.createMappingData(nodeId, nodeVersion); - if (isPortMapping && "1.2.1".equals(this.portMapping.getNode(nodeId).getOpenroadmVersion().getName())) { - this.linkDiscovery.readLLDP(new NodeId(nodeId)); + if (!portMapping.createMappingData(nodeId,openRoadmVersion)) { + LOG.warn("Could not generate port mapping for {} skipping network model creation",nodeId); + return; + } + //this.linkDiscovery.readLLDP(new NodeId(nodeId)); - Node clliNode = ClliNetwork.createNode(this.deviceTransactionManager, nodeId); - if (clliNode == null) { - LOG.error("Unable to create clli node! Node id: {}", nodeId); - return; - } + Node clliNode = ClliNetwork.createNode(this.deviceTransactionManager, nodeId,openRoadmVersion); + if (clliNode == null) { + LOG.error("Unable to create clli node! Node id: {}", nodeId); + return; + } - Node openRoadmNode = OpenRoadmNetwork.createNode(nodeId, this.deviceTransactionManager); - if (openRoadmNode == null) { - LOG.error("Unable to create OpenRoadm node! Node id: {}", nodeId); - return; - } + InstanceIdentifier iiClliNode = InstanceIdentifier + .builder(Network.class, new NetworkKey(new + NetworkId(NetworkUtils.CLLI_NETWORK_ID))) + .child(Node.class, clliNode.key()) + .build(); - TopologyShard topologyShard = this.openRoadmTopology.createTopologyShard(nodeId); - if (topologyShard == null) { - LOG.error("Unable to create topology shard for node {}!", nodeId); - return; - } - this.topologyShardMountedDevice.put(nodeId, topologyShard); - WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction(); - LOG.info("creating node in {}", NetworkUtils.CLLI_NETWORK_ID); - InstanceIdentifier iiClliNode = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))) - .child(Node.class, clliNode.key()) - .build(); - writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iiClliNode, clliNode, - CREATE_MISSING_PARENTS); - LOG.info("creating node in {}", NetworkUtils.UNDERLAY_NETWORK_ID); - InstanceIdentifier iiOpenRoadmNode = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))) - .child(Node.class, openRoadmNode.key()) - .build(); - writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmNode, openRoadmNode, - CREATE_MISSING_PARENTS); - for (Node openRoadmTopologyNode: topologyShard.getNodes()) { - LOG.info("creating node {} in {}", openRoadmTopologyNode.getNodeId().getValue(), - NetworkUtils.OVERLAY_NETWORK_ID); - InstanceIdentifier iiOpenRoadmTopologyNode = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) - .child(Node.class, openRoadmTopologyNode.key()) - .build(); - writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode, - openRoadmTopologyNode, CREATE_MISSING_PARENTS); - } - for (Link openRoadmTopologyLink: topologyShard.getLinks()) { - LOG.info("creating link {} in {}", openRoadmTopologyLink.getLinkId().getValue(), - NetworkUtils.OVERLAY_NETWORK_ID); - InstanceIdentifier iiOpenRoadmTopologyLink = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) - .augmentation(Network1.class) - .child(Link.class, openRoadmTopologyLink.key()) - .build(); - writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink, - openRoadmTopologyLink, CREATE_MISSING_PARENTS); - } - writeTransaction.submit().get(); - LOG.info("all nodes and links created"); - } else { - LOG.warn("openroadm-topology is not managed yet with openROADM device 2.2.1"); + LOG.info("creating node in {}", NetworkUtils.CLLI_NETWORK_ID); + networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiClliNode, clliNode, + CREATE_MISSING_PARENTS); + + Node openRoadmNode = OpenRoadmNetwork.createNode(nodeId, this.deviceTransactionManager,openRoadmVersion); + if (openRoadmNode == null) { + LOG.error("Unable to create OpenRoadm node! Node id: {}", nodeId); + return; + } + InstanceIdentifier iiOpenRoadmNode = InstanceIdentifier + .builder(Network.class, new NetworkKey(new + NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))) + .child(Node.class, openRoadmNode.key()) + .build(); + + LOG.info("creating node in {}", NetworkUtils.UNDERLAY_NETWORK_ID); + networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmNode, openRoadmNode, + CREATE_MISSING_PARENTS); + + + TopologyShard topologyShard = openRoadmFactory.createTopologyShardVersionControl(nodeId); + + if (topologyShard == null) { + LOG.error("Unable to create topology shard for node {}!", nodeId); + return; } + this.topologyShardMountedDevice.put(nodeId, topologyShard); + + for (Node openRoadmTopologyNode: topologyShard.getNodes()) { + LOG.info("creating node {} in {}", openRoadmTopologyNode.getNodeId().getValue(), + NetworkUtils.OVERLAY_NETWORK_ID); + InstanceIdentifier iiOpenRoadmTopologyNode = InstanceIdentifier + .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .child(Node.class, openRoadmTopologyNode.key()) + .build(); + networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode, + openRoadmTopologyNode, CREATE_MISSING_PARENTS); + } + for (Link openRoadmTopologyLink: topologyShard.getLinks()) { + LOG.info("creating link {} in {}", openRoadmTopologyLink.getLinkId().getValue(), + NetworkUtils.OVERLAY_NETWORK_ID); + InstanceIdentifier iiOpenRoadmTopologyLink = InstanceIdentifier + .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .augmentation(Network1.class) + .child(Link.class, openRoadmTopologyLink.key()) + .build(); + networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink, + openRoadmTopologyLink, CREATE_MISSING_PARENTS); + } + networkTransactionService.submit().get(); + //linkDiscovery.readLLDP(nodeId); + LOG.info("all nodes and links created"); } catch (InterruptedException | ExecutionException e) { LOG.error("ERROR: ", e); } + } @Override - public void setOpenROADMnodeStatus(String nodeId, NetconfNodeConnectionStatus.ConnectionStatus connectionStatus) { + public void setOpenRoadmNodeStatus(String nodeId, NetconfNodeConnectionStatus.ConnectionStatus connectionStatus) { LOG.info("setOpenROADMNodeStatus: {} {}", nodeId, connectionStatus.name()); /* TODO: set connection status of the device in model, @@ -151,9 +156,12 @@ public class NetworkModelServiceImpl implements NetworkModelService { /* (non-Javadoc) * @see org.opendaylight.transportpce.networkmodel.service.NetworkModelService#deleteOpenROADMnode(java.lang.String) */ + + + @Override - public void deleteOpenROADMnode(String nodeId) { - try { + public void deleteOpenRoadmnode(String nodeId) { + /*try { LOG.info("deleteOpenROADMnode: {} ", nodeId); this.portMapping.deleteMappingData(nodeId); @@ -161,15 +169,17 @@ public class NetworkModelServiceImpl implements NetworkModelService { WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction(); LOG.info("deleting node in {}", NetworkUtils.CLLI_NETWORK_ID); InstanceIdentifier iiClliNode = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))) - .child(Node.class, nodeIdKey) - .build(); + .builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))) + .child(Node.class, nodeIdKey) + .build(); writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iiClliNode); LOG.info("deleting node in {}", NetworkUtils.UNDERLAY_NETWORK_ID); InstanceIdentifier iiOpenRoadmNode = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))) - .child(Node.class, nodeIdKey) - .build(); + .builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))) + .child(Node.class, nodeIdKey) + .build(); writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmNode); TopologyShard topologyShard = this.topologyShardMountedDevice.get(nodeId); if (topologyShard != null) { @@ -178,19 +188,21 @@ public class NetworkModelServiceImpl implements NetworkModelService { LOG.info("deleting node {} in {}", openRoadmTopologyNode.getNodeId().getValue(), NetworkUtils.OVERLAY_NETWORK_ID); InstanceIdentifier iiOpenRoadmTopologyNode = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) - .child(Node.class, openRoadmTopologyNode.key()) - .build(); + .builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .child(Node.class, openRoadmTopologyNode.key()) + .build(); writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode); } for (Link openRoadmTopologyLink: topologyShard.getLinks()) { LOG.info("deleting link {} in {}", openRoadmTopologyLink.getLinkId().getValue(), NetworkUtils.OVERLAY_NETWORK_ID); InstanceIdentifier iiOpenRoadmTopologyLink = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) - .augmentation(Network1.class) - .child(Link.class, openRoadmTopologyLink.key()) - .build(); + .builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .augmentation(Network1.class) + .child(Link.class, openRoadmTopologyLink.key()) + .build(); writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink); } } else { @@ -200,6 +212,6 @@ public class NetworkModelServiceImpl implements NetworkModelService { LOG.info("all nodes and links deleted ! "); } catch (InterruptedException | ExecutionException e) { LOG.error("Error when trying to delete node : {}", nodeId, e); - } + }*/ } } diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/ClliNetwork.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/ClliNetwork.java index f891ca509..e144f2414 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/ClliNetwork.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/ClliNetwork.java @@ -8,7 +8,6 @@ package org.opendaylight.transportpce.networkmodel.util; -import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -16,15 +15,12 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; -import org.opendaylight.transportpce.common.Timeouts; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; import org.opendaylight.yang.gen.v1.http.org.openroadm.clli.network.rev170626.NetworkTypes1; import org.opendaylight.yang.gen.v1.http.org.openroadm.clli.network.rev170626.NetworkTypes1Builder; import org.opendaylight.yang.gen.v1.http.org.openroadm.clli.network.rev170626.Node1; import org.opendaylight.yang.gen.v1.http.org.openroadm.clli.network.rev170626.Node1Builder; import org.opendaylight.yang.gen.v1.http.org.openroadm.clli.network.rev170626.network.network.types.ClliNetworkBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Info; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkId; @@ -55,8 +51,8 @@ public final class ClliNetwork { public static void createClliLayer(DataBroker controllerdb) { try { Network clliNetwork = createNetwork(); - InstanceIdentifierBuilder nwIID = InstanceIdentifier.builder( - Network.class,new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))); + InstanceIdentifierBuilder nwIID = InstanceIdentifier.builder(Network.class, + new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))); WriteTransaction wrtx = controllerdb.newWriteOnlyTransaction(); wrtx.put(LogicalDatastoreType.CONFIGURATION, nwIID.build(), clliNetwork); wrtx.submit().get(1, TimeUnit.SECONDS); @@ -74,18 +70,20 @@ public final class ClliNetwork { * * @return node builder status */ - public static Node createNode(DeviceTransactionManager deviceTransactionManager, String deviceId) { + public static Node createNode(DeviceTransactionManager deviceTransactionManager, String deviceId, + String openRoadmVersion) { //Read clli from the device - InstanceIdentifier infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class); - Optional deviceInfo = deviceTransactionManager.getDataFromDevice(deviceId, - LogicalDatastoreType.OPERATIONAL, infoIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); + InfoSubtree infoSubtree = new InfoSubtree(openRoadmVersion); String clli; - if (deviceInfo.isPresent()) { - clli = deviceInfo.get().getClli(); + + if (infoSubtree.getDeviceInfo(deviceId,deviceTransactionManager)) { + + clli = infoSubtree.getClli(); } else { + LOG.info("Unable for get Info subtree from the device"); return null; } + /* * Create node in the CLLI layer of the network model * with nodeId equal to the clli attribute in the device diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/InfoSubtree.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/InfoSubtree.java new file mode 100644 index 000000000..4956f06d1 --- /dev/null +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/InfoSubtree.java @@ -0,0 +1,143 @@ +/* + * Copyright © 2019 AT&T 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.transportpce.networkmodel.util; + +import java.util.Optional; + +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.StringConstants; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Info; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InfoSubtree { + + private static final Logger LOG = LoggerFactory.getLogger(InfoSubtree.class); + + String clli; + String vendor; + String model; + IpAddress ipAddress; + int nodeType; + String openRoadmVersion; + + public InfoSubtree(String openRoadmVersion) { + + this.clli = new String(); + this.vendor = new String(); + this.model = new String(); + this.ipAddress = null; + this.nodeType = 0; + this.openRoadmVersion = openRoadmVersion; + + + } + + public boolean getDeviceInfo(String nodeId, DeviceTransactionManager deviceTransactionManager) { + switch (this.openRoadmVersion) { + case StringConstants.OPENROADM_DEVICE_VERSION_1_2_1: + return getDeviceInfo1_2_1(nodeId, deviceTransactionManager); + case StringConstants.OPENROADM_DEVICE_VERSION_2_2_1: + return getDeviceInfo2_2_1(nodeId, deviceTransactionManager); + default: + LOG.info("Device version {} not supported",this.openRoadmVersion); + return false; + } + + } + + private boolean getDeviceInfo1_2_1(String nodeId, DeviceTransactionManager deviceTransactionManager) { + + //Read clli from the device + InstanceIdentifier infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class); + Optional deviceInfoOpt = + deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, infoIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + + Info deviceInfo = null; + + if (deviceInfoOpt.isPresent()) { + deviceInfo = deviceInfoOpt.get(); + } else { + LOG.error("Unable to get device info from device {}!", nodeId); + return false; + + } + + this.clli = deviceInfo.getClli(); + this.vendor = deviceInfo.getVendor(); + this.model = deviceInfo.getModel(); + this.ipAddress = deviceInfo.getIpAddress(); + this.nodeType = deviceInfo.getNodeType().getIntValue(); + + return true; + + } + + private boolean getDeviceInfo2_2_1(String nodeId, DeviceTransactionManager deviceTransactionManager) { + + //TODO : change back to operational when testing on real device + //Read clli from the device + InstanceIdentifier infoIID = InstanceIdentifier.create(org + .opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device + .container.OrgOpenroadmDevice.class).child(org.opendaylight.yang.gen.v1.http.org + .openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.Info.class); + Optional deviceInfoOpt = + deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.CONFIGURATION, infoIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + + org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container + .org.openroadm.device.Info deviceInfo = null; + + if (deviceInfoOpt.isPresent()) { + deviceInfo = deviceInfoOpt.get(); + } else { + LOG.error("Unable to get device info from device {}!", nodeId); + return false; + + } + + this.clli = deviceInfo.getClli(); + //this.vendor = deviceInfo.getVendor(); + //this.model = deviceInfo.getModel(); + this.ipAddress = deviceInfo.getIpAddress(); + this.nodeType = deviceInfo.getNodeType().getIntValue(); + + return true; + } + + public String getClli() { + return clli; + } + + public String getVendor() { + return vendor; + } + + public String getModel() { + return model; + } + + public IpAddress getIpAddress() { + return ipAddress; + } + + public int getNodeType() { + return nodeType; + } +} + + diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/LinkIdUtil.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/LinkIdUtil.java index 371bdf5bf..940d41dd8 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/LinkIdUtil.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/LinkIdUtil.java @@ -12,6 +12,7 @@ import java.text.MessageFormat; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev170818.InitRoadmNodesInput; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.LinkId; + public final class LinkIdUtil { private static final String NETWORK = "-NETWORK"; diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmFactory.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmFactory.java new file mode 100644 index 000000000..be6b89728 --- /dev/null +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmFactory.java @@ -0,0 +1,60 @@ +/* + * Copyright © 2019 AT&T 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.transportpce.networkmodel.util; + +import org.opendaylight.transportpce.common.StringConstants; +import org.opendaylight.transportpce.common.mapping.MappingUtils; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; +import org.opendaylight.transportpce.networkmodel.dto.TopologyShard; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.LinkBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OpenRoadmFactory { + private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmFactory.class); + OpenRoadmTopology121 openRoadmTopology121; + OpenRoadmTopology22 openRoadmTopology22; + private final MappingUtils mappingUtils; + + public OpenRoadmFactory(MappingUtils mappingUtils, OpenRoadmTopology121 openRoadmTopology121, + OpenRoadmTopology22 openRoadmTopology22) { + this.mappingUtils = mappingUtils; + this.openRoadmTopology22 = openRoadmTopology22; + this.openRoadmTopology121 = openRoadmTopology121; + } + + public void createTopoLayerVersionControl(NetworkTransactionService networkTransactionService) { + openRoadmTopology22.createTopoLayer(); + + } + + public TopologyShard createTopologyShardVersionControl(String nodeId) { + LOG.info("Create topology called for {}",nodeId); + switch (mappingUtils.getOpenRoadmVersion(nodeId)) { + case StringConstants.OPENROADM_DEVICE_VERSION_1_2_1: + return openRoadmTopology121.createTopologyShard(nodeId); + case StringConstants.OPENROADM_DEVICE_VERSION_2_2_1: + LOG.info("Creating openroadm topology v2.2 node for {}",nodeId); + return openRoadmTopology22.createTopologyShard(nodeId); + default: + return null; + + } + } + + public boolean deleteLink(String srcNode, String dstNode, String srcTp, String destTp, + NetworkTransactionService networkTransactionService) { + + return TopologyUtils.deleteLink(srcNode, dstNode, srcTp, destTp, networkTransactionService); + } + + public LinkBuilder createLink(String srcNode, String dstNode, String srcTp, String destTp) { + return TopologyUtils.createLink(srcNode,dstNode,srcTp,destTp); + + } +} diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmNetwork.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmNetwork.java index 22dedb9a5..2cf82886a 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmNetwork.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmNetwork.java @@ -9,7 +9,6 @@ package org.opendaylight.transportpce.networkmodel.util; import com.google.common.collect.ImmutableList; -import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -17,16 +16,12 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; -import org.opendaylight.transportpce.common.Timeouts; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.NodeTypes; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Info; -import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev170929.NetworkTypes1; -import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev170929.NetworkTypes1Builder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev170929.Node1; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev170929.Node1Builder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev170929.network.network.types.OpenroadmNetworkBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.NetworkTypes1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.NetworkTypes1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.network.types.OpenroadmTopologyBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmNodeType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; @@ -45,6 +40,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdenti import org.slf4j.Logger; import org.slf4j.LoggerFactory; + public final class OpenRoadmNetwork { private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmNetwork.class); @@ -63,7 +59,7 @@ public final class OpenRoadmNetwork { try { Network openRoadmNetwork = createOpenRoadmNetwork(); InstanceIdentifierBuilder nwIID = InstanceIdentifier.builder(Network.class, - new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))); + new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))); WriteTransaction wrtx = controllerdb.newWriteOnlyTransaction(); wrtx.put(LogicalDatastoreType.CONFIGURATION, nwIID.build(), openRoadmNetwork); wrtx.submit().get(1, TimeUnit.SECONDS); @@ -81,20 +77,34 @@ public final class OpenRoadmNetwork { * * @return node builder status */ - public static Node createNode(String nodeId, DeviceTransactionManager deviceTransactionManager) { - // Fetches the info from the deviceInfo - InstanceIdentifier infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class); - Optional deviceInfoOpt = deviceTransactionManager.getDataFromDevice(nodeId, - LogicalDatastoreType.OPERATIONAL, infoIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); - Info deviceInfo; - if (deviceInfoOpt.isPresent()) { - deviceInfo = deviceInfoOpt.get(); + public static Node createNode(String nodeId, DeviceTransactionManager deviceTransactionManager, + String openRoadmVersion) { + + InfoSubtree infoSubtree = new InfoSubtree(openRoadmVersion); + String clli; + String vendor; + String model; + IpAddress ipAddress; + int nodeType; + + if (infoSubtree.getDeviceInfo(nodeId,deviceTransactionManager)) { + + clli = infoSubtree.getClli(); + + /** + * TODO : Uncomment when real when testing on real device + * vendor = infoSubtree.getVendor(); + * model = infoSubtree.getModel(); + **/ + vendor = infoSubtree.getVendor(); + clli = infoSubtree.getClli(); + model = infoSubtree.getModel(); + ipAddress = infoSubtree.getIpAddress(); + nodeType = infoSubtree.getNodeType(); + } else { - LOG.error("Unable to get device info from device {}!", nodeId); return null; } - NodeTypes nodeType = deviceInfo.getNodeType(); // Uses the Node Builder to set the nodeId and Key NodeBuilder nodeBldr = new NodeBuilder(); @@ -106,7 +116,7 @@ public final class OpenRoadmNetwork { /* * Recognize the node type: 1:ROADM, 2:XPONDER */ - switch (nodeType.getIntValue()) { + switch (nodeType) { case 1: node1bldr.setNodeType(OpenroadmNodeType.ROADM); break; @@ -114,13 +124,11 @@ public final class OpenRoadmNetwork { node1bldr.setNodeType(OpenroadmNodeType.XPONDER); break; default: - LOG.error("No correponsding type for the value: {}", nodeType.getIntValue()); + LOG.error("No correponsding type for the value: {}", nodeType); break; } - String vendor = deviceInfo.getVendor(); - String model = deviceInfo.getModel(); - IpAddress ipAddress = deviceInfo.getIpAddress(); + // Sets IP, Model and Vendor information fetched from the deviceInfo node1bldr.setIp(ipAddress); node1bldr.setModel(model); @@ -128,7 +136,7 @@ public final class OpenRoadmNetwork { // Sets the value of Network-ref and Node-ref as a part of the supporting node // attribute - String clli = deviceInfo.getClli(); + SupportingNodeBuilder supportbldr = new SupportingNodeBuilder(); supportbldr.withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID), new NodeId(clli))); supportbldr.setNetworkRef(new NetworkId(NetworkUtils.CLLI_NETWORK_ID)); @@ -150,7 +158,7 @@ public final class OpenRoadmNetwork { openrdmnwBuilder.withKey(new NetworkKey(nwId)); // sets network type to OpenRoadmNetwork NetworkTypes1Builder openRoadmNetworkTypesBldr = new NetworkTypes1Builder(); - openRoadmNetworkTypesBldr.setOpenroadmNetwork(new OpenroadmNetworkBuilder().build()); + openRoadmNetworkTypesBldr.setOpenroadmTopology(new OpenroadmTopologyBuilder().build()); NetworkTypesBuilder openrdmnwTypeBuilder = new NetworkTypesBuilder(); openrdmnwTypeBuilder.addAugmentation(NetworkTypes1.class, openRoadmNetworkTypesBldr.build()); openrdmnwBuilder.setNetworkTypes(openrdmnwTypeBuilder.build()); diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology121.java similarity index 77% rename from networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology.java rename to networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology121.java index c89fd5a65..ed5e485a6 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology121.java @@ -15,12 +15,12 @@ import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; + import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; import org.opendaylight.transportpce.common.Timeouts; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.networkmodel.dto.NodeData; import org.opendaylight.transportpce.networkmodel.dto.TopologyShard; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.NodeTypes; @@ -46,6 +46,7 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev17092 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1Builder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.link.OMSAttributesBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.network.types.OpenroadmTopologyBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.DegreeAttributesBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.SrgAttributesBuilder; @@ -83,35 +84,33 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdenti import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class OpenRoadmTopology { +public class OpenRoadmTopology121 { - private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmTopology.class); + private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmTopology121.class); private static final int DEFAULT_PORT_DIRECTION = -1; private static final int MAX_DEGREE = 20; private static final int MAX_SRG = 20; - private final DataBroker dataBroker; + private NetworkTransactionService networkTransactionService; private final DeviceTransactionManager deviceTransactionManager; - public OpenRoadmTopology(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager) { - this.dataBroker = dataBroker; + public OpenRoadmTopology121(NetworkTransactionService networkTransactionService, + DeviceTransactionManager deviceTransactionManager) { + this.networkTransactionService = networkTransactionService; this.deviceTransactionManager = deviceTransactionManager; } /** * This public method creates the OpenROADM Topology Layer and posts it to * the controller. - * - * @param controllerdb controller databroker */ - public void createTopoLayer(DataBroker controllerdb) { + public void createTopoLayer() { try { Network openRoadmTopology = createOpenRoadmTopology(); InstanceIdentifierBuilder nwIID = InstanceIdentifier.builder(Network.class, - new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))); - WriteTransaction wrtx = controllerdb.newWriteOnlyTransaction(); - wrtx.put(LogicalDatastoreType.CONFIGURATION, nwIID.build(), openRoadmTopology); - wrtx.submit().get(1, TimeUnit.SECONDS); + new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))); + this.networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, nwIID.build(), openRoadmTopology); + this.networkTransactionService.submit().get(1, TimeUnit.SECONDS); LOG.info("OpenRoadm-Topology created successfully."); } catch (ExecutionException | TimeoutException | InterruptedException e) { LOG.warn("Failed to create OpenRoadm-Topology", e); @@ -147,9 +146,9 @@ public class OpenRoadmTopology { int portDirectionEnum = DEFAULT_PORT_DIRECTION; InstanceIdentifier infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class); - java.util.Optional deviceInfoOpt = this.deviceTransactionManager.getDataFromDevice(nodeId, - LogicalDatastoreType.OPERATIONAL, infoIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); + java.util.Optional deviceInfoOpt = + deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, infoIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); Info deviceInfo; if (deviceInfoOpt.isPresent()) { deviceInfo = deviceInfoOpt.get(); @@ -163,10 +162,8 @@ public class OpenRoadmTopology { if (NodeTypes.Rdm.equals(deviceInfo.getNodeType())) { /* - * Adding Degree Node Get Degree Number -> x - * then get connection ports - * then find the port directions to decide whether TX/RX/TXRX - * Get value for max degree from info subtree, required for iteration + * Adding Degree Node Get Degree Number -> x then get connection ports then find the port directions + * to decide whether TX/RX/TXRX Get value for max degree from info subtree, required for iteration * if not present assume to be 20 (temporary) */ @@ -188,8 +185,9 @@ public class OpenRoadmTopology { portDirectionEnum = nodeData.getPortDirectionEnum(); nodes.add(tempNode.build()); degreeCounter++; - } else { - // null returned if Degree number= degreeCounter not present in the device + } + // null returned if Degree number= degreeCounter not present in the device + else { break; } } @@ -219,6 +217,7 @@ public class OpenRoadmTopology { } numOfSrgs = srgCounter - 1; + LOG.info("adding links numOfDegrees={} numOfSrgs={}", numOfDegrees, numOfSrgs); List links = new ArrayList<>(); links.addAll(createExpressLinks(nodeId, numOfDegrees, portDirectionEnum)); @@ -227,10 +226,20 @@ public class OpenRoadmTopology { return new TopologyShard(nodes, links); } else if (NodeTypes.Xpdr.equals(deviceInfo.getNodeType())) { // Check if node is XPONDER - XponderPortNumber portNums = getNoOfPorts(nodeId); + Integer clientport = getNoOfClientPorts(nodeId); List links = new ArrayList<>(); - NodeBuilder tempNode = createXpdr(portNums.getNumOfClientPorts(), portNums.getNumOfLinePorts(), nodeId); - nodes.add(tempNode.build()); + Integer clientCounter = 1; + Integer lineCounter = 1; + while (clientCounter <= clientport) { + NodeBuilder tempNode = createXpdr(clientCounter, lineCounter, nodeId); + if (tempNode == null) { + break; + } + nodes.add(tempNode.build()); + clientCounter++; + lineCounter++; + LOG.info("Entered this loop"); + } return new TopologyShard(nodes, links); } @@ -238,10 +247,9 @@ public class OpenRoadmTopology { } /** - * This private method gets the list of circuit packs on a xponder. - * For each circuit pack on a Xponder, it does a get on circuit-pack subtree with - * circuit-pack-name as key in order to get the list of ports. - * It then iterates over the list of ports to get ports with port-qual as + * This private method gets the list of circuit packs on a xponder. For each circuit pack on a + * Xponder, it does a get on circuit-pack subtree with circuit-pack-name as key in order to get the + * list of ports. It then iterates over the list of ports to get ports with port-qual as * xpdr-network/xpdr-client. The line and client ports are saved as: * *

@@ -250,18 +258,15 @@ public class OpenRoadmTopology { *

* 2. CLNTn */ - private XponderPortNumber getNoOfPorts(String deviceId) { - - XponderPortNumber xponderPortNumber = new XponderPortNumber(); + private int getNoOfClientPorts(String deviceId) { // Creating for Xponder Line and Client Ports InstanceIdentifier deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class); - Optional deviceObject = this.deviceTransactionManager.getDataFromDevice(deviceId, - LogicalDatastoreType.OPERATIONAL, deviceIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); + Optional deviceObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.OPERATIONAL, deviceIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); // Variable to keep track of number of client ports - int client = 0; - int line = 0; + int client = 1; if (deviceObject.isPresent()) { for (CircuitPacks cp : deviceObject.get().getCircuitPacks()) { if (cp.getPorts() != null) { @@ -269,19 +274,15 @@ public class OpenRoadmTopology { if (port.getPortQual() != null) { if (port.getPortQual().getIntValue() == 4) { client++; - } else if (port.getPortQual().getIntValue() == 3) { - line++; } } } } } } else { - return xponderPortNumber; + return 0; } - xponderPortNumber.setNumOfClientPorts(client); - xponderPortNumber.setNumOfLinePorts(line); - return xponderPortNumber; + return client; } private NodeBuilder createXpdr(Integer clientCounter, Integer lineCounter, String nodeId) { @@ -296,12 +297,13 @@ public class OpenRoadmTopology { node1bldr.setNodeType(OpenroadmNodeType.XPONDER); List tpList = new ArrayList<>(); String nodeIdtopo = new StringBuilder().append(nodeId).append("-XPDR1").toString(); - // Ad degree node specific augmentation + + nodebldr.setNodeId(new NodeId(nodeIdtopo)); nodebldr.withKey(new NodeKey(new NodeId(nodeIdtopo))); nodebldr.addAugmentation(Node1.class, node1bldr.build()); while (clientCounter != 0) { - // Create CLNT-TX terminationCannot get available Capabilitiesc + // Create CLNT-TX termination tempTpBldr = createTpBldr("XPDR1-CLIENT" + clientCounter); tp1Bldr.setTpType(OpenroadmTpType.XPONDERCLIENT); XpdrClientAttributesBuilder xpdrClntBldr = new XpdrClientAttributesBuilder(); @@ -322,17 +324,19 @@ public class OpenRoadmTopology { tpList.add(tempTpBldr.build()); lineCounter--; } - LOG.info("printing tpList {}", tpList); - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder tpNode1 = - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder(); + LOG.info("printing tpList {}",tpList); + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608 + .Node1Builder tpNode1 = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf + .network.topology.rev150608.Node1Builder(); tpNode1.setTerminationPoint(tpList); nodebldr.addAugmentation( - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class, - tpNode1.build()); - LOG.info("The nodebldr {}", nodebldr); + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class, + tpNode1.build()); + LOG.info("The nodebldr {}",nodebldr); return nodebldr; } + private NodeData createDegreeNode(String nodeId, int degreeCounter) { // Create augmentation node to inorder to add degree Node1Builder node1bldr = new Node1Builder(); @@ -342,7 +346,7 @@ public class OpenRoadmTopology { // Get connection ports on degree number = degreeCounter in order to get port // direction List degreeConPorts = getDegreePorts(nodeId, degreeCounter); - if ((degreeConPorts == null) || degreeConPorts.isEmpty()) { + if (degreeConPorts == null || degreeConPorts.isEmpty()) { return null; } @@ -359,7 +363,7 @@ public class OpenRoadmTopology { nodebldr.addAugmentation(Node1.class, node1bldr.build()); // Get Port direction int portDirectionEnum = getPortDirection(nodeId, degreeConPorts.get(0).getCircuitPackName(), - degreeConPorts.get(0).getPortName().toString()); + degreeConPorts.get(0).getPortName().toString()); /* * if bi-directional then create 2 tp's : @@ -368,13 +372,16 @@ public class OpenRoadmTopology { * * if uni-directional : * - * --> TTP-TX --> TTP-RX --> CTP-TX --> CTP-RX + * --> TTP-TX + * --> TTP-RX + * --> CTP-TX + * --> CTP-RX */ TerminationPoint1Builder tp1Bldr = new TerminationPoint1Builder(); TerminationPointBuilder tempTpBldr; List tpList = new ArrayList<>(); - if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) { + if (portDirectionEnum == 1 || portDirectionEnum == 2) { // ports are uni Directional on a degree, therefore 4 termination points // Create TTP-TX termination @@ -388,21 +395,21 @@ public class OpenRoadmTopology { tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-RX"); tp1Bldr.setTpType(OpenroadmTpType.DEGREERXTTP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); tpList.add(tempTpBldr.build()); // Create CTP-TX termination tp1Bldr = new TerminationPoint1Builder(); tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-TX"); tp1Bldr.setTpType(OpenroadmTpType.DEGREETXCTP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); tpList.add(tempTpBldr.build()); // Create CTP-RX termination tp1Bldr = new TerminationPoint1Builder(); tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-RX"); tp1Bldr.setTpType(OpenroadmTpType.DEGREERXCTP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); tpList.add(tempTpBldr.build()); } else if (portDirectionEnum == 3) { @@ -411,20 +418,22 @@ public class OpenRoadmTopology { tp1Bldr = new TerminationPoint1Builder(); tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-TXRX"); tp1Bldr.setTpType(OpenroadmTpType.DEGREETXRXTTP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); tpList.add(tempTpBldr.build()); // Create CTP-TXRX termination tp1Bldr = new TerminationPoint1Builder(); tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-TXRX"); tp1Bldr.setTpType(OpenroadmTpType.DEGREETXRXCTP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); tpList.add(tempTpBldr.build()); } - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder tpNode1 = - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder(); + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608 + .Node1Builder tpNode1 + = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network + .topology.rev150608.Node1Builder(); tpNode1.setTerminationPoint(tpList); @@ -434,6 +443,7 @@ public class OpenRoadmTopology { return new NodeData(nodebldr, portDirectionEnum); } + private NodeBuilder createSrgNode(String nodeId, int srgCounter, int portDirectionEnum) { // Create augmentation node to inorder to add degree Node1Builder node1bldr = new Node1Builder(); @@ -450,6 +460,7 @@ public class OpenRoadmTopology { NodeBuilder nodebldr = createTopoLayerNode(nodeId); nodebldr.addAugmentation(Node1.class, node1bldr.build()); + // Get connection ports on degree number = degreeCounter in order to get port // direction int maxPpPorts = getMaxPp(nodeId, srgCounter); @@ -457,6 +468,7 @@ public class OpenRoadmTopology { return null; } + String nodeIdtopo = new StringBuilder().append(nodeId).append("-SRG").append(srgCounter).toString(); nodebldr.setNodeId(new NodeId(nodeIdtopo)); List tpList = new ArrayList<>(); @@ -465,19 +477,19 @@ public class OpenRoadmTopology { TerminationPointBuilder tempTpBldr; for (int i = 1; i <= maxPpPorts; i++) { - if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) { - if (i >= (maxPpPorts / 2)) { + if (portDirectionEnum == 1 || portDirectionEnum == 2) { + if (i >= maxPpPorts / 2) { break; } // ports are uni Directional on a degree, therefore 4 termination points - // Create PP-TX termination + // Create TTP-TX termination tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-TX"); tp1Bldr = new TerminationPoint1Builder(); tp1Bldr.setTpType(OpenroadmTpType.SRGTXPP); tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); tpList.add(tempTpBldr.build()); - // Create PP-RX termination + // Create TTP-RX termination tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-RX"); tp1Bldr = new TerminationPoint1Builder(); tp1Bldr.setTpType(OpenroadmTpType.SRGRXPP); @@ -486,7 +498,7 @@ public class OpenRoadmTopology { } else if (portDirectionEnum == 3) { // Ports are bi directional therefore 2 termination points - // Create PP-TXRX termination + // Create TTP-TXRX termination tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-TXRX"); tp1Bldr = new TerminationPoint1Builder(); tp1Bldr.setTpType(OpenroadmTpType.SRGTXRXPP); @@ -495,39 +507,9 @@ public class OpenRoadmTopology { } } - switch (portDirectionEnum) { - case 1: // ports are uni Directional on a degree - // Create CP-TX termination - tempTpBldr = createTpBldr("SRG" + srgCounter + "-CP" + "-TX"); - tp1Bldr = new TerminationPoint1Builder(); - tp1Bldr.setTpType(OpenroadmTpType.SRGTXCP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); - tpList.add(tempTpBldr.build()); - break; - case 2: - // Create CP-RX termination - tempTpBldr = createTpBldr("SRG" + srgCounter + "-CP" + "-RX"); - tp1Bldr = new TerminationPoint1Builder(); - tp1Bldr.setTpType(OpenroadmTpType.SRGRXCP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); - tpList.add(tempTpBldr.build()); - break; - case 3: - // Ports are bi directional therefore 2 termination points - // Create CP-TXRX termination - tempTpBldr = createTpBldr("SRG" + srgCounter + "-CP" + "-TXRX"); - tp1Bldr = new TerminationPoint1Builder(); - tp1Bldr.setTpType(OpenroadmTpType.SRGTXRXCP); - tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); - tpList.add(tempTpBldr.build()); - break; - default: - LOG.error("No correponsding direction to the value: {}", portDirectionEnum); - break; - } - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder tpNode1 = - new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder(); + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology + .rev150608.Node1Builder(); tpNode1.setTerminationPoint(tpList); @@ -539,18 +521,18 @@ public class OpenRoadmTopology { } /* - * This method will return the TTP ports in the device for a given degree number to - * be used by the node to create TTP and CTP termination point on the device. + * This method will return the TTP ports in the device for a given degree number to be used by the + * node to create TTP and CTP termination point on the device */ private List getDegreePorts(String deviceId, Integer degreeCounter) { List degreeConPorts = new ArrayList<>(); LOG.info("Getting Connection ports for Degree Number {}", degreeCounter); - InstanceIdentifier deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Degree.class, - new DegreeKey(degreeCounter)); + InstanceIdentifier deviceIID = + InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Degree.class, new DegreeKey(degreeCounter)); - Optional ordmDegreeObject = this.deviceTransactionManager.getDataFromDevice(deviceId, - LogicalDatastoreType.CONFIGURATION, deviceIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); + Optional ordmDegreeObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.CONFIGURATION, deviceIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); if (ordmDegreeObject.isPresent()) { degreeConPorts.addAll(new ArrayList<>(ordmDegreeObject.get().getConnectionPorts())); @@ -566,9 +548,9 @@ public class OpenRoadmTopology { LOG.info("Getting max pp ports for Srg Number {}", srgCounter); InstanceIdentifier deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) .child(SharedRiskGroup.class, new SharedRiskGroupKey(srgCounter)); - Optional ordmSrgObject = this.deviceTransactionManager.getDataFromDevice(deviceId, - LogicalDatastoreType.OPERATIONAL, deviceIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); + Optional ordmSrgObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.OPERATIONAL, deviceIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); if (ordmSrgObject.isPresent()) { if (ordmSrgObject.get().getMaxAddDropPorts() != null) { maxPpPorts = ordmSrgObject.get().getMaxAddDropPorts(); @@ -607,9 +589,9 @@ public class OpenRoadmTopology { .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName)) .child(Ports.class, new PortsKey(portName)); LOG.info("Fetching Port Direction for port {} at circuit pack {}", portName, circuitPackName); - Optional portObject = this.deviceTransactionManager.getDataFromDevice(deviceId, - LogicalDatastoreType.OPERATIONAL, portIID, Timeouts.DEVICE_READ_TIMEOUT, - Timeouts.DEVICE_READ_TIMEOUT_UNIT); + Optional portObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.OPERATIONAL, portIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); if (portObject.isPresent()) { Ports port = portObject.get(); if (port.getPortDirection() != null) { @@ -632,7 +614,7 @@ public class OpenRoadmTopology { return tpBldr; } - // This method returns the linkBuilder object for given source and destination. + // This method returns the linkBuilder object for given source and destination public LinkBuilder createLink(String srcNode, String dstNode, String srcTp, String destTp) { LOG.info("creating link for {}-{}", srcNode, dstNode); // Create Destination for link @@ -643,21 +625,24 @@ public class OpenRoadmTopology { SourceBuilder srcNodeBldr = new SourceBuilder(); srcNodeBldr.setSourceNode(new NodeId(srcNode)); srcNodeBldr.setSourceTp(srcTp); - LinkBuilder lnkBldr = new LinkBuilder(); // set link builder attribute + LinkBuilder lnkBldr = new LinkBuilder(); lnkBldr.setDestination(dstNodeBldr.build()); lnkBldr.setSource(srcNodeBldr.build()); lnkBldr.setLinkId(LinkIdUtil.buildLinkId(srcNode, srcTp, dstNode, destTp)); lnkBldr.withKey(new LinkKey(lnkBldr.getLinkId())); - org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk1Bldr = - new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1Builder lnk1Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1Builder(); + OMSAttributesBuilder omsAttributesBuilder = new OMSAttributesBuilder(); LinkId oppositeLinkId = LinkIdUtil.getOppositeLinkId(srcNode, srcTp, dstNode, destTp); - lnk1Bldr.setOppositeLink(oppositeLinkId); - lnkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1.class, - lnk1Bldr.build()); + omsAttributesBuilder.setOppositeLink(oppositeLinkId); + lnk1Bldr.setOMSAttributes(omsAttributesBuilder.build()); + lnkBldr.addAugmentation(Link1.class,lnk1Bldr.build()); return lnkBldr; } + + private List createExpressLinks(String nodeId, int numOfDegrees, int portDirectionEnum) { LOG.info("creating express links {} {} {}", nodeId, numOfDegrees, portDirectionEnum); List links = new ArrayList<>(); @@ -669,7 +654,7 @@ public class OpenRoadmTopology { String destTp; // ports are uni-directional - if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) { + if (portDirectionEnum == 1 || portDirectionEnum == 2) { LOG.info("creating uni-directional express links"); for (int i = 1; i <= numOfDegrees; i++) { for (int j = i + 1; j <= numOfDegrees; j++) { @@ -685,8 +670,12 @@ public class OpenRoadmTopology { Link1Builder lnk1Bldr = new Link1Builder(); lnk1Bldr.setLinkType(OpenroadmLinkType.EXPRESSLINK); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); - + expLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929 + .Link1.class, lnk2Bldr.build()); links.add(expLinkBldr.build()); // ZtoA direction @@ -717,9 +706,13 @@ public class OpenRoadmTopology { Link1Builder lnk1Bldr = new Link1Builder(); lnk1Bldr.setLinkType(OpenroadmLinkType.EXPRESSLINK); - LinkBuilder expLinkBldr = createLink(srcNode, destNode, srcTp, destTp); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + expLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929 + .Link1.class, lnk2Bldr.build()); links.add(expLinkBldr.build()); // ZtoA direction @@ -732,7 +725,8 @@ public class OpenRoadmTopology { return links; } - private List createAddDropLinks(String nodeId, int numOfDegrees, int numOfSrgs, int portDirectionEnum) { + private List createAddDropLinks(String nodeId, int numOfDegrees, int numOfSrgs, + int portDirectionEnum) { LOG.info("creating add-drop links {} {} {} {}", nodeId, numOfDegrees, numOfSrgs, portDirectionEnum); List links = new ArrayList<>(); @@ -743,7 +737,7 @@ public class OpenRoadmTopology { String destTp; // ports are uni-directional - if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) { + if (portDirectionEnum == 1 || portDirectionEnum == 2) { LOG.info("creating uni-directional add-drop links"); for (int i = 1; i <= numOfDegrees; i++) { for (int j = 1; j <= numOfSrgs; j++) { @@ -758,7 +752,12 @@ public class OpenRoadmTopology { LinkBuilder addDropLinkBldr = createLink(srcNode, destNode, srcTp, destTp); Link1Builder lnk1Bldr = new Link1Builder(); lnk1Bldr.setLinkType(OpenroadmLinkType.DROPLINK); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + addDropLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links + .rev170929.Link1.class, lnk2Bldr.build()); links.add(addDropLinkBldr.build()); // add links direction @@ -789,7 +788,13 @@ public class OpenRoadmTopology { LinkBuilder addDropLinkBldr = createLink(srcNode, destNode, srcTp, destTp); Link1Builder lnk1Bldr = new Link1Builder(); lnk1Bldr.setLinkType(OpenroadmLinkType.DROPLINK); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + addDropLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links + .rev170929.Link1.class, lnk2Bldr.build()); + links.add(addDropLinkBldr.build()); // add link @@ -803,28 +808,6 @@ public class OpenRoadmTopology { return links; } - // This method returns the linkBuilder object for given source and destination. - public boolean deleteLink(String srcNode, String dstNode, Integer srcDegId, - Integer destDegId ,String srcTp, String destTp) { - LOG.info("deleting link for {}-{}", srcNode, dstNode); - try { - LinkId linkId = LinkIdUtil.buildLinkId(srcNode + "-DEG" + srcDegId, - srcTp, dstNode + "-DEG" + destDegId, destTp); - LOG.info("Link is for the link is {}", linkId.getValue()); - InstanceIdentifierBuilder linkIID = InstanceIdentifier - .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) - .augmentation(Network1.class).child(Link.class, new LinkKey(linkId)); - WriteTransaction wrtx = this.dataBroker.newWriteOnlyTransaction(); - wrtx.delete(LogicalDatastoreType.CONFIGURATION, linkIID.build()); - LOG.info("Deleted"); - wrtx.submit().get(1, TimeUnit.SECONDS); - LOG.info("Submitted"); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - LOG.error(e.getMessage(), e); - return false; - } - return true; - } private List create96AvalWaveDegree() { List waveList = new ArrayList<>(); @@ -839,50 +822,24 @@ public class OpenRoadmTopology { return waveList; } - private List - create96AvalWaveSrg() { + private List create96AvalWaveSrg() { - List - waveList = new ArrayList<>(); + List waveList = new ArrayList<>(); for (int i = 1; i < 97; i++) { org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes - .AvailableWavelengthsBuilder avalBldr = - new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes - .AvailableWavelengthsBuilder(); + .AvailableWavelengthsBuilder avalBldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes + .AvailableWavelengthsBuilder(); avalBldr.setIndex((long) i); avalBldr.withKey( - new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes - .AvailableWavelengthsKey((long) i)); + new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes + .AvailableWavelengthsKey((long) i)); waveList.add(avalBldr.build()); } return waveList; } - - private class XponderPortNumber { - private int numOfLinePorts; - private int numOfClientPorts; - - XponderPortNumber() { - numOfClientPorts = 0; - numOfLinePorts = 0; - } - - public void setNumOfLinePorts(int numOfLinePorts) { - this.numOfLinePorts = numOfLinePorts; - } - - public void setNumOfClientPorts(int numOfClientPorts) { - this.numOfClientPorts = numOfClientPorts; - } - - public int getNumOfClientPorts() { - return numOfClientPorts; - } - - public int getNumOfLinePorts() { - return numOfLinePorts; - } - } } diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology22.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology22.java new file mode 100644 index 000000000..ecb21b227 --- /dev/null +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/OpenRoadmTopology22.java @@ -0,0 +1,862 @@ +/* + * Copyright © 2016 AT&T 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.transportpce.networkmodel.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.NetworkUtils; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; +import org.opendaylight.transportpce.networkmodel.dto.NodeData; +import org.opendaylight.transportpce.networkmodel.dto.TopologyShard; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.NodeTypes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev170929.State; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes.AvailableWavelengths; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes.AvailableWavelengthsBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes.AvailableWavelengthsKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.pack.Ports; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.pack.PortsKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.packs.CircuitPacks; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.packs.CircuitPacksKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.degree.ConnectionPorts; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.OrgOpenroadmDevice; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.Degree; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.DegreeKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.Info; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.SharedRiskGroup; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.SharedRiskGroupKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.NetworkTypes1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.NetworkTypes1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.network.types.OpenroadmTopologyBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.DegreeAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.SrgAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrClientAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrNetworkAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmLinkType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmNodeType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmTpType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NodeId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NetworkTypesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.Node; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NodeKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.node.SupportingNode; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.node.SupportingNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.node.SupportingNodeKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.LinkId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Network1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Network1Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.TpId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.Link; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.LinkBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.LinkKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.node.TerminationPoint; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.node.TerminationPointBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.node.TerminationPointKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OpenRoadmTopology22 { + + private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmTopology22.class); + private static final int DEFAULT_PORT_DIRECTION = -1; + private static final int MAX_DEGREE = 20; + private static final int MAX_SRG = 20; + + private NetworkTransactionService networkTransactionService; + private final DeviceTransactionManager deviceTransactionManager; + + public OpenRoadmTopology22(NetworkTransactionService networkTransactionService, + DeviceTransactionManager deviceTransactionManager) { + this.networkTransactionService = networkTransactionService; + this.deviceTransactionManager = deviceTransactionManager; + } + + /** + * This public method creates the OpenROADM Topology + * Layer and posts it to the controller. + */ + public void createTopoLayer() { + try { + Network openRoadmTopology = createOpenRoadmTopology(); + InstanceIdentifierBuilder nwIID = InstanceIdentifier.builder(Network.class, + new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))); + + this.networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, nwIID.build(), openRoadmTopology); + this.networkTransactionService.submit().get(1, TimeUnit.SECONDS); + LOG.info("OpenRoadm-Topology created successfully."); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + LOG.warn("Failed to create OpenRoadm-Topology", e); + } + } + + /** + * Create empty OpenROADM topology. + */ + private Network createOpenRoadmTopology() { + NetworkBuilder nwBuilder = new NetworkBuilder(); + NetworkId nwId = new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID); + nwBuilder.setNetworkId(nwId); + nwBuilder.withKey(new NetworkKey(nwId)); + NetworkTypes1Builder topoNetworkTypesBldr = new NetworkTypes1Builder(); + topoNetworkTypesBldr.setOpenroadmTopology(new OpenroadmTopologyBuilder().build()); + NetworkTypesBuilder nwTypeBuilder = new NetworkTypesBuilder(); + nwTypeBuilder.addAugmentation(NetworkTypes1.class, topoNetworkTypesBldr.build()); + nwBuilder.setNetworkTypes(nwTypeBuilder.build()); + // Array to store nodes in the topolayer of a roadm/Xponder + Network1Builder nwBldr1 = new Network1Builder(); + // adding expressLinks + nwBldr1.setLink(Collections.emptyList()); + nwBuilder.addAugmentation(Network1.class, nwBldr1.build()); + nwBuilder.setNode(Collections.emptyList()); + return nwBuilder.build(); + } + + public TopologyShard createTopologyShard(String nodeId) { + int numOfDegrees; + int numOfSrgs; + int portDirectionEnum = DEFAULT_PORT_DIRECTION; + + InstanceIdentifier infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class); + java.util.Optional deviceInfoOpt = + deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.CONFIGURATION, infoIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + Info deviceInfo; + if (deviceInfoOpt.isPresent()) { + deviceInfo = deviceInfoOpt.get(); + } else { + LOG.error("Unable to get device info for device {}!", nodeId); + return null; + } + List nodes = new ArrayList<>(); + + // Check if node is ROADM + if (NodeTypes.Rdm.equals(deviceInfo.getNodeType())) { + + /* + * Adding Degree Node Get Degree Number -> x then get connection ports then find the port directions + * to decide whether TX/RX/TXRX Get value for max degree from info subtree, required for iteration + * if not present assume to be 20 (temporary) + */ + + Integer maxDegree; + if (deviceInfo.getMaxDegrees() != null) { + maxDegree = deviceInfo.getMaxDegrees(); + } else { + maxDegree = MAX_DEGREE; + } + + // Starting with degree Number = 1 + Integer degreeCounter = 1; + + while (degreeCounter <= maxDegree) { + LOG.info("creating degree node {}/{}", degreeCounter, maxDegree); + NodeData nodeData = createDegreeNode(nodeId, degreeCounter); + if (nodeData != null) { + NodeBuilder tempNode = nodeData.getNodeBuilder(); + portDirectionEnum = nodeData.getPortDirectionEnum(); + nodes.add(tempNode.build()); + degreeCounter++; + } + // null returned if Degree number= degreeCounter not present in the device + else { + break; + } + } + numOfDegrees = degreeCounter - 1; + + Integer maxSrg; + if (deviceInfo.getMaxSrgs() != null) { + maxSrg = deviceInfo.getMaxSrgs(); + } else { + maxSrg = MAX_SRG; + } + + // Starting with degree Number = 1 + Integer srgCounter = 1; + + while (srgCounter <= maxSrg) { + LOG.info("creating SRG node {}/{}", srgCounter, maxSrg); + NodeBuilder tempNode = createSrgNode(nodeId, srgCounter, portDirectionEnum); + + if (tempNode != null) { + nodes.add(tempNode.build()); + srgCounter++; + } else { + // null returned if Degree number= degreeCounter not present in the device + break; + } + } + numOfSrgs = srgCounter - 1; + + + LOG.info("adding links numOfDegrees={} numOfSrgs={}", numOfDegrees, numOfSrgs); + List links = new ArrayList<>(); + links.addAll(createExpressLinks(nodeId, numOfDegrees, portDirectionEnum)); + links.addAll(createAddDropLinks(nodeId, numOfDegrees, numOfSrgs, portDirectionEnum)); + LOG.info("created nodes/links: {}/{}", nodes.size(), links.size()); + return new TopologyShard(nodes, links); + } else if (NodeTypes.Xpdr.equals(deviceInfo.getNodeType())) { + // Check if node is XPONDER + Integer clientport = getNoOfClientPorts(nodeId); + List links = new ArrayList<>(); + Integer clientCounter = 1; + Integer lineCounter = 1; + while (clientCounter <= clientport) { + NodeBuilder tempNode = createXpdr(clientCounter, lineCounter, nodeId); + if (tempNode == null) { + break; + } + nodes.add(tempNode.build()); + clientCounter++; + lineCounter++; + LOG.info("Entered this loop"); + } + return new TopologyShard(nodes, links); + } + + return null; + } + + /** + * This private method gets the list of circuit packs on a xponder. For each circuit pack on a + * Xponder, it does a get on circuit-pack subtree with circuit-pack-name as key in order to get the + * list of ports. It then iterates over the list of ports to get ports with port-qual as + * xpdr-network/xpdr-client. The line and client ports are saved as: + * + *

+ * 1. LINEn + * + *

+ * 2. CLNTn + */ + private int getNoOfClientPorts(String deviceId) { + // Creating for Xponder Line and Client Ports + InstanceIdentifier deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class); + Optional deviceObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.CONFIGURATION, deviceIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + + // Variable to keep track of number of client ports + int client = 1; + if (deviceObject.isPresent()) { + for (CircuitPacks cp : deviceObject.get().getCircuitPacks()) { + if (cp.getPorts() != null) { + for (Ports port : cp.getPorts()) { + if (port.getPortQual() != null) { + if (port.getPortQual().getIntValue() == 4) { + client++; + } + } + } + } + } + } else { + return 0; + } + return client; + } + + private NodeBuilder createXpdr(Integer clientCounter, Integer lineCounter, String nodeId) { + // Create a generic Topo Layer node + NodeBuilder nodebldr = createTopoLayerNode(nodeId); + // Create augmentation node to inorder to add degree + Node1Builder node1bldr = new Node1Builder(); + TerminationPoint1Builder tp1Bldr = new TerminationPoint1Builder(); + TerminationPointBuilder tempTpBldr; + + // set node type to Xponder + node1bldr.setNodeType(OpenroadmNodeType.XPONDER); + List tpList = new ArrayList<>(); + String nodeIdtopo = new StringBuilder().append(nodeId).append("-XPDR1").toString(); + // Ad degree node specific augmentation + nodebldr.setNodeId(new NodeId(nodeIdtopo)); + nodebldr.withKey((new NodeKey(new NodeId(nodeIdtopo)))); + nodebldr.addAugmentation(Node1.class, node1bldr.build()); + while (clientCounter != 0) { + // Create CLNT-TX termination + tempTpBldr = createTpBldr("XPDR1-CLIENT" + clientCounter); + tp1Bldr.setTpType(OpenroadmTpType.XPONDERCLIENT); + XpdrClientAttributesBuilder xpdrClntBldr = new XpdrClientAttributesBuilder(); + xpdrClntBldr.setTailEquipmentId("XPDR1-NETWORK" + clientCounter); + tp1Bldr.setXpdrClientAttributes(xpdrClntBldr.build()); + tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + clientCounter--; } + while (lineCounter != 0) { + // Create LINE-TX termination + tempTpBldr = (createTpBldr("XPDR1-NETWORK" + lineCounter)); + tp1Bldr.setTpType(OpenroadmTpType.XPONDERNETWORK); + XpdrNetworkAttributesBuilder xpdrNwAttrBldr = new XpdrNetworkAttributesBuilder(); + xpdrNwAttrBldr.setTailEquipmentId("XPDR1-CLIENT" + lineCounter); + tp1Bldr.setXpdrNetworkAttributes(xpdrNwAttrBldr.build()); + tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + lineCounter--; } + LOG.info("printing tpList {}",tpList); + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608 + .Node1Builder tpNode1 = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang + .ietf.network.topology.rev150608.Node1Builder(); + tpNode1.setTerminationPoint(tpList); + nodebldr.addAugmentation( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class, + tpNode1.build()); + LOG.info("The nodebldr {}",nodebldr); + return nodebldr; + } + + + private NodeData createDegreeNode(String nodeId, int degreeCounter) { + // Create augmentation node to inorder to add degree + Node1Builder node1bldr = new Node1Builder(); + // set node type to degree + node1bldr.setNodeType(OpenroadmNodeType.DEGREE); + + // Get connection ports on degree number = degreeCounter in order to get port + // direction + List degreeConPorts = getDegreePorts(nodeId, degreeCounter); + if (degreeConPorts == null || degreeConPorts.isEmpty()) { + return null; + } + + DegreeAttributesBuilder degAttBldr = new DegreeAttributesBuilder(); + degAttBldr.setDegreeNumber(degreeCounter); + degAttBldr.setAvailableWavelengths(create96AvalWaveDegree()); + node1bldr.setDegreeAttributes(degAttBldr.build()); + + String nodeIdtopo = new StringBuilder(nodeId).append("-DEG").append(degreeCounter).toString(); + // Create a generic Topo Layer node + NodeBuilder nodebldr = createTopoLayerNode(nodeId); + nodebldr.setNodeId(new NodeId(nodeIdtopo)); + // Ad degree node specific augmentation + nodebldr.addAugmentation(Node1.class, node1bldr.build()); + // Get Port direction + int portDirectionEnum = getPortDirection(nodeId, degreeConPorts.get(0).getCircuitPackName(), + degreeConPorts.get(0).getPortName().toString()); + + /* + * if bi-directional then create 2 tp's : + * + * --> TTP-TXRX --> CTP-TXRX + * + * if uni-directional : + * + * --> TTP-TX + * --> TTP-RX + * --> CTP-TX + * --> CTP-RX + */ + TerminationPoint1Builder tp1Bldr = new TerminationPoint1Builder(); + TerminationPointBuilder tempTpBldr; + + List tpList = new ArrayList<>(); + if (portDirectionEnum == 1 || portDirectionEnum == 2) { + // ports are uni Directional on a degree, therefore 4 termination points + // Create TTP-TX termination + + tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-TX"); + tp1Bldr.setTpType(OpenroadmTpType.DEGREETXTTP); + tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + // Create TTP-RX termination + tp1Bldr = new TerminationPoint1Builder(); + tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-RX"); + tp1Bldr.setTpType(OpenroadmTpType.DEGREERXTTP); + + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + // Create CTP-TX termination + tp1Bldr = new TerminationPoint1Builder(); + tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-TX"); + tp1Bldr.setTpType(OpenroadmTpType.DEGREETXCTP); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + // Create CTP-RX termination + tp1Bldr = new TerminationPoint1Builder(); + tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-RX"); + tp1Bldr.setTpType(OpenroadmTpType.DEGREERXCTP); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + } else if (portDirectionEnum == 3) { + // Ports are bi directional therefore 2 termination points + // Create TTP-TXRX termination + tp1Bldr = new TerminationPoint1Builder(); + tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-TXRX"); + tp1Bldr.setTpType(OpenroadmTpType.DEGREETXRXTTP); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + // Create CTP-TXRX termination + tp1Bldr = new TerminationPoint1Builder(); + tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-TXRX"); + tp1Bldr.setTpType(OpenroadmTpType.DEGREETXRXCTP); + tempTpBldr.addAugmentation(TerminationPoint1.class,tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + } + + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder tpNode1 + = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology + .rev150608.Node1Builder(); + + tpNode1.setTerminationPoint(tpList); + + nodebldr.addAugmentation( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class, + tpNode1.build()); + return new NodeData(nodebldr, portDirectionEnum); + } + + + private NodeBuilder createSrgNode(String nodeId, int srgCounter, int portDirectionEnum) { + // Create augmentation node to inorder to add degree + Node1Builder node1bldr = new Node1Builder(); + // set node type to degree + node1bldr.setNodeType(OpenroadmNodeType.SRG); + + node1bldr.setNodeType(OpenroadmNodeType.SRG); + + SrgAttributesBuilder srgAttrBldr = new SrgAttributesBuilder(); + srgAttrBldr.setAvailableWavelengths(create96AvalWaveSrg()); + node1bldr.setSrgAttributes(srgAttrBldr.build()); + // Create a generic Topo Layer node + NodeBuilder nodebldr = createTopoLayerNode(nodeId); + nodebldr.addAugmentation(Node1.class, node1bldr.build()); + + + // Get connection ports on degree number = degreeCounter in order to get port + // direction + int maxPpPorts = getMaxPp(nodeId, srgCounter); + if (maxPpPorts == -1) { + return null; + } + + + String nodeIdtopo = new StringBuilder().append(nodeId).append("-SRG").append(srgCounter).toString(); + nodebldr.setNodeId(new NodeId(nodeIdtopo)); + List tpList = new ArrayList<>(); + + TerminationPoint1Builder tp1Bldr; + TerminationPointBuilder tempTpBldr; + + for (int i = 1; i <= maxPpPorts; i++) { + if (portDirectionEnum == 1 || portDirectionEnum == 2) { + if (i >= maxPpPorts / 2) { + break; + } + // ports are uni Directional on a degree, therefore 4 termination points + // Create TTP-TX termination + tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-TX"); + tp1Bldr = new TerminationPoint1Builder(); + tp1Bldr.setTpType(OpenroadmTpType.SRGTXPP); + tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + // Create TTP-RX termination + tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-RX"); + tp1Bldr = new TerminationPoint1Builder(); + tp1Bldr.setTpType(OpenroadmTpType.SRGRXPP); + tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + + } else if (portDirectionEnum == 3) { + // Ports are bi directional therefore 2 termination points + // Create TTP-TXRX termination + tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-TXRX"); + tp1Bldr = new TerminationPoint1Builder(); + tp1Bldr.setTpType(OpenroadmTpType.SRGTXRXPP); + tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build()); + tpList.add(tempTpBldr.build()); + } + } + + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608 + .Node1Builder tpNode1 = + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf + .network.topology.rev150608.Node1Builder(); + + tpNode1.setTerminationPoint(tpList); + + nodebldr.addAugmentation( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network + .topology.rev150608.Node1.class, + tpNode1.build()); + + return nodebldr; + } + + /* + * This method will return the TTP ports in the device for a given degree number to be used by the + * node to create TTP and CTP termination point on the device + */ + private List getDegreePorts(String deviceId, Integer degreeCounter) { + List degreeConPorts = new ArrayList<>(); + LOG.info("Getting Connection ports for Degree Number {}", degreeCounter); + InstanceIdentifier deviceIID = + InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Degree.class, new DegreeKey(degreeCounter)); + + Optional ordmDegreeObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.CONFIGURATION, deviceIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + + if (ordmDegreeObject.isPresent()) { + degreeConPorts.addAll(new ArrayList<>(ordmDegreeObject.get().getConnectionPorts())); + } else { + LOG.info("Device has {} degree", (degreeCounter - 1)); + return Collections.emptyList(); + } + return degreeConPorts; + } + + private int getMaxPp(String deviceId, Integer srgCounter) { + int maxPpPorts; + LOG.info("Getting max pp ports for Srg Number {}", srgCounter); + InstanceIdentifier deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) + .child(SharedRiskGroup.class, new SharedRiskGroupKey(srgCounter)); + Optional ordmSrgObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.CONFIGURATION, deviceIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + if (ordmSrgObject.isPresent()) { + if (ordmSrgObject.get().getMaxAddDropPorts() != null) { + maxPpPorts = ordmSrgObject.get().getMaxAddDropPorts(); + } else { + LOG.info("Max add drop ports absent"); + return -1; + } + } else { + LOG.info("SRG absent"); + return -1; + } + return maxPpPorts; + } + + private NodeBuilder createTopoLayerNode(String nodeId) { + // Sets the value of Network-ref and Node-ref as a part of the supporting node + // attribute + SupportingNodeBuilder supportbldr = new SupportingNodeBuilder(); + supportbldr.withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID), new NodeId(nodeId))); + supportbldr.setNetworkRef(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID)); + supportbldr.setNodeRef(new NodeId(nodeId)); + ArrayList supportlist = new ArrayList<>(); + supportlist.add(supportbldr.build()); + NodeBuilder nodebldr = new NodeBuilder(); + nodebldr.setSupportingNode(supportlist); + return nodebldr; + } + + // Return 0 for null/error values + // Return 1 for tx + // Return 2 for rx + // Return 3 for bi-directional + + private int getPortDirection(String deviceId, String circuitPackName, String portName) { + InstanceIdentifier portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) + .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName)) + .child(Ports.class, new PortsKey(portName)); + LOG.info("Fetching Port Direction for port {} at circuit pack {}", portName, circuitPackName); + Optional portObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.CONFIGURATION, portIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + if (portObject.isPresent()) { + Ports port = portObject.get(); + if (port.getPortDirection() != null) { + return port.getPortDirection().getIntValue(); + } else { + LOG.warn("Port direction value missing for {} {}", circuitPackName, port.getPortName()); + return 0; + } + } + return 0; + } + + // This method returns a generic termination point builder for a given tpid + private TerminationPointBuilder createTpBldr(String tpId) { + TerminationPointBuilder tpBldr = new TerminationPointBuilder(); + TpId tp = new TpId(tpId); + TerminationPointKey tpKey = new TerminationPointKey(tp); + tpBldr.withKey(tpKey); + tpBldr.setTpId(tp); + return tpBldr; + } + + + + + + private List createExpressLinks(String nodeId, int numOfDegrees, int portDirectionEnum) { + LOG.info("creating express links {} {} {}", nodeId, numOfDegrees, portDirectionEnum); + List links = new ArrayList<>(); + + String srcNode; + String destNode; + + String srcTp; + String destTp; + + // ports are uni-directional + if (portDirectionEnum == 1 || portDirectionEnum == 2) { + LOG.info("creating uni-directional express links"); + for (int i = 1; i <= numOfDegrees; i++) { + for (int j = i + 1; j <= numOfDegrees; j++) { + + srcNode = nodeId + "-DEG" + i; + destNode = nodeId + "-DEG" + j; + + // AtoZ direction + srcTp = "DEG" + i + "-CTP-TX"; + destTp = "DEG" + j + "-CTP-RX"; + + LinkBuilder expLinkBldr = TopologyUtils.createLink(srcNode, destNode, srcTp, destTp); + + Link1Builder lnk1Bldr = new Link1Builder(); + lnk1Bldr.setLinkType(OpenroadmLinkType.EXPRESSLINK); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); + expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + expLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929 + .Link1.class, lnk2Bldr.build()); + + links.add(expLinkBldr.build()); + + // ZtoA direction + srcTp = "DEG" + i + "-CTP-RX"; + destTp = "DEG" + j + "-CTP-TX"; + + expLinkBldr = TopologyUtils.createLink(destNode, srcNode, destTp, srcTp); + expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + + links.add(expLinkBldr.build()); + + } + } + } + + // ports are bi-directional + if (portDirectionEnum == 3) { + LOG.info("creating bi-directional express links"); + for (int i = 1; i <= numOfDegrees; i++) { + for (int j = i + 1; j <= numOfDegrees; j++) { + + srcNode = nodeId + "-DEG" + i; + destNode = nodeId + "-DEG" + j; + + // AtoZ direction + srcTp = "DEG" + i + "-CTP-TXRX"; + destTp = "DEG" + j + "-CTP-TXRX"; + + Link1Builder lnk1Bldr = new Link1Builder(); + lnk1Bldr.setLinkType(OpenroadmLinkType.EXPRESSLINK); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); + LinkBuilder expLinkBldr = TopologyUtils.createLink(srcNode, destNode, srcTp, destTp); + expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + expLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929 + .Link1.class, lnk2Bldr.build()); + links.add(expLinkBldr.build()); + + // ZtoA direction + expLinkBldr = TopologyUtils.createLink(destNode, srcNode, destTp, srcTp); + expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + links.add(expLinkBldr.build()); + } + } + } + return links; + } + + private List createAddDropLinks(String nodeId, int numOfDegrees, int numOfSrgs, + int portDirectionEnum) { + LOG.info("creating add-drop links {} {} {} {}", nodeId, numOfDegrees, numOfSrgs, portDirectionEnum); + List links = new ArrayList<>(); + + String srcNode; + String destNode; + + String srcTp; + String destTp; + + // ports are uni-directional + if (portDirectionEnum == 1 || portDirectionEnum == 2) { + LOG.info("creating uni-directional add-drop links"); + for (int i = 1; i <= numOfDegrees; i++) { + for (int j = 1; j <= numOfSrgs; j++) { + + srcNode = nodeId + "-DEG" + i; + destNode = nodeId + "-SRG" + j; + + // drop links + srcTp = "DEG" + i + "-CTP-TX"; + destTp = "SRG" + j + "-CP-RX"; + + LinkBuilder addDropLinkBldr = TopologyUtils.createLink(srcNode, destNode, srcTp, destTp); + Link1Builder lnk1Bldr = new Link1Builder(); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); + lnk1Bldr.setLinkType(OpenroadmLinkType.DROPLINK); + addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + addDropLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links + .rev170929.Link1.class, lnk2Bldr.build()); + links.add(addDropLinkBldr.build()); + + // add links direction + srcTp = "DEG" + i + "-CTP-RX"; + destTp = "SRG" + j + "-CP-TX"; + + addDropLinkBldr = TopologyUtils.createLink(destNode, srcNode, destTp, srcTp); + lnk1Bldr.setLinkType(OpenroadmLinkType.ADDLINK); + addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + links.add(addDropLinkBldr.build()); + + } + } + } + // ports are bi-directional + if (portDirectionEnum == 3) { + LOG.info("creating bi-directional add-drop links"); + for (int i = 1; i <= numOfDegrees; i++) { + for (int j = 1; j <= numOfSrgs; j++) { + + srcNode = nodeId + "-DEG" + i; + destNode = nodeId + "-SRG" + j; + + // drop links + srcTp = "DEG" + i + "-CTP-TXRX"; + destTp = "SRG" + j + "-CP-TXRX"; + + LinkBuilder addDropLinkBldr = TopologyUtils.createLink(srcNode, destNode, srcTp, destTp); + Link1Builder lnk1Bldr = new Link1Builder(); + org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk2Bldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder(); + lnk2Bldr.setOppositeLink(LinkIdUtil.getOppositeLinkId(srcNode, srcTp, destNode, destTp)); + lnk1Bldr.setLinkType(OpenroadmLinkType.DROPLINK); + addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + addDropLinkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links + .rev170929.Link1.class, lnk2Bldr.build()); + links.add(addDropLinkBldr.build()); + + // add link + addDropLinkBldr = TopologyUtils.createLink(destNode, srcNode, destTp, srcTp); + lnk1Bldr.setLinkType(OpenroadmLinkType.ADDLINK); + addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build()); + links.add(addDropLinkBldr.build()); + } + } + } + return links; + } + + // This method returns the linkBuilder object for given source and destination + public static boolean deleteLink(String srcNode, String dstNode, String srcTp, String destTp, + NetworkTransactionService networkTransactionService) { + LOG.info("deleting link for {}-{}", srcNode, dstNode); + LinkId linkId = LinkIdUtil.buildLinkId(srcNode, srcTp, dstNode, destTp); + if (deleteLinkLinkId(linkId, networkTransactionService)) { + LOG.debug("Link Id {} updated to have admin state down"); + return true; + } else { + LOG.debug("Link Id not found for Source {} and Dest {}", srcNode, dstNode); + return false; + } + } + + // This method returns the linkBuilder object for given source and destination + public static boolean deleteLinkLinkId(LinkId linkId , NetworkTransactionService networkTransactionService) { + LOG.info("deleting link for LinkId: {}", linkId); + try { + InstanceIdentifierBuilder linkIID = InstanceIdentifier.builder(Network.class, + new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).augmentation(Network1.class) + .child(Link.class, new LinkKey(linkId)); + com.google.common.base.Optional link = + networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,linkIID.build()).get(); + if (link.isPresent()) { + LinkBuilder linkBuilder = new LinkBuilder(link.get()); + Link1Builder link1Builder = new Link1Builder(linkBuilder.augmentation(org.opendaylight + .yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1.class)); + link1Builder.setAdministrativeState(State.OutOfService); + linkBuilder.removeAugmentation(Link1.class); + linkBuilder.addAugmentation(Link1.class,link1Builder.build()); + networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, linkIID.build(), + linkBuilder.build()); + networkTransactionService.submit().get(1, TimeUnit.SECONDS); + return true; + } else { + LOG.error("No link found for given LinkId: {}", + linkId); + return false; + } + + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.error(e.getMessage(), e); + return false; + } + } + + private List create96AvalWaveDegree() { + List waveList = new ArrayList<>(); + + for (int i = 1; i < 97; i++) { + AvailableWavelengthsBuilder avalBldr = new AvailableWavelengthsBuilder(); + avalBldr.setIndex((long) i); + avalBldr.withKey(new AvailableWavelengthsKey((long) i)); + waveList.add(avalBldr.build()); + } + + return waveList; + } + + private List create96AvalWaveSrg() { + + List waveList = + new ArrayList<>(); + + for (int i = 1; i < 97; i++) { + org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes + .AvailableWavelengthsBuilder avalBldr = + new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node + .attributes.AvailableWavelengthsBuilder(); + avalBldr.setIndex((long) i); + avalBldr.withKey( + new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node + .attributes.AvailableWavelengthsKey( + (long) i)); + waveList.add(avalBldr.build()); + } + + return waveList; + } +} diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/TopologyUtils.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/TopologyUtils.java new file mode 100644 index 000000000..8fa6bdfb9 --- /dev/null +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/util/TopologyUtils.java @@ -0,0 +1,124 @@ +/* + * Copyright © 2019 AT&T 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.transportpce.networkmodel.util; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.NetworkUtils; +import org.opendaylight.transportpce.common.network.NetworkTransactionService; +//import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1; +//import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev181130.State; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev170929.State; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.link.OMSAttributesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NodeId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.LinkId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Network1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.Link; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.LinkBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.LinkKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.link.DestinationBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.link.SourceBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class TopologyUtils { + + private static final Logger LOG = LoggerFactory.getLogger(TopologyUtils.class); + + private TopologyUtils() { + } + + // This method returns the linkBuilder object for given source and destination + public static LinkBuilder createLink(String srcNode, String dstNode, String srcTp, String destTp) { + + // Create Destination for link + DestinationBuilder dstNodeBldr = new DestinationBuilder(); + dstNodeBldr.setDestTp(destTp); + dstNodeBldr.setDestNode(new NodeId(dstNode)); + + // Create Source for the link + SourceBuilder srcNodeBldr = new SourceBuilder(); + srcNodeBldr.setSourceNode(new NodeId(srcNode)); + srcNodeBldr.setSourceTp(srcTp); + + // set link builder attribute + LinkBuilder lnkBldr = new LinkBuilder(); + + lnkBldr.setDestination(dstNodeBldr.build()); + lnkBldr.setSource(srcNodeBldr.build()); + lnkBldr.setLinkId(LinkIdUtil.buildLinkId(srcNode, srcTp, dstNode, destTp)); + lnkBldr.withKey(new LinkKey(lnkBldr.getLinkId())); + + //set Oms Attributes + Link1Builder lnk1Bldr = + new Link1Builder(); + OMSAttributesBuilder omsAttributesBuilder = new OMSAttributesBuilder(); + LinkId oppositeLinkId = LinkIdUtil.getOppositeLinkId(srcNode, srcTp, dstNode, destTp); + omsAttributesBuilder.setOppositeLink(oppositeLinkId); + lnk1Bldr.setOMSAttributes(omsAttributesBuilder.build()); + lnkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929 + .Link1.class,lnk1Bldr.build()); + + return lnkBldr; + } + + // This method returns the linkBuilder object for given source and destination + public static boolean deleteLink(String srcNode, String dstNode, String srcTp, String destTp, + NetworkTransactionService networkTransactionService) { + LOG.info("deleting link for {}-{}", srcNode, dstNode); + LinkId linkId = LinkIdUtil.buildLinkId(srcNode, srcTp, dstNode, destTp); + if (deleteLinkLinkId(linkId, networkTransactionService)) { + LOG.debug("Link Id {} updated to have admin state down"); + return true; + } else { + LOG.debug("Link Id not found for Source {} and Dest {}", srcNode, dstNode); + return false; + } + } + + // This method returns the linkBuilder object for given source and destination + public static boolean deleteLinkLinkId(LinkId linkId , NetworkTransactionService networkTransactionService) { + LOG.info("deleting link for LinkId: {}", linkId); + try { + InstanceIdentifier.InstanceIdentifierBuilder linkIID = InstanceIdentifier.builder(Network.class, + new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).augmentation(Network1.class) + .child(Link.class, new LinkKey(linkId)); + com.google.common.base.Optional link = + networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,linkIID.build()).get(); + if (link.isPresent()) { + LinkBuilder linkBuilder = new LinkBuilder(link.get()); + Link1Builder link1Builder = new Link1Builder(linkBuilder.augmentation(org.opendaylight.yang.gen.v1 + .http.org.openroadm.network.topology.rev170929.Link1.class)); + link1Builder.setAdministrativeState(State.OutOfService); + linkBuilder.removeAugmentation(Link1.class); + linkBuilder.addAugmentation(Link1.class,link1Builder.build()); + networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, linkIID.build(), + linkBuilder.build()); + networkTransactionService.submit().get(1, TimeUnit.SECONDS); + return true; + } else { + LOG.error("No link found for given LinkId: {}", + linkId); + return false; + } + + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.error(e.getMessage(), e); + return false; + } + } +} diff --git a/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml b/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml index 81681b44b..ad8e86175 100644 --- a/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml +++ b/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml @@ -10,50 +10,55 @@ odl:type="default" /> - + + - - + + + + + + + + + + + + + + - - + - + + - + - - + - - - - - - - -- 2.36.6