From 2669cb5bf53da7783235d38803667cbf455c161d Mon Sep 17 00:00:00 2001 From: "guillaume.lambert" Date: Thu, 25 Apr 2024 11:34:43 +0200 Subject: [PATCH] Refactor TAPI TopologyUtils JIRA: TRNSPRTPCE-735 Signed-off-by: guillaume.lambert Change-Id: Id54f56a401141031ee762def51459f0a9f49aacf --- .../tapi/topology/TopologyUtils.java | 336 ++++++++---------- 1 file changed, 156 insertions(+), 180 deletions(-) diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TopologyUtils.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TopologyUtils.java index 9eca76d69..db93b9ebb 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TopologyUtils.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TopologyUtils.java @@ -12,7 +12,6 @@ import com.google.common.util.concurrent.ListenableFuture; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -22,7 +21,6 @@ import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.transportpce.common.InstanceIdentifiers; @@ -50,7 +48,6 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Laye import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Uuid; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.Name; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameBuilder; -import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePointKey; //import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.OwnedNodeEdgePoint1; @@ -66,7 +63,6 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.to import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.TopologyBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.TopologyKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,8 +76,8 @@ public final class TopologyUtils { private String topologicalMode; public static final String NOOPMODEDECLARED = "No operational mode declared in Topo for Tp {}, assumes by default "; - public TopologyUtils(NetworkTransactionService networkTransactionService, DataBroker dataBroker, - TapiLink tapiLink) { + public TopologyUtils( + NetworkTransactionService networkTransactionService, DataBroker dataBroker, TapiLink tapiLink) { this.networkTransactionService = networkTransactionService; this.dataBroker = dataBroker; this.tapiSips = new HashMap<>(); @@ -91,50 +87,50 @@ public final class TopologyUtils { } public Network readTopology(InstanceIdentifier networkIID) throws TapiTopologyException { - Network topology = null; ListenableFuture> topologyFuture = this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, networkIID); try { - topology = topologyFuture.get().orElseThrow(); + return topologyFuture.get().orElseThrow(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new TapiTopologyException("Unable to get from mdsal topology: " + networkIID - .firstKeyOf(Network.class).getNetworkId().getValue(), e); + throw new TapiTopologyException( + "Unable to get from mdsal topology: " + networkIID.firstKeyOf(Network.class).getNetworkId().getValue(), + e); } catch (ExecutionException e) { - throw new TapiTopologyException("Unable to get from mdsal topology: " + networkIID - .firstKeyOf(Network.class).getNetworkId().getValue(), e); + throw new TapiTopologyException( + "Unable to get from mdsal topology: " + networkIID.firstKeyOf(Network.class).getNetworkId().getValue(), + e); } catch (NoSuchElementException e) { return null; } - return topology; } public List readTopologyName(Uuid topoUuid) throws TapiTopologyException { Topology topology = null; - InstanceIdentifier topoIID = InstanceIdentifier.builder( - Context.class).augmentation(org.opendaylight.yang.gen.v1.urn - .onf.otcc.yang.tapi.topology.rev221121.Context1.class).child(TopologyContext.class) - .child(Topology.class, new TopologyKey(topoUuid)).build(); - + InstanceIdentifier topoIID = InstanceIdentifier.builder(Context.class) + .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class) + .child(TopologyContext.class) + .child(Topology.class, new TopologyKey(topoUuid)) + .build(); ListenableFuture> topologyFuture = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, topoIID); try { topology = topologyFuture.get().orElseThrow(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new TapiTopologyException("Unable to get from mdsal topology: " + topoIID - .firstKeyOf(Topology.class).getUuid().getValue(), e); + throw new TapiTopologyException( + "Unable to get from mdsal topology: " + topoIID.firstKeyOf(Topology.class).getUuid().getValue(), e); } catch (ExecutionException e) { - throw new TapiTopologyException("Unable to get from mdsal topology: " + topoIID - .firstKeyOf(Topology.class).getUuid().getValue(), e); + throw new TapiTopologyException( + "Unable to get from mdsal topology: " + topoIID.firstKeyOf(Topology.class).getUuid().getValue(), e); } catch (NoSuchElementException e) { return null; } List nameList = new ArrayList<>(); - for (Map.Entry entry : topology.getName().entrySet()) { - nameList.add(entry.getValue().getValue()); + for (Name value : topology.getName().values()) { + nameList.add(value.getValue()); } - LOG.debug("Topology nameList {} = ", nameList.toString()); + LOG.debug("Topology nameList {} = ", nameList); return nameList; } @@ -144,177 +140,160 @@ public final class TopologyUtils { String topoType = this.topologicalMode.equals("Full") ? TapiStringConstants.T0_FULL_MULTILAYER : TapiStringConstants.T0_TAPI_MULTILAYER; Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(topoType.getBytes(Charset.forName("UTF-8"))).toString()); - Name name = new NameBuilder() - .setValue(topoType) - .setValueName("TAPI Topology Name") - .build(); - if (openroadmTopo != null) { - List linkList = new ArrayList<>(); - if (openroadmTopo.augmentation(Network1.class) != null) { - linkList.addAll(openroadmTopo.augmentation(Network1.class).getLink().values()); + Name name = new NameBuilder().setValue(topoType).setValueName("TAPI Topology Name").build(); + var topoBdr = new TopologyBuilder() + .setName(Map.of(name.key(), name)) + .setUuid(topoUuid) + .setLayerProtocolName(Set.of( + LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU, + LayerProtocolName.DSR, LayerProtocolName.DIGITALOTN)); + if (openroadmTopo == null) { + return topoBdr.build(); + } + List linkList = openroadmTopo.augmentation(Network1.class) == null ? new ArrayList<>() + : new ArrayList<>(openroadmTopo.augmentation(Network1.class).getLink().values()); + List xponderOutLinkList = new ArrayList<>(); + List xponderInLinkList = new ArrayList<>(); + for (Link lk : linkList) { + switch (lk.augmentation(Link1.class).getLinkType()) { + case XPONDEROUTPUT: + xponderOutLinkList.add(lk); + break; + case XPONDERINPUT: + xponderInLinkList.add(lk); + break; + default: + break; } - List xponderOutLinkList = linkList.stream() - .filter(lk -> lk.augmentation(Link1.class).getLinkType().equals(OpenroadmLinkType.XPONDEROUTPUT)) - .collect(Collectors.toList()); - List xponderInLinkList = linkList.stream() - .filter(lk -> lk.augmentation(Link1.class).getLinkType().equals(OpenroadmLinkType.XPONDERINPUT)) - .collect(Collectors.toList()); - // read otn-topology - Network otnTopo = readTopology(InstanceIdentifiers.OTN_NETWORK_II); - Map otnNodeMap = otnTopo.nonnullNode() - .values().stream().collect(Collectors.toMap(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang - .ietf.network.rev180226.networks.network.Node::getNodeId, node -> node)); - - Map> networkPortMap = new HashMap<>(); - Iterator> itOtnNodeMap = otnNodeMap - .entrySet().iterator(); - while (itOtnNodeMap.hasNext()) { - Map.Entry entry = itOtnNodeMap.next(); - String portMappingNodeId = entry.getValue().getSupportingNode().values().stream() - .filter(sn -> sn.getNetworkRef().getValue().equals(NetworkUtils.UNDERLAY_NETWORK_ID)) - .findFirst() - .orElseThrow().getNodeRef().getValue(); - List networkPortList = new ArrayList<>(); - for (TerminationPoint tp: entry.getValue().augmentation(Node1.class).getTerminationPoint().values()) { - // TODO -> why are we checking with respect to XPDR links?? Is there a real purpose on doing that? - if (tp.augmentation(TerminationPoint1.class).getTpType().equals(OpenroadmTpType.XPONDERNETWORK) - && checkTp(entry.getKey().getValue(), portMappingNodeId, tp, xponderOutLinkList, - xponderInLinkList)) { - networkPortList.add(tp.getTpId().getValue()); - } - } - if (!networkPortList.isEmpty()) { - networkPortMap.put(entry.getKey().getValue(), networkPortList); + } + // read otn-topology + Network otnTopo = readTopology(InstanceIdentifiers.OTN_NETWORK_II); + Map + otnNodeMap = + otnTopo.nonnullNode().values().stream() + .collect(Collectors.toMap( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226 + .networks.network.Node::getNodeId, node -> node)); + Map> networkPortMap = new HashMap<>(); + for (var entry : otnNodeMap.entrySet()) { + var entVal = entry.getValue(); + String portMappingNodeId = entVal.getSupportingNode().values().stream() + .filter(sn -> sn.getNetworkRef().getValue().equals(NetworkUtils.UNDERLAY_NETWORK_ID)) + .findFirst() + .orElseThrow().getNodeRef().getValue(); + List networkPortList = new ArrayList<>(); + var entKeyVal = entry.getKey().getValue(); + for (TerminationPoint tp: entVal.augmentation(Node1.class).getTerminationPoint().values()) { + // TODO -> why are we checking with respect to XPDR links?? Is there a real purpose on doing that? + if (tp.augmentation(TerminationPoint1.class).getTpType().equals(OpenroadmTpType.XPONDERNETWORK) + && checkTp(entKeyVal, portMappingNodeId, tp, xponderOutLinkList, xponderInLinkList)) { + networkPortList.add(tp.getTpId().getValue()); } } - Map - tapiNodeList = new HashMap<>(); - Map - tapiLinkList = new HashMap<>(); - ConvertORTopoToTapiFullTopo tapiFullFactory = new ConvertORTopoToTapiFullTopo(topoUuid, this.tapiLink); - ConvertORToTapiTopology tapiFactory = new ConvertORToTapiTopology(topoUuid); - Iterator>> it = networkPortMap.entrySet().iterator(); - while (it.hasNext()) { - String nodeId = it.next().getKey(); - tapiFactory.convertNode(otnNodeMap.get(new NodeId(nodeId)), networkPortMap.get(nodeId)); - this.tapiSips.putAll(tapiFactory.getTapiSips()); - tapiFullFactory.setTapiNodes(tapiFactory.getTapiNodes()); - tapiFullFactory.setTapiSips(tapiFactory.getTapiSips()); - tapiNodeList.putAll(tapiFactory.getTapiNodes()); - tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); + if (!networkPortList.isEmpty()) { + networkPortMap.put(entKeyVal, networkPortList); } - // roadm infrastructure not abstracted - // read openroadm-network - Network openroadmNet = readTopology(InstanceIdentifiers.UNDERLAY_NETWORK_II); - if (openroadmNet != null && openroadmNet.nonnullNode().values().stream() - .filter(nt -> nt - .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class) - .getNodeType() - .equals(OpenroadmNodeType.ROADM)) - .count() > 0) { - // map roadm nodes - if (this.topologicalMode.equals("Full")) { - for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks - .network.Node roadm:openroadmNet.nonnullNode().values().stream() - .filter(nt -> nt - .augmentation( - org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class) - .getNodeType() - .equals(OpenroadmNodeType.ROADM)) - .collect(Collectors.toList())) { - tapiFullFactory.convertRoadmNode(roadm, openroadmTopo, "Full"); - this.tapiSips.putAll(tapiFullFactory.getTapiSips()); - tapiNodeList.putAll(tapiFullFactory.getTapiNodes()); - tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); - // map roadm to roadm link - List rdmTordmLinkList = linkList.stream() - .filter(lk -> lk.augmentation(Link1.class).getLinkType() - .equals(OpenroadmLinkType.ROADMTOROADM)) - .collect(Collectors.toList()); - tapiFullFactory.convertRdmToRdmLinks(rdmTordmLinkList); - tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); - } - } else { - tapiFullFactory.convertRoadmNode(null, openroadmTopo, "Abstracted"); + } + Map + tapiNodeList = new HashMap<>(); + Map + tapiLinkList = new HashMap<>(); + ConvertORTopoToTapiFullTopo tapiFullFactory = new ConvertORTopoToTapiFullTopo(topoUuid, this.tapiLink); + ConvertORToTapiTopology tapiFactory = new ConvertORToTapiTopology(topoUuid); + for (var entry : networkPortMap.entrySet()) { + tapiFactory.convertNode(otnNodeMap.get(new NodeId(entry.getKey())), entry.getValue()); + this.tapiSips.putAll(tapiFactory.getTapiSips()); + tapiFullFactory.setTapiNodes(tapiFactory.getTapiNodes()); + tapiFullFactory.setTapiSips(tapiFactory.getTapiSips()); + tapiNodeList.putAll(tapiFactory.getTapiNodes()); + tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); + } + // roadm infrastructure not abstracted + // read openroadm-network + Network openroadmNet = readTopology(InstanceIdentifiers.UNDERLAY_NETWORK_II); + List rdmList = + openroadmNet == null ? new ArrayList<>() + : openroadmNet.nonnullNode().values().stream() + .filter(nt -> nt + .augmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class) + .getNodeType() + .equals(OpenroadmNodeType.ROADM)) + .collect(Collectors.toList()); + if (rdmList.isEmpty()) { + LOG.warn("No roadm nodes exist in the network"); + } else { + // map roadm nodes + if (this.topologicalMode.equals("Full")) { + for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226 + .networks.network.Node roadm : rdmList) { + tapiFullFactory.convertRoadmNode(roadm, openroadmTopo, "Full"); this.tapiSips.putAll(tapiFullFactory.getTapiSips()); tapiNodeList.putAll(tapiFullFactory.getTapiNodes()); tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); + tapiFullFactory.convertRdmToRdmLinks( + // map roadm to roadm link + linkList.stream() + .filter(lk -> lk.augmentation(Link1.class).getLinkType() + .equals(OpenroadmLinkType.ROADMTOROADM)) + .collect(Collectors.toList())); + tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); } - } else { - LOG.warn("No roadm nodes exist in the network"); + tapiFullFactory.convertRoadmNode(null, openroadmTopo, "Abstracted"); + this.tapiSips.putAll(tapiFullFactory.getTapiSips()); + tapiNodeList.putAll(tapiFullFactory.getTapiNodes()); + tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); } - - // map xpdr_input to roadm and xpdr_output to roadm links. - xponderInLinkList.addAll(xponderOutLinkList); - tapiFullFactory.convertXpdrToRdmLinks(xponderInLinkList); - tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); - - // Retrieve created sips map in TapiFactory when mapping all the nodes - this.tapiSips.putAll(tapiFullFactory.getTapiSips()); - return new TopologyBuilder() - .setName(Map.of(name.key(), name)) - .setUuid(topoUuid) - .setNode(tapiNodeList) - .setLayerProtocolName(Set.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU, - LayerProtocolName.DSR, LayerProtocolName.DIGITALOTN)) - .setLink(tapiLinkList).build(); } - return new TopologyBuilder() - .setName(Map.of(name.key(), name)) - .setUuid(topoUuid) - .setLayerProtocolName(Set.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU, - LayerProtocolName.DSR, LayerProtocolName.DIGITALOTN)) - .build(); + // map xpdr_input to roadm and xpdr_output to roadm links. + xponderInLinkList.addAll(xponderOutLinkList); + tapiFullFactory.convertXpdrToRdmLinks(xponderInLinkList); + tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); + // Retrieve created sips map in TapiFactory when mapping all the nodes + this.tapiSips.putAll(tapiFullFactory.getTapiSips()); + return topoBdr.setNode(tapiNodeList).setLink(tapiLinkList).build(); } - public boolean checkTp(String nodeIdTopo, String nodeIdPortMap, TerminationPoint tp, List xpdOut, - List xpdIn) { + public boolean checkTp( + String nodeIdTopo, String nodeIdPortMap, TerminationPoint tp, List xpdOut, List xpdIn) { LOG.info("Inside Checktp for node {}-{}", nodeIdTopo, nodeIdPortMap); - String networkLcp; - if (tp.augmentation(TerminationPoint1.class).getTpType().equals(OpenroadmTpType.XPONDERCLIENT)) { - networkLcp = tp.augmentation( + String networkLcp = tp.augmentation(TerminationPoint1.class).getTpType().equals(OpenroadmTpType.XPONDERCLIENT) + ? tp.augmentation( org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.TerminationPoint1.class) - .getAssociatedConnectionMapTp().iterator().next().getValue(); - } else { - networkLcp = tp.getTpId().getValue(); - } + .getAssociatedConnectionMapTp().iterator().next().getValue() + : tp.getTpId().getValue(); LOG.info("Network LCP associated = {}", networkLcp); @NonNull - KeyedInstanceIdentifier pmIID = InstanceIdentifier.create( - org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.Network.class) - .child(Nodes.class, new NodesKey(nodeIdPortMap)).child(Mapping.class, new MappingKey(networkLcp)); - @NonNull FluentFuture> mappingOpt = this.dataBroker.newReadOnlyTransaction().read( - LogicalDatastoreType.CONFIGURATION, pmIID); + LogicalDatastoreType.CONFIGURATION, + InstanceIdentifier.create( + org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.Network.class) + .child(Nodes.class, new NodesKey(nodeIdPortMap)) + .child(Mapping.class, new MappingKey(networkLcp))); + if (!mappingOpt.isDone()) { + LOG.error("Impossible to get mapping of associated network port {} of tp {}", + networkLcp, tp.getTpId().getValue()); + return false; + } Mapping mapping = null; - if (mappingOpt.isDone()) { - try { - mapping = mappingOpt.get().orElseThrow(); - } catch (InterruptedException | ExecutionException e) { - LOG.error("Error getting mapping for {}", networkLcp,e); - return false; - } - } else { - LOG.error("Impossible to get mapping of associated network port {} of tp {}", networkLcp, tp.getTpId() - .getValue()); + try { + mapping = mappingOpt.get().orElseThrow(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Error getting mapping for {}", networkLcp, e); return false; } LOG.info("Mapping found = {}", mapping); - String networkPortDirection = mapping.getPortDirection(); - switch (networkPortDirection) { + switch (mapping.getPortDirection()) { // TODO -> remove the part of counting only if the Network LCP is part of a Link. // We want to have all OTN nodes in the TAPI topology case "bidirectional": return true; case "tx": case "rx": - @Nullable - String partnerLcp = mapping.getPartnerLcp(); - LOG.info("PartnerLCP = {}", partnerLcp); + LOG.info("PartnerLCP = {}", mapping.getPartnerLcp()); return true; default: LOG.error("Invalid port direction for {}", networkLcp); @@ -322,16 +301,14 @@ public final class TopologyUtils { } } - public org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.get.topology.details.output.Topology - transformTopology(Topology topology) { - org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121 - .get.topology.details.output.TopologyBuilder topologyBuilder = - new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121 - .get.topology.details.output.TopologyBuilder() - .setUuid(topology.getUuid()) - .setName(topology.getName()) - .setLayerProtocolName(topology.getLayerProtocolName()) - .setLink(topology.getLink()); + public org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121 + .get.topology.details.output.Topology transformTopology(Topology topology) { + var topologyBuilder = new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121 + .get.topology.details.output.TopologyBuilder() + .setUuid(topology.getUuid()) + .setName(topology.getName()) + .setLayerProtocolName(topology.getLayerProtocolName()) + .setLink(topology.getLink()); if (topology.nonnullNode().isEmpty()) { return topologyBuilder.build(); } @@ -376,8 +353,7 @@ public final class TopologyUtils { .build(); mapNode.put(newNode.key(), newNode); } - topologyBuilder.setNode(mapNode); - return topologyBuilder.build(); + return topologyBuilder.setNode(mapNode).build(); } public Map getSipMap() { -- 2.36.6