From 652c9098f8d97e6f5a723a7c55929f9351bffb5b Mon Sep 17 00:00:00 2001 From: orenais Date: Fri, 23 Feb 2024 17:34:04 +0100 Subject: [PATCH] Refactor TAPI 2.4 JIRA: TRNSPRTPCE-735 Signed-off-by: orenais Change-Id: Iebccbefb0ddfb1ec902916a18e9447046c7101e2 --- .../tapi/TapiStringConstants.java | 11 + .../tapi/impl/rpc/GetTopologyDetailsImpl.java | 103 +++- .../topology/ConvertORToTapiTopology.java | 552 +++++++++++++++--- .../topology/ConvertORTopoToTapiFullTopo.java | 231 +++++++- .../topology/ConvertORTopoToTapiTopo.java | 23 +- .../topology/ConvertTapiTopoToAbstracted.java | 194 ++++++ .../topology/TapiNetworkModelServiceImpl.java | 463 +++++++++++---- .../topology/TapiPortMappingListener.java | 4 + .../tapi/topology/TopologyUtils.java | 70 ++- .../transportpce/tapi/utils/TapiContext.java | 4 +- .../transportpce/tapi/utils/TapiLinkImpl.java | 6 +- .../ConvertORTopoToFullTapiTopoTest.java | 51 +- .../topology/ConvertORTopoToTapiTopoTest.java | 8 +- .../tapi/topology/TapiTopologyImplTest.java | 2 +- .../tapi/test01_abstracted_topology.py | 4 +- 15 files changed, 1426 insertions(+), 300 deletions(-) create mode 100644 tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertTapiTopoToAbstracted.java diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/TapiStringConstants.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/TapiStringConstants.java index a1adfff6a..0efaaccae 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/TapiStringConstants.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/TapiStringConstants.java @@ -13,8 +13,19 @@ public final class TapiStringConstants { public static final String OMS_RDM_RDM_LINK = "tapi-rdm-rdm-link"; public static final String OMS_XPDR_RDM_LINK = "tapi-xpdr-rdm-link"; public static final String OTN_XPDR_XPDR_LINK = "tapi-otn-xpdr-xpdr-link"; + public static final String VALUE_NAME_OTN_XPDR_XPDR_LINK = "otn link name"; + public static final String VALUE_NAME_OTS_XPDR_RDM_LINK = "Xpdr to roadm link"; + public static final String VALUE_NAME_OMS_RDM_RDM_LINK = "OMS link name"; + public static final String VALUE_NAME_ROADM_NODE = "roadm node name"; + public static final String VALUE_NAME_XPDR_NODE = "dsr/odu node name"; public static final String T0_MULTILAYER = "T0 - Multi-layer topology"; + public static final String T0_TAPI_MULTILAYER = "T0 - Tapi-Multi-layer Abstracted topology"; public static final String T0_FULL_MULTILAYER = "T0 - Full Multi-layer topology"; + // TODO: these hardcoded UUID are here for debugging purpose. + // They allow to have a reference somewhere of the UUID to be used when testing. + public static final String T0_MULTILAYER_UUID = "747c670e-7a07-3dab-b379-5b1cd17402a3"; + public static final String T0_TAPI_MULTILAYER_UUID = "a6c5aed1-dc75-333a-b3a3-b6b70534eae8"; + public static final String T0_FULL_MULTILAYER_UUID = "393f09a4-0a0b-3d82-a4f6-1fbbc14ca1a8"; public static final String TPDR_100G = "Transponder 100GE"; public static final String DSR = "DSR"; public static final String ODU = "ODU"; diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/rpc/GetTopologyDetailsImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/rpc/GetTopologyDetailsImpl.java index eb7c163ab..e2da5de36 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/rpc/GetTopologyDetailsImpl.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/rpc/GetTopologyDetailsImpl.java @@ -31,6 +31,7 @@ import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.tapi.TapiStringConstants; import org.opendaylight.transportpce.tapi.topology.ConvertORToTapiTopology; import org.opendaylight.transportpce.tapi.topology.ConvertORTopoToTapiTopo; +import org.opendaylight.transportpce.tapi.topology.ConvertTapiTopoToAbstracted; import org.opendaylight.transportpce.tapi.topology.TapiTopologyException; import org.opendaylight.transportpce.tapi.topology.TopologyUtils; import org.opendaylight.transportpce.tapi.utils.TapiContext; @@ -111,53 +112,68 @@ public class GetTopologyDetailsImpl implements GetTopologyDetails { @Override public ListenableFuture> invoke(GetTopologyDetailsInput input) { org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.Topology topology; - Uuid topologyUuidAbs = new Uuid(UUID - .nameUUIDFromBytes(TapiStringConstants.T0_MULTILAYER.getBytes(Charset.forName("UTF-8"))).toString()); - Uuid topologyUuidFull = new Uuid( - UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER.getBytes(Charset.forName("UTF-8"))) - .toString()); + Uuid topologyUuidFull = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER.getBytes( + Charset.forName("UTF-8"))).toString()); if (input.getTopologyId().equals(topologyUuidFull)) { Context context = this.tapiContext.getTapiContext(); - Map topologyMap = context - .augmentation(Context1.class).getTopologyContext().getTopology(); + Map + topologyMap = context.augmentation(Context1.class).getTopologyContext().getTopology(); if (topologyMap == null || !topologyMap.containsKey(new TopologyKey(topologyUuidFull))) { LOG.error("Topology {} not found in datastore", input.getTopologyId()); return RpcResultBuilder.failed() - .withError(ErrorType.RPC, "Invalid Topology name") - .buildFuture(); + .withError(ErrorType.RPC, "Invalid Topology name") + .buildFuture(); } topology = topologyMap.get(new TopologyKey(input.getTopologyId())); - return RpcResultBuilder - .success(new GetTopologyDetailsOutputBuilder() - .setTopology(this.topologyUtils.transformTopology(topology)).build()) + return RpcResultBuilder.success(new GetTopologyDetailsOutputBuilder() + .setTopology(this.topologyUtils.transformTopology(topology)) + .build()) + .buildFuture(); + } + Uuid topologyUuidTapiAbs = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_TAPI_MULTILAYER.getBytes( + Charset.forName("UTF-8"))).toString()); + if (input.getTopologyId().equals(topologyUuidTapiAbs)) { + try { + LOG.info("Building TAPI Topology abstraction for {}", input.getTopologyId()); + topology = createAbsTopologyFromTapiTopo(); + return RpcResultBuilder.success(new GetTopologyDetailsOutputBuilder() + .setTopology(this.topologyUtils.transformTopology(topology)).build()) + .buildFuture(); + } catch (TapiTopologyException e) { + LOG.error("error building TAPI topology"); + return RpcResultBuilder.failed() + .withError(ErrorType.RPC, "Error building topology") .buildFuture(); + } } - Uuid topologyUuid100G = new Uuid( - UUID.nameUUIDFromBytes(TapiStringConstants.TPDR_100G.getBytes(Charset.forName("UTF-8"))).toString()); + Uuid topologyUuid100G = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.TPDR_100G.getBytes( + Charset.forName("UTF-8"))).toString()); + Uuid topologyUuidAbs = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_MULTILAYER.getBytes( + Charset.forName("UTF-8"))).toString()); if (topologyUuid100G.equals(input.getTopologyId()) || topologyUuidAbs.equals(input.getTopologyId())) { try { LOG.info("Building TAPI Topology abstraction for {}", input.getTopologyId()); topology = createAbstractedOtnTopology(); if (input.getTopologyId().equals(topologyUuidAbs)) { - return RpcResultBuilder - .success(new GetTopologyDetailsOutputBuilder() - .setTopology(this.topologyUtils.transformTopology(topology)).build()) - .buildFuture(); + return RpcResultBuilder.success(new GetTopologyDetailsOutputBuilder() + .setTopology(this.topologyUtils.transformTopology(topology)).build()) + .buildFuture(); } topology = createAbstracted100GTpdrTopology(topology); return RpcResultBuilder.success(new GetTopologyDetailsOutputBuilder() - .setTopology(this.topologyUtils.transformTopology(topology)).build()).buildFuture(); + .setTopology(this.topologyUtils.transformTopology(topology)).build()) + .buildFuture(); } catch (TapiTopologyException e) { LOG.error("error building TAPI topology"); return RpcResultBuilder.failed() - .withError(ErrorType.RPC, "Error building topology") - .buildFuture(); + .withError(ErrorType.RPC, "Error building topology") + .buildFuture(); } } return RpcResultBuilder.failed() - .withError(ErrorType.RPC, "Invalid Topology name") - .buildFuture(); + .withError(ErrorType.RPC, "Invalid Topology name") + .buildFuture(); } public org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.Topology @@ -266,7 +282,44 @@ public class GetTopologyDetailsImpl implements GetTopologyDetails { .onf.otcc.yang.tapi.topology.rev221121.topology.context.TopologyBuilder() .setName(Map.of(name.key(), name)).setUuid(topoUuid).setNode(tapiNodeList) .setLayerProtocolName(Set.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.DIGITALOTN)) - .setLink(tapiLinkList).build(); + .setLink(tapiLinkList) + .build(); + } + + public org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.Topology + createAbsTopologyFromTapiTopo() throws TapiTopologyException { + Uuid refTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString()); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.Topology tapiFullTopo = + this.tapiContext + .getTopologyContext().entrySet().stream().filter(topo -> topo.getKey().getUuid().equals(refTopoUuid)) + .findAny().orElseThrow().getValue(); + ConvertTapiTopoToAbstracted absTapiTopo = new ConvertTapiTopoToAbstracted(refTopoUuid); + absTapiTopo.setTapiLinks(tapiFullTopo.getLink()); + absTapiTopo.setTapiNodes(tapiFullTopo.getNode()); + absTapiTopo.convertRoadmInfrastructure(); + + Map + tapiNodeList = new HashMap<>(); + Map + tapiLinkList = new HashMap<>(); + tapiNodeList.putAll(absTapiTopo.getTapiNodes()); + tapiLinkList.putAll(absTapiTopo.getTapiLinks()); + Name name = new NameBuilder() + .setValue(TapiStringConstants.T0_MULTILAYER) + .setValueName("TAPI Topology Name") + .build(); + Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_TAPI_MULTILAYER + .getBytes(Charset.forName("UTF-8"))).toString()); + LOG.info("ABSTRACTED TAPI TOPOLOGY : the list of node is as follows {}", tapiNodeList); + return new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context + .TopologyBuilder() + .setName(Map.of(name.key(), name)) + .setUuid(topoUuid) + .setNode(tapiNodeList) + .setLayerProtocolName(Set.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.DIGITALOTN)) + .setLink(tapiLinkList) + .build(); } private Network readTopology(InstanceIdentifier networkIID) throws TapiTopologyException { diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java index c4f589036..b7526590a 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java @@ -10,6 +10,7 @@ package org.opendaylight.transportpce.tapi.topology; import java.math.RoundingMode; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -19,11 +20,16 @@ import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import org.opendaylight.transportpce.common.fixedflex.GridConstant; +import org.opendaylight.transportpce.common.fixedflex.GridUtils; import org.opendaylight.transportpce.tapi.TapiStringConstants; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.TerminationPoint1; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev230526.degree.used.wavelengths.UsedWavelengths; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev230526.degree.used.wavelengths.UsedWavelengthsKey; import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.termination.point.PpAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.termination.point.TxTtpAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.termination.point.XpdrNetworkAttributes; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev230526.xpdr.odu.switching.pools.OduSwitchingPools; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev230526.xpdr.odu.switching.pools.OduSwitchingPoolsBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev230526.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingList; @@ -66,17 +72,28 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.dsr.rev221121.DIGITAL import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTS; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTSi; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTSiMC; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.context.topology.context.topology.node.owned.node.edge.point.PhotonicMediaNodeEdgePointSpec; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.context.topology.context.topology.node.owned.node.edge.point.PhotonicMediaNodeEdgePointSpecBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.photonic.media.node.edge.point.spec.SpectrumCapabilityPacBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.AvailableSpectrum; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.AvailableSpectrumBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.AvailableSpectrumKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.OccupiedSpectrum; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.OccupiedSpectrumBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.OccupiedSpectrumKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.SupportableSpectrum; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.SupportableSpectrumBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.spectrum.capability.pac.SupportableSpectrumKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.FORWARDINGRULE; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.FORWARDINGRULECANNOTFORWARDACROSSGROUP; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.FORWARDINGRULEMAYFORWARDACROSSGROUP; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.RuleType; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.inter.rule.group.AssociatedNodeRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.inter.rule.group.AssociatedNodeRuleGroupBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.inter.rule.group.AssociatedNodeRuleGroupKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroupBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroupKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroup; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupKey; @@ -206,37 +223,148 @@ public class ConvertORToTapiTopology { tapiNodes.put(dsrNode.key(), dsrNode); } - public Map createNodeRuleGroupForRdmNode( - String topoType, Uuid nodeUuid, String orNodeId, Collection onepl) { + public Map createNodeRuleGroupForRdmNode(String topoType, Uuid nodeUuid, + String subNodeName, List onepl, FORWARDINGRULE forwardingRule, int index) { Map - nepMap = new HashMap<>(); - for (OwnedNodeEdgePoint onep : onepl) { - var nep = new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121 - .node.rule.group.NodeEdgePointBuilder() + nepMap = new HashMap<>(); + for (OwnedNodeEdgePointKey onepKey : onepl) { + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.rule.group.NodeEdgePoint + nep = new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.rule.group + .NodeEdgePointBuilder() .setTopologyUuid(tapiTopoUuid) .setNodeUuid(nodeUuid) - .setNodeEdgePointUuid(onep.key().getUuid()) + .setNodeEdgePointUuid(onepKey.getUuid()) .build(); nepMap.put(nep.key(), nep); } + String nrgNameValue = String.join("-", subNodeName, "node-rule-group-" + index); + //Map nodeRuleGroupMap = new HashMap<>(); + Set ruleTypes = new HashSet<>(Set.of(RuleType.FORWARDING)); + Map ruleList = new HashMap<>(); Rule rule = new RuleBuilder() .setLocalId("forward") - .setForwardingRule(FORWARDINGRULEMAYFORWARDACROSSGROUP.VALUE) - .setRuleType(new HashSet<>(Set.of(RuleType.FORWARDING))) + .setForwardingRule(forwardingRule) + .setRuleType(ruleTypes) + .build(); + ruleList.put(rule.key(), rule); + Name nrgName = new NameBuilder() + .setValueName("nrg name") + .setValue(nrgNameValue) .build(); NodeRuleGroup nodeRuleGroup = new NodeRuleGroupBuilder() - .setUuid(new Uuid(UUID.nameUUIDFromBytes(( - topoType.equals("Abstracted") ? "rdm infra node rule group" : orNodeId + " node rule group") + .setName(Map.of(nrgName.key(), nrgName)) + .setUuid(new Uuid(UUID.nameUUIDFromBytes((nrgNameValue) .getBytes(Charset.forName("UTF-8"))).toString())) - .setRule(new HashMap<>(Map.of(rule.key(), rule))) + .setRule(ruleList) .setNodeEdgePoint(nepMap) .build(); return new HashMap<>(Map.of(nodeRuleGroup.key(), nodeRuleGroup)); } - public Map createMSIP( - int nb, LayerProtocolName layerProtocol, String tpId, String nodeid, + public Map createAllNodeRuleGroupForRdmNode(String topoType, Uuid nodeUuid, + String orNodeId, Collection onepl) { + List otsNepList = new ArrayList<>(); + LOG.info("Creating NRG for {} {}", topoType, otsNepList.toString()); + if (topoType.equals("T0ML")) { + otsNepList = onepl.stream().collect(Collectors.toList()); + } else { + otsNepList = onepl.stream() + .filter(onep -> onep.getName().keySet().contains(new NameKey("PHOTONIC_MEDIA_OTSNodeEdgePoint"))) + .collect(Collectors.toList()); + } + List degOnepKeyList = new ArrayList<>(); + List srgNames = new ArrayList<>(); + Map srgMap = new HashMap<>(); + for (OwnedNodeEdgePoint onep : otsNepList) { + String onepName = onep.getName().get(new NameKey( + topoType.equals("T0ML") ? "NodeEdgePoint name" + : "PHOTONIC_MEDIA_OTSNodeEdgePoint")).getValue(); + String subNodeName = topoType.equals("T0ML") ? "ROADMINFRA-SRG-PP" + : String.join("-", onepName.split("\\+")[0], onepName.split("\\+")[2]); + if (subNodeName.contains("DEG")) { + subNodeName = subNodeName.split("\\-TTP")[0]; + degOnepKeyList.add(onep.key()); + } else if (subNodeName.contains("SRG")) { + subNodeName = subNodeName.split("\\-PP")[0]; + srgMap.put(onep.key(), subNodeName); + if (!srgNames.contains(subNodeName)) { + srgNames.add(subNodeName); + } + } + } + int index = 0; + Map globalNrgMap = new HashMap<>(); + if (topoType.equals("Full")) { + globalNrgMap.putAll( + createNodeRuleGroupForRdmNode(topoType, nodeUuid, String.join("-", orNodeId, "DEG"), degOnepKeyList, + FORWARDINGRULEMAYFORWARDACROSSGROUP.VALUE, index)); + index++; + } + for (String srgName : srgNames) { + globalNrgMap.putAll(createNodeRuleGroupForRdmNode(topoType, nodeUuid, srgName, + srgMap.entrySet().stream() + .filter(item -> item.getValue().equals(srgName)) + .map(item -> item.getKey()) + .collect(Collectors.toList()), + // For T0ML we consider any port of ROADM INFRA can connect to potentially any other port + //topoType.equals("T0ML") ? FORWARDINGRULEMAYFORWARDACROSSGROUP.VALUE + topoType.equals("T0ML") ? FORWARDINGRULEMAYFORWARDACROSSGROUP.VALUE + // Whereas for Abstracted or Full Topology we consider any port of the same SRG can not forward to + // another port of the same SRG. Connectivity between SRGS will be defined through inter-rule-group + : FORWARDINGRULECANNOTFORWARDACROSSGROUP.VALUE, index)); + index++; + LOG.debug("AllNodeRuleGroup : creating a NRG for {}", srgName); + } + return globalNrgMap; + } + + public Map createInterRuleGroupForRdmNode( + String topoType, Uuid nodeUuid,String orNodeId, List nrgList) { + Map associatedNrgMap = new HashMap<>(); + for (NodeRuleGroupKey nrgKey : nrgList) { + AssociatedNodeRuleGroup associatedNrg = new AssociatedNodeRuleGroupBuilder() + .setTopologyUuid(tapiTopoUuid) + .setNodeUuid(nodeUuid) + .setNodeRuleGroupUuid(nrgKey.getUuid()) + .build(); + associatedNrgMap.put(associatedNrg.key(), associatedNrg); + } + String irgNameValue = + topoType.equals("Full") + ? orNodeId + " inter rule group-" + : "rdm infra inter rule group-"; + Set ruleTypes = new HashSet<>(Set.of(RuleType.FORWARDING)); + Map ruleMap + = new HashMap<>(); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.inter.rule.group.Rule rule + = new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.inter.rule.group.RuleBuilder() + .setLocalId("forward") + .setForwardingRule(FORWARDINGRULEMAYFORWARDACROSSGROUP.VALUE) + .setRuleType(ruleTypes) + .build(); + ruleMap.put(rule.key(), rule); + + Map interRuleGroupMap = new HashMap<>(); + + Name irgName = new NameBuilder() + .setValueName("irg name") + .setValue(irgNameValue) + .build(); + InterRuleGroup interRuleGroup = new InterRuleGroupBuilder() + .setUuid(new Uuid(UUID.nameUUIDFromBytes((irgNameValue) + .getBytes(Charset.forName("UTF-8"))).toString())) + .setName(Map.of(irgName.key(), irgName)) + .setRule(ruleMap) + .setAssociatedNodeRuleGroup(associatedNrgMap) + .build(); + interRuleGroupMap.put(new InterRuleGroupKey(interRuleGroup.getUuid()), interRuleGroup); + return interRuleGroupMap; + } + + public Map createMSIP(int nb, + LayerProtocolName layerProtocol, String tpId, String nodeid, Collection supportedInterfaceCapability, OperationalState operState, AdministrativeState adminState) { // add them to SIP context @@ -556,84 +684,344 @@ public class ConvertORToTapiTopology { if (tpAug == null || tpAug.getXpdrNetworkAttributes() == null) { return null; } + XpdrNetworkAttributes xnatt = tpAug.getXpdrNetworkAttributes(); + //Map freqWidthMap = new HashMap<>(); var xnattWvlgth = tpAug.getXpdrNetworkAttributes().getWavelength(); return xnattWvlgth == null || xnattWvlgth.getFrequency() == null || xnattWvlgth.getWidth() == null ? null : new HashMap<>(Map.of( - xnattWvlgth.getFrequency().getValue().doubleValue(), - xnattWvlgth.getWidth().getValue().doubleValue())); + (xnatt.getWavelength().getFrequency().getValue().doubleValue() + - xnatt.getWavelength().getWidth().getValue().doubleValue() * 0.001 / 2), + (xnatt.getWavelength().getFrequency().getValue().doubleValue() + - xnatt.getWavelength().getWidth().getValue().doubleValue() * 0.001 / 2))); } public Map getPPUsedWavelength(TerminationPoint tp) { - PpAttributes ppAtt = tp.augmentation( - org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1.class) - .getPpAttributes(); - return ppAtt == null || ppAtt.getUsedWavelength() == null - || ppAtt.getUsedWavelength().entrySet().iterator().next() == null - ? null - : new HashMap<>(Map.of( - ppAtt.getUsedWavelength().entrySet().iterator().next().getValue().getFrequency().getValue().doubleValue(), - ppAtt.getUsedWavelength().entrySet().iterator().next().getValue().getFrequency().getValue().doubleValue())); + var tpAug = tp.augmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1.class); + if (tpAug == null) { + return null; + } + PpAttributes ppAtt = tpAug.getPpAttributes(); + if (ppAtt == null) { + return null; + } + if (ppAtt != null && ppAtt.getUsedWavelength() != null + && ppAtt.getUsedWavelength().entrySet().iterator().next() != null) { + Double centFreq = ppAtt.getUsedWavelength().entrySet().iterator().next().getValue().getFrequency() + .getValue().doubleValue(); + Double width = ppAtt.getUsedWavelength().entrySet().iterator().next().getValue().getWidth() + .getValue().doubleValue(); + return new HashMap<>(Map.of(centFreq - width * 0.001 / 2, centFreq + width * 0.001 / 2)); + } + return null; } - public OwnedNodeEdgePointBuilder addPayloadStructureAndPhotSpecToOnep( - String nodeId, Map freqWidthMap, List operModeList, - Collection sicColl, OwnedNodeEdgePointBuilder onepBldr, String keyword) { - if (!String.join("+", nodeId, TapiStringConstants.OTSI_MC).equals(keyword) - && !String.join("+", nodeId, TapiStringConstants.PHTNC_MEDIA_OTS).equals(keyword)) { - return onepBldr; + public Map getTTPUsedFreqMap(TerminationPoint tp) { + byte[] byteArray = new byte[GridConstant.NB_OCTECTS]; + Arrays.fill(byteArray, (byte) GridConstant.AVAILABLE_SLOT_VALUE); + var termPoint1 = tp.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526 + .TerminationPoint1.class); + if (termPoint1 == null || termPoint1.getTxTtpAttributes() == null) { + return null; + } + TxTtpAttributes txttpAtt = termPoint1.getTxTtpAttributes(); + Map freqMap = new HashMap<>(); + if (txttpAtt.getUsedWavelengths() != null + && txttpAtt.getUsedWavelengths().entrySet().iterator().next() != null) { + for (Map.Entry usedLambdas : + txttpAtt.getUsedWavelengths().entrySet()) { + Double centFreq = usedLambdas.getValue().getFrequency().getValue().doubleValue(); + Double width = usedLambdas.getValue().getWidth() + .getValue().doubleValue(); + freqMap.put(centFreq - width * 0.001 / 2, centFreq + width * 0.001 / 2); + } + return freqMap; + } else if (txttpAtt.getAvailFreqMaps() != null + && txttpAtt.getAvailFreqMaps().keySet().toString().contains(GridConstant.C_BAND)) { + byte[] freqBitSet = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", freqBitSet); + freqBitSet = txttpAtt.getAvailFreqMaps().entrySet().stream() + .filter(afm -> afm.getKey().toString().equals(GridConstant.C_BAND)) + .findFirst().orElseThrow().getValue().getFreqMap(); + for (int i = 0; i < GridConstant.EFFECTIVE_BITS; i++) { + if (freqBitSet[i] == 0) { + freqBitSet[i] = 1; + } else { + freqBitSet[i] = 0; + } + } + return getFreqMapFromBitSet(freqBitSet); + } else { + return null; + } + } + + public Map getTTPAvailableFreqMap(TerminationPoint tp) { + var termPoint1 = tp.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526 + .TerminationPoint1.class); + if (termPoint1 == null || termPoint1.getTxTtpAttributes() == null + || termPoint1.getTxTtpAttributes().getAvailFreqMaps() == null + || !(termPoint1.getTxTtpAttributes().getAvailFreqMaps().keySet().toString() + .contains(GridConstant.C_BAND))) { + return null; + } + byte[] byteArray = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", byteArray); + return getFreqMapFromBitSet( + termPoint1.getTxTtpAttributes().getAvailFreqMaps().entrySet().stream() + .filter(afm -> afm.getKey().toString().equals(GridConstant.C_BAND)) + .findFirst().orElseThrow().getValue().getFreqMap()); + } + + public Map getTTP11AvailableFreqMap( + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1 tp) { + if (tp == null || tp.getTxTtpAttributes() == null + || tp.getTxTtpAttributes().getAvailFreqMaps() == null + || !(tp.getTxTtpAttributes().getAvailFreqMaps().keySet().toString() + .contains(GridConstant.C_BAND))) { + return null; + } + byte[] byteArray = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", byteArray); + return getFreqMapFromBitSet( + tp.getTxTtpAttributes().getAvailFreqMaps().entrySet().stream() + .filter(afm -> afm.getKey().toString().equals(GridConstant.C_BAND)) + .findFirst().orElseThrow().getValue().getFreqMap()); + } + + public Map getPP11UsedWavelength( + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1 tp) { + if (tp == null || tp.getPpAttributes() == null + || tp.getPpAttributes().getUsedWavelength() == null + || tp.getPpAttributes().getUsedWavelength().entrySet().iterator().next() == null) { + return null; + } + PpAttributes ppAtt = tp.getPpAttributes(); + Map freqMap = new HashMap<>(); + Double centFreq = ppAtt.getUsedWavelength().entrySet().iterator().next().getValue().getFrequency() + .getValue().doubleValue(); + Double width = ppAtt.getUsedWavelength().entrySet().iterator().next().getValue().getWidth() + .getValue().doubleValue(); + freqMap.put(centFreq - width * 0.001 / 2, centFreq + width * 0.001 / 2); + return freqMap; + } + + public Map getTTP11UsedFreqMap( + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1 tp) { + byte[] byteArray = new byte[GridConstant.NB_OCTECTS]; + Arrays.fill(byteArray, (byte) GridConstant.AVAILABLE_SLOT_VALUE); + if (tp == null || tp.getTxTtpAttributes() == null) { + return null; } - //Creating OTS & OTSI_MC NEP specific attributes - double naz = 0.01; - Uint64 supLoFreq = Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + naz)); - Uint64 supUpFreq = Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 - + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E06 + naz)); - boolean boolParam; - Uint64 upFreq; - Uint64 loFreq; - SpectrumCapabilityPacBuilder spectrumPac = new SpectrumCapabilityPacBuilder(); - if (freqWidthMap == null || freqWidthMap.isEmpty()) { - upFreq = Uint64.valueOf(0); - loFreq = Uint64.valueOf(0); - boolParam = false; - AvailableSpectrum aspec = - new AvailableSpectrumBuilder().setUpperFrequency(supUpFreq).setLowerFrequency(supLoFreq).build(); - spectrumPac.setAvailableSpectrum(new HashMap<>(Map.of( - new AvailableSpectrumKey(aspec.getLowerFrequency(), aspec.getUpperFrequency()), aspec))); + TxTtpAttributes txttpAtt = tp.getTxTtpAttributes(); + Map freqMap = new HashMap<>(); + if (txttpAtt.getUsedWavelengths() != null + && txttpAtt.getUsedWavelengths().entrySet().iterator().next() != null) { + for (Map.Entry usedLambdas : + txttpAtt.getUsedWavelengths().entrySet()) { + Double centFreq = usedLambdas.getValue().getFrequency().getValue().doubleValue(); + Double width = usedLambdas.getValue().getWidth() + .getValue().doubleValue(); + freqMap.put(centFreq - width * 0.001 / 2, centFreq + width * 0.001 / 2); + } + return freqMap; + } else if (txttpAtt.getAvailFreqMaps() != null + && txttpAtt.getAvailFreqMaps().keySet().toString().contains(GridConstant.C_BAND)) { + byte[] freqBitSet = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", freqBitSet); + freqBitSet = txttpAtt.getAvailFreqMaps().entrySet().stream() + .filter(afm -> afm.getKey().toString().equals(GridConstant.C_BAND)) + .findFirst().orElseThrow().getValue().getFreqMap(); + for (int i = 0; i < GridConstant.EFFECTIVE_BITS; i++) { + if (freqBitSet[i] == 0) { + freqBitSet[i] = 1; + } else { + freqBitSet[i] = 0; + } + } + return getFreqMapFromBitSet(freqBitSet); } else { - upFreq = Uint64.valueOf(Math.round( - freqWidthMap.keySet().iterator().next().doubleValue() * 1E09 - + (freqWidthMap.entrySet().iterator().next().getValue().doubleValue() * 1E06) / 2)); - loFreq = Uint64.valueOf(Math.round( - freqWidthMap.keySet().iterator().next().doubleValue() * 1E09 - - (freqWidthMap.entrySet().iterator().next().getValue().doubleValue() * 1E06) / 2)); - boolParam = true; + return null; + } + } + + public Map getFreqMapFromBitSet(byte[] byteArray) { + // Provides a Map describing start and stop frequencies of all slots that are available + // in the ByteArray describing the spectrum : bit sets initially sets to 1/true + // In case the byte array has been inverted before calling this method, it provides respectively a map + // describing all occupied slots! + Map freqMap = new HashMap<>(); + Double startFreq = GridConstant.START_EDGE_FREQUENCY; + Double stopFreq = 0.0; + boolean occupied = false; + if (byteArray[0] == 0) { + occupied = true; } - return onepBldr - .setSupportedPayloadStructure(createSupportedPayloadStructureForPhtncMedia(sicColl, operModeList)) - .setAvailablePayloadStructure(createAvailablePayloadStructureForPhtncMedia(boolParam, sicColl,operModeList)) - .addAugmentation( + for (int index = 0 ; index < GridConstant.EFFECTIVE_BITS ; index++) { + if (byteArray[index] == 1 && occupied) { + startFreq = GridUtils.getStartFrequencyFromIndex(index).doubleValue(); + stopFreq = GridUtils.getStartFrequencyFromIndex(index).doubleValue(); + occupied = false; + } else if (byteArray[index] == 0 && !occupied) { + stopFreq = GridUtils.getStartFrequencyFromIndex(index).doubleValue(); + occupied = true; + } + if (stopFreq.doubleValue() > startFreq.doubleValue() && occupied) { + freqMap.put(startFreq, stopFreq); + startFreq = stopFreq; + } + if ((index == GridConstant.EFFECTIVE_BITS - 1) && (startFreq.doubleValue() == stopFreq.doubleValue()) + && !occupied) { + stopFreq = GridUtils.getStopFrequencyFromIndex(index).doubleValue(); + freqMap.put(startFreq, stopFreq); + } + } + return freqMap; + } + + public OwnedNodeEdgePointBuilder addPayloadStructureAndPhotSpecToOnep(String nodeId, + Map freqMap, List operModeList, + Collection sicColl, OwnedNodeEdgePointBuilder onepBldr, String keyword) { + if (String.join("+", nodeId, TapiStringConstants.OTSI_MC).equals(keyword) + || String.join("+", nodeId, TapiStringConstants.PHTNC_MEDIA_OTS).equals(keyword)) { + LOG.debug("Entering LOOP Step1"); + // Creating OTS & OTSI_MC NEP specific attributes + onepBldr.setSupportedPayloadStructure(createSupportedPayloadStructureForPhtncMedia( + sicColl,operModeList)); + SpectrumCapabilityPacBuilder spectrumPac = new SpectrumCapabilityPacBuilder(); + OccupiedSpectrumBuilder ospecBd = new OccupiedSpectrumBuilder(); + if (freqMap == null || freqMap.isEmpty()) { +// TODO: verify if we need to fill OcupiedSpectrum as follows when no lambda provisioned +// ospecBd +// .setUpperFrequency(Uint64.valueOf(0)) +// .setLowerFrequency(Uint64.valueOf(0)); + onepBldr.setAvailablePayloadStructure(createAvailablePayloadStructureForPhtncMedia( + false, sicColl,operModeList)); + double naz = 0.01; + AvailableSpectrum aspec = new AvailableSpectrumBuilder() + .setLowerFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + naz))) + .setUpperFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E06 + naz))) + .build(); + Map aspecMap = new HashMap<>(); + aspecMap.put(new AvailableSpectrumKey(aspec.getLowerFrequency(), + aspec.getUpperFrequency()), aspec); + spectrumPac.setAvailableSpectrum(aspecMap); + } else { + LOG.debug("Entering LOOP Step2"); + onepBldr.setAvailablePayloadStructure(createAvailablePayloadStructureForPhtncMedia( + true, sicColl,operModeList)); + Map ospecMap = new HashMap<>(); + for (Map.Entry frequency : freqMap.entrySet()) { + ospecBd + .setLowerFrequency(Uint64.valueOf(Math.round(frequency.getKey().doubleValue() * 1E09))) + .setUpperFrequency(Uint64.valueOf(Math.round(frequency.getValue().doubleValue() * 1E09))); + } + OccupiedSpectrum ospec = ospecBd.build(); + ospecMap.put(new OccupiedSpectrumKey(ospec.getLowerFrequency(), ospec.getUpperFrequency()), ospec); + spectrumPac.setOccupiedSpectrum(ospecMap); + } + LOG.debug("Entering LOOP Step3"); + double nazz = 0.01; + SupportableSpectrum sspec = new SupportableSpectrumBuilder() + .setUpperFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + nazz))) + .setLowerFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E06 + nazz))) + .build(); + Map sspecMap = new HashMap<>(); + sspecMap.put(new SupportableSpectrumKey(sspec.getLowerFrequency(), + sspec.getUpperFrequency()), sspec); + spectrumPac.setSupportableSpectrum(sspecMap); + LOG.debug("Entering LOOP Step4"); + PhotonicMediaNodeEdgePointSpec pnepSpec = new PhotonicMediaNodeEdgePointSpecBuilder() + .setSpectrumCapabilityPac(spectrumPac.build()) + .build(); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.OwnedNodeEdgePoint1 onep1 = + new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121 + .OwnedNodeEdgePoint1Builder() + .setPhotonicMediaNodeEdgePointSpec(pnepSpec) + .build(); + LOG.debug("creating Photonic NEP SPEC for node {} and nep {}", nodeId, onep1); + onepBldr.addAugmentation(onep1); + LOG.debug("Entering LOOP Step5"); + } + return onepBldr; + } + + + public OwnedNodeEdgePointBuilder addPhotSpecToRoadmOnep(String nodeId, + Map usedFreqMap, Map availableFreqMap, + OwnedNodeEdgePointBuilder onepBldr, String keyword) { + if (String.join("+", nodeId, TapiStringConstants.PHTNC_MEDIA_OTS).equals(keyword) + || String.join("+", nodeId, TapiStringConstants.PHTNC_MEDIA_OMS).equals(keyword)) { + // Creating OTS/OMS NEP specific attributes + SpectrumCapabilityPacBuilder spectrumPac = new SpectrumCapabilityPacBuilder(); + if ((usedFreqMap == null || usedFreqMap.isEmpty()) + && (availableFreqMap == null || availableFreqMap.isEmpty())) { + double naz = 0.01; + AvailableSpectrum aspec = new AvailableSpectrumBuilder() + .setLowerFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + naz))) + .setUpperFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E06 + naz))) + .build(); + Map aspecMap = new HashMap<>(); + aspecMap.put(new AvailableSpectrumKey(aspec.getLowerFrequency(), + aspec.getUpperFrequency()), aspec); + spectrumPac.setAvailableSpectrum(aspecMap); + } else { + if (availableFreqMap != null && !availableFreqMap.isEmpty()) { + Map aspecMap = new HashMap<>(); + AvailableSpectrumBuilder aspecBd = new AvailableSpectrumBuilder(); + for (Map.Entry frequency : availableFreqMap.entrySet()) { + aspecBd + .setLowerFrequency(Uint64.valueOf(Math.round(frequency.getKey().doubleValue() * 1E09))) + .setUpperFrequency(Uint64.valueOf(Math.round(frequency.getValue().doubleValue() * 1E09))); + AvailableSpectrum aspec = aspecBd.build(); + aspecMap.put(new AvailableSpectrumKey(aspec.getLowerFrequency(), + aspec.getUpperFrequency()), aspec); + } + spectrumPac.setAvailableSpectrum(aspecMap); + } + if (usedFreqMap != null && !usedFreqMap.isEmpty()) { + Map ospecMap = new HashMap<>(); + OccupiedSpectrumBuilder ospecBd = new OccupiedSpectrumBuilder(); + for (Map.Entry frequency : usedFreqMap.entrySet()) { + ospecBd + .setLowerFrequency(Uint64.valueOf(Math.round(frequency.getKey().doubleValue() * 1E09))) + .setUpperFrequency(Uint64.valueOf(Math.round(frequency.getValue().doubleValue() * 1E09))); + OccupiedSpectrum ospec = ospecBd.build(); + ospecMap.put(new OccupiedSpectrumKey(ospec.getLowerFrequency(), + ospec.getUpperFrequency()), ospec); + } + spectrumPac.setOccupiedSpectrum(ospecMap); + } + } + double nazz = 0.01; + SupportableSpectrum sspec = new SupportableSpectrumBuilder() + .setUpperFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + nazz))) + .setLowerFrequency(Uint64.valueOf(Math.round(GridConstant.START_EDGE_FREQUENCY * 1E09 + + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E06 + nazz))) + .build(); + Map sspecMap = new HashMap<>(); + sspecMap.put(new SupportableSpectrumKey(sspec.getLowerFrequency(), + sspec.getUpperFrequency()), sspec); + spectrumPac.setSupportableSpectrum(sspecMap); + + PhotonicMediaNodeEdgePointSpec pnepSpec = new PhotonicMediaNodeEdgePointSpecBuilder() + .setSpectrumCapabilityPac(spectrumPac.build()) + .build(); + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.OwnedNodeEdgePoint1 onep1 = new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121 .OwnedNodeEdgePoint1Builder() - .setPhotonicMediaNodeEdgePointSpec( - new PhotonicMediaNodeEdgePointSpecBuilder() - .setSpectrumCapabilityPac( - spectrumPac - .setOccupiedSpectrum(new HashMap<>(Map.of( - new OccupiedSpectrumKey(loFreq, upFreq), - new OccupiedSpectrumBuilder() - .setUpperFrequency(upFreq) - .setLowerFrequency(loFreq) - .build()))) - .setSupportableSpectrum(new HashMap<>(Map.of( - new SupportableSpectrumKey(supLoFreq, supUpFreq), - new SupportableSpectrumBuilder() - .setUpperFrequency(supUpFreq) - .setLowerFrequency(supLoFreq) - .build()))) - .build()) - .build()) - .build()); + .setPhotonicMediaNodeEdgePointSpec(pnepSpec) + .build(); + onepBldr.addAugmentation(onep1); + LOG.debug("Add Photonic Node Edge point Spec to {} including available Spectrum {} = ", + onepBldr.getName(), + onep1.getPhotonicMediaNodeEdgePointSpec().getSpectrumCapabilityPac().getAvailableSpectrum()); + } + return onepBldr; } private OduSwitchingPools createOduSwitchingPoolForTp100G() { @@ -879,7 +1267,12 @@ public class ConvertORToTapiTopology { .setRiskCharacteristicName("risk characteristic") .setRiskIdentifierList(Set.of("risk identifier1", "risk identifier2")) .build(); + Name nrgName = new NameBuilder() + .setValueName("nrg name") + .setValue("odu node rule group " + count) + .build(); NodeRuleGroup nodeRuleGroup1 = new NodeRuleGroupBuilder() + .setName(Map.of(nrgName.key(), nrgName)) .setUuid(new Uuid(UUID.nameUUIDFromBytes(("dsr node rule group " + count) .getBytes(Charset.forName("UTF-8"))).toString())) .setRule(ruleList) @@ -962,6 +1355,7 @@ public class ConvertORToTapiTopology { onepBldr = addPayloadStructureAndPhotSpecToOnep( this.ietfNodeId, getXpdrUsedWavelength(oorTp), opModeList, sicColl, onepBldr, keyword); } + LOG.debug("ConvertORToTapiTopology 1360, onep = {}", onepBldr.build()); return onepBldr.build(); } @@ -969,7 +1363,7 @@ public class ConvertORToTapiTopology { String nodeid, Collection supportedInterfaceCapability, OperationalState operState, AdministrativeState adminState) { // TODO: what value should be set in total capacity and available capacity?? - // LOG.info("SIP name = {}", String.join("+", nodeid, tp.getTpId().getValue())); + LOG.debug("SIP name = {}", String.join("+", nodeid, tpId)); Name sipName = new NameBuilder() .setValueName("SIP name") .setValue(String.join("+", nodeid, tpId)) diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java index ca5d57cdd..023b229dc 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiFullTopo.java @@ -15,6 +15,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; +import org.opendaylight.transportpce.common.fixedflex.GridConstant; import org.opendaylight.transportpce.tapi.TapiStringConstants; import org.opendaylight.transportpce.tapi.utils.TapiLink; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Link1; @@ -39,8 +40,14 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.glob 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.photonic.media.rev221121.PHOTONICLAYERQUALIFIERMC; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROMS; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTS; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTSiMC; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroupKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointKey; @@ -72,6 +79,7 @@ public class ConvertORTopoToTapiFullTopo { private Map tapiLinks; private Map tapiSips; private final TapiLink tapiLink; + private static String topologicalMode; public ConvertORTopoToTapiFullTopo(Uuid tapiTopoUuid, TapiLink tapiLink) { @@ -80,6 +88,9 @@ public class ConvertORTopoToTapiFullTopo { this.tapiLinks = new HashMap<>(); this.tapiSips = new HashMap<>(); this.tapiLink = tapiLink; + if (topologicalMode == null) { + ConvertORTopoToTapiFullTopo.topologicalMode = "Full"; + } } public void convertRdmToRdmLinks( @@ -128,7 +139,16 @@ public class ConvertORTopoToTapiFullTopo { } } - public void convertRoadmNode(Node roadm, Network openroadmTopo) { + public void convertRoadmNode(Node roadm, Network openroadmTopo, String topoMode) { + setTopologicalMode(topoMode); + if (topoMode.equals("Full")) { + convertRoadmNodeFull(roadm, openroadmTopo); + } else { + convertRoadmNodeAbstracted(openroadmTopo); + } + } + + private void convertRoadmNodeFull(Node roadm, Network openroadmTopo) { this.ietfNodeId = roadm.getNodeId().getValue(); this.ietfNodeType = roadm.augmentation( org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class) @@ -175,10 +195,12 @@ public class ConvertORTopoToTapiFullTopo { == OpenroadmTpType.DEGREETXTTP.getIntValue()) .collect(Collectors.toList()); // Convert TP List in NEPs and put it in onepl - LOG.info("Degree port List: {}", degPortList); + LOG.info("Degree port List: {}", degPortList.toString()); // TODO: deg port could be sip. e.g. MDONS - oneplist.putAll(populateNepsForRdmNode(degPortList, false, TapiStringConstants.PHTNC_MEDIA_OTS)); - oneplist.putAll(populateNepsForRdmNode(degPortList, false, TapiStringConstants.PHTNC_MEDIA_OMS)); + oneplist.putAll(populateNepsForRdmNode(node.getNodeId().getValue(), degPortList, false, + TapiStringConstants.PHTNC_MEDIA_OTS)); + oneplist.putAll(populateNepsForRdmNode(node.getNodeId().getValue(), degPortList, false, + TapiStringConstants.PHTNC_MEDIA_OMS)); numNeps += degPortList.size() * 2; break; case 12: @@ -194,7 +216,8 @@ public class ConvertORTopoToTapiFullTopo { .collect(Collectors.toList()); // Convert TP List in NEPs and put it in onepl LOG.info("Srg port List: {}", srgPortList); - oneplist.putAll(populateNepsForRdmNode(srgPortList, true, TapiStringConstants.PHTNC_MEDIA_OTS)); + oneplist.putAll(populateNepsForRdmNode(node.getNodeId().getValue(), srgPortList, true, + TapiStringConstants.PHTNC_MEDIA_OTS)); numNeps += srgPortList.size(); numSips += srgPortList.size(); break; @@ -213,8 +236,17 @@ public class ConvertORTopoToTapiFullTopo { // Protocol Layer Set layerProtocols = Set.of(LayerProtocolName.PHOTONICMEDIA); // Build tapi node - var roadmNode = createRoadmTapiNode( - nodeUuid, Map.of(nodeNames.key(), nodeNames, nameNodeType.key(), nameNodeType), layerProtocols, oneplist); + LOG.debug("CONVERTTOFULL SRG OTSNode of retrieved OnepMap {} ", + oneplist.entrySet().stream().filter(e -> e.getValue() + .getSupportedCepLayerProtocolQualifierInstances() + .contains(new SupportedCepLayerProtocolQualifierInstancesBuilder() + .setNumberOfCepInstances(Uint64.valueOf(1)) + .setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTS.VALUE) + .build())) + .collect(Collectors.toList()).toString()); + //org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node + var roadmNode = createRoadmTapiNode(nodeUuid, + Map.of(nodeNames.key(), nodeNames, nameNodeType.key(), nameNodeType), layerProtocols, oneplist, "Full"); // TODO add states corresponding to device config LOG.info("ROADM node {} should have {} NEPs and {} SIPs", roadm.getNodeId().getValue(), numNeps, numSips); LOG.info("ROADM node {} has {} NEPs and {} SIPs", @@ -225,9 +257,76 @@ public class ConvertORTopoToTapiFullTopo { tapiNodes.put(roadmNode.key(), roadmNode); } - private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node createRoadmTapiNode( - Uuid nodeUuid, Map nameMap, Set layerProtocols, - Map oneplist) { + private void convertRoadmNodeAbstracted(Network openroadmTopo) { + Map oneMap = new HashMap<>(); + // 1. Get degree and srg nodes to map TPs into NEPs + if (openroadmTopo.getNode() == null) { + LOG.warn("Openroadm-topology is null."); + return; + } + int numNeps = 0; + int numSips = 0; + List nodeList = new ArrayList(openroadmTopo.getNode().values()); + for (Node node:nodeList) { + var node1 = node.augmentation( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class); + if (node.augmentation(Node1.class) == null && node1 == null) { + LOG.warn("Abstracted node {} doesnt have type of node or is not disaggregated", + node.getNodeId().getValue()); + continue; + } + OpenroadmNodeType nodeType = node.augmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class) + .getNodeType(); + if (nodeType.getIntValue() != 11) { + // Only consider ROADMS SRG Nodes + continue; + } + LOG.debug("Handling SRG node in Topology abstraction {}", node.getNodeId().toString()); + // Get only external TPs of the srg + List srgPortList = node1.getTerminationPoint().values().stream() + .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue() + == OpenroadmTpType.SRGTXRXPP.getIntValue() + || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue() + == OpenroadmTpType.SRGRXPP.getIntValue() + || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue() + == OpenroadmTpType.SRGTXPP.getIntValue()) + .collect(Collectors.toList()); + // Convert TP List in NEPs and put it in onepl + LOG.debug("Srg port List: {}", srgPortList); + oneMap.putAll(populateNepsForRdmNode(node.getNodeId().getValue(), srgPortList, true, + TapiStringConstants.PHTNC_MEDIA_OTS)); + numNeps += srgPortList.size(); + numSips += srgPortList.size(); + } + // create a unique ROADM tapi Node + LOG.info("abstraction of the ROADM infrastructure towards a photonic node"); + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes( + TapiStringConstants.RDM_INFRA.getBytes(Charset.forName("UTF-8"))).toString()); + Name nodeName = + new NameBuilder().setValueName("roadm node name").setValue(TapiStringConstants.RDM_INFRA).build(); + Name nameNodeType = + new NameBuilder().setValueName("Node Type").setValue(OpenroadmNodeType.ROADM.getName()).build(); + + // Protocol Layer + Set layerProtocols = Set.of(LayerProtocolName.PHOTONICMEDIA); + // Build tapi node + org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node roadmNode = + createRoadmTapiNode(nodeUuid, Map.of(nodeName.key(), nodeName, nameNodeType.key(), nameNodeType), + layerProtocols, oneMap, "Abstracted"); + // TODO add states corresponding to device config + LOG.info("ROADM node {} should have {} NEPs and {} SIPs", TapiStringConstants.RDM_INFRA, numNeps, numSips); + LOG.info("ROADM node {} has {} NEPs and {} SIPs", TapiStringConstants.RDM_INFRA, + roadmNode.nonnullOwnedNodeEdgePoint().values().size(), + roadmNode.nonnullOwnedNodeEdgePoint().values().stream() + .filter(nep -> nep.getMappedServiceInterfacePoint() != null).count()); + + tapiNodes.put(roadmNode.key(), roadmNode); + } + + private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node + createRoadmTapiNode(Uuid nodeUuid, Map nameMap, Set layerProtocols, + Map onepMap, String topoMode) { // Empty random creation of mandatory fields for avoiding errors.... CostCharacteristic costCharacteristic = new CostCharacteristicBuilder() .setCostAlgorithm("Restricted Shortest Path - RSP") @@ -245,6 +344,14 @@ public class ConvertORTopoToTapiFullTopo { .setRiskCharacteristicName("risk characteristic") .setRiskIdentifierList(Set.of("risk identifier1", "risk identifier2")) .build(); + + var tapiFactory = new ConvertORToTapiTopology(this.tapiTopoUuid); + String choosenMode = topoMode.equals("Full") ? "Full" : "Abstracted"; + Map nodeRuleGroupMap = + tapiFactory.createAllNodeRuleGroupForRdmNode(choosenMode, nodeUuid, this.ietfNodeId, onepMap.values()); + Map interRuleGroupMap = + tapiFactory.createInterRuleGroupForRdmNode(choosenMode, nodeUuid, this.ietfNodeId, + nodeRuleGroupMap.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList())); return new NodeBuilder() .setUuid(nodeUuid) .setName(nameMap) @@ -252,9 +359,9 @@ public class ConvertORTopoToTapiFullTopo { .setAdministrativeState(AdministrativeState.UNLOCKED) .setOperationalState(OperationalState.ENABLED) .setLifecycleState(LifecycleState.INSTALLED) - .setOwnedNodeEdgePoint(oneplist) - .setNodeRuleGroup(new ConvertORToTapiTopology(this.tapiTopoUuid) - .createNodeRuleGroupForRdmNode("Full",nodeUuid, this.ietfNodeId, oneplist.values())) + .setOwnedNodeEdgePoint(onepMap) + .setNodeRuleGroup(nodeRuleGroupMap) + .setInterRuleGroup(interRuleGroupMap) .setCostCharacteristic(Map.of(costCharacteristic.key(), costCharacteristic)) .setLatencyCharacteristic(Map.of(latencyCharacteristic.key(), latencyCharacteristic)) .setRiskParameterPac( @@ -270,20 +377,86 @@ public class ConvertORTopoToTapiFullTopo { .build(); } - private Map populateNepsForRdmNode( + public Map populateNepsForRdmNode(String nodeId, List tpList, boolean withSip, String nepPhotonicSublayer) { - // create neps for MC and OTSiMC and Photonic Media + // create neps for MC and and Photonic Media OTS/OMS Map onepMap = new HashMap<>(); for (TerminationPoint tp:tpList) { + // Admin and oper state common for all tps + OpenroadmTpType tpType = tp.augmentation(TerminationPoint1.class).getTpType(); // PHOTONIC MEDIA nep - String nodeIdNepTp = String.join("+", this.ietfNodeId, nepPhotonicSublayer, tp.getTpId().getValue()); - LOG.info("PHOTO NEP = {}", nodeIdNepTp); + LOG.debug("PHOTO NEP = {}", String.join("+", this.ietfNodeId, nepPhotonicSublayer, + tp.getTpId().getValue())); + SupportedCepLayerProtocolQualifierInstancesBuilder sclpqiBd = + new SupportedCepLayerProtocolQualifierInstancesBuilder() + .setNumberOfCepInstances(Uint64.valueOf(1)); + switch (nepPhotonicSublayer) { + case TapiStringConstants.PHTNC_MEDIA_OMS: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROMS.VALUE); + break; + case TapiStringConstants.PHTNC_MEDIA_OTS: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTS.VALUE); + break; + case TapiStringConstants.MC: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIERMC.VALUE); + break; + case TapiStringConstants.OTSI_MC: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTSiMC.VALUE); + break; + default: + break; + } + //List sclpqiList = new ArrayList<>(List.of(sclpqiBd.build())); + OwnedNodeEdgePointBuilder onepBd = new OwnedNodeEdgePointBuilder(); + if (!nepPhotonicSublayer.equals(TapiStringConstants.MC) + && !nepPhotonicSublayer.equals(TapiStringConstants.OTSI_MC)) { + ConvertORToTapiTopology tapiFactory = new ConvertORToTapiTopology(this.tapiTopoUuid); + Map usedFreqMap = new HashMap<>(); + Map availableFreqMap = new HashMap<>(); + switch (tpType) { + // Whatever is the TP and its type we consider that it is handled in a bidirectional way : + // same wavelength(s) used in both direction. + case SRGRXPP: + case SRGTXPP: + case SRGTXRXPP: + usedFreqMap = tapiFactory.getPPUsedWavelength(tp); + if (usedFreqMap == null || usedFreqMap.isEmpty()) { + availableFreqMap.put(GridConstant.START_EDGE_FREQUENCY * 1E09, + GridConstant.START_EDGE_FREQUENCY * 1E09 + + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E06); + } else { + LOG.debug("EnteringLOOPcreateOTSiMC & MC with usedFreqMap non empty {} NEP {} for Node {}", + usedFreqMap.toString(), String.join("+", this.ietfNodeId, nepPhotonicSublayer, + tp.getTpId().getValue()), nodeId); + onepMap.putAll(populateNepsForRdmNode(nodeId, new ArrayList<>(List.of(tp)), + true, TapiStringConstants.MC)); + onepMap.putAll(populateNepsForRdmNode(nodeId, new ArrayList<>(List.of(tp)), + true, TapiStringConstants.OTSI_MC)); + } + break; + case DEGREERXTTP: + case DEGREETXTTP: + case DEGREETXRXTTP: + usedFreqMap = tapiFactory.getTTPUsedFreqMap(tp); + availableFreqMap = tapiFactory.getTTPAvailableFreqMap(tp); + break; + default: + break; + } + LOG.debug("calling add Photonic NEP spec for Roadm"); + onepBd = tapiFactory.addPhotSpecToRoadmOnep(nodeId, usedFreqMap, availableFreqMap, onepBd, + nepPhotonicSublayer); + } + AdminStates admin = tp.augmentation(TerminationPoint1.class).getAdministrativeState(); + State oper = tp.augmentation(TerminationPoint1.class).getOperationalState(); Name nepName = new NameBuilder() .setValueName(nepPhotonicSublayer + "NodeEdgePoint") - .setValue(nodeIdNepTp) + .setValue(String.join("+", this.ietfNodeId, nepPhotonicSublayer, tp.getTpId().getValue())) .build(); - OwnedNodeEdgePoint onep = new OwnedNodeEdgePointBuilder() - .setUuid(new Uuid(UUID.nameUUIDFromBytes(nodeIdNepTp.getBytes(Charset.forName("UTF-8"))).toString())) + OwnedNodeEdgePoint onep = onepBd + .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", this.ietfNodeId, + nepPhotonicSublayer, tp.getTpId().getValue())) + .getBytes(Charset.forName("UTF-8"))).toString())) .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA) .setName(Map.of(nepName.key(), nepName)) .setSupportedCepLayerProtocolQualifierInstances( @@ -297,12 +470,8 @@ public class ConvertORTopoToTapiFullTopo { .build()))) .setDirection(Direction.BIDIRECTIONAL) .setLinkPortRole(PortRole.SYMMETRIC) - .setAdministrativeState(this.tapiLink.setTapiAdminState( - // Admin state common for all tps - tp.augmentation(TerminationPoint1.class).getAdministrativeState().getName())) - .setOperationalState(this.tapiLink.setTapiOperationalState( - // Oper state common for all tps - tp.augmentation(TerminationPoint1.class).getOperationalState().getName())) + .setAdministrativeState(this.tapiLink.setTapiAdminState(admin.getName())) + .setOperationalState(this.tapiLink.setTapiOperationalState(oper.getName())) .setLifecycleState(LifecycleState.INSTALLED) .build(); onepMap.put(onep.key(), onep); @@ -315,7 +484,7 @@ public class ConvertORTopoToTapiFullTopo { .networks.network.Link> xpdrRdmLinkList) { List linksToNotConvert = new ArrayList<>(); LOG.info("creation of {} xpdr to roadm links", xpdrRdmLinkList.size() / 2); - // LOG.info("Link list = {}", xpdrRdmLinkList.toString()); + LOG.debug("Link list = {}", xpdrRdmLinkList); for (var link:xpdrRdmLinkList) { if (!linksToNotConvert.contains(link.getLinkId().getValue())) { var oppositeLink = xpdrRdmLinkList.stream() @@ -391,4 +560,12 @@ public class ConvertORTopoToTapiFullTopo { public Map getTapiSips() { return tapiSips; } + + public static void setTopologicalMode(String topoMode) { + ConvertORTopoToTapiFullTopo.topologicalMode = topoMode; + } + + public String getTopologicalMode() { + return topologicalMode; + } } diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java index b417c77c4..6e9476adf 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopo.java @@ -41,6 +41,8 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.link.NodeEdgePoint; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.link.NodeEdgePointBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.link.NodeEdgePointKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroupKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroup; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePoint; @@ -146,8 +148,10 @@ public class ConvertORTopoToTapiTopo { LOG.info("abstraction of the ROADM infrastructure towards a photonic node"); Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.RDM_INFRA .getBytes(Charset.forName("UTF-8"))).toString()); - Name nodeName = new NameBuilder().setValueName("otsi node name").setValue(TapiStringConstants.RDM_INFRA) - .build(); + Name nodeName = + new NameBuilder().setValueName("otsi node name").setValue(TapiStringConstants.RDM_INFRA).build(); + Name nodeName2 = + new NameBuilder().setValueName("roadm node name").setValue(TapiStringConstants.RDM_INFRA).build(); Name nameNodeType = new NameBuilder().setValueName("Node Type") .setValue(OpenroadmNodeType.ROADM.getName()).build(); Set nodeLayerProtocols = Set.of(LayerProtocolName.PHOTONICMEDIA); @@ -158,9 +162,13 @@ public class ConvertORTopoToTapiTopo { // nep creation for rdm infra abstraction node Map onepMap = createNepForRdmNode(photonicNepUuisMap.size()); // node rule group creation - Map nodeRuleGroupList - = new ConvertORToTapiTopology(this.tapiTopoUuid) - .createNodeRuleGroupForRdmNode("Abstracted", nodeUuid, null, onepMap.values()); + var tapiFactory = new ConvertORToTapiTopology(this.tapiTopoUuid); + Map nodeRuleGroupMap + = tapiFactory.createAllNodeRuleGroupForRdmNode("T0ML", nodeUuid, null, onepMap.values()); + Map interRuleGroupMap + = tapiFactory.createInterRuleGroupForRdmNode("T0ML", nodeUuid, null, + nodeRuleGroupMap.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList())); + // Empty random creation of mandatory fields for avoiding errors.... CostCharacteristic costCharacteristic = new CostCharacteristicBuilder() .setCostAlgorithm("Restricted Shortest Path - RSP") @@ -184,13 +192,14 @@ public class ConvertORTopoToTapiTopo { // build RDM infra node abstraction org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node rdmNode = new NodeBuilder() .setUuid(nodeUuid) - .setName(Map.of(nodeName.key(), nodeName, nameNodeType.key(), nameNodeType)) + .setName(Map.of(nodeName.key(), nodeName, nodeName2.key(), nodeName2, nameNodeType.key(), nameNodeType)) .setLayerProtocolName(nodeLayerProtocols) .setAdministrativeState(AdministrativeState.UNLOCKED) .setOperationalState(OperationalState.ENABLED) .setLifecycleState(LifecycleState.INSTALLED) .setOwnedNodeEdgePoint(onepMap) - .setNodeRuleGroup(nodeRuleGroupList) + .setNodeRuleGroup(nodeRuleGroupMap) + .setInterRuleGroup(interRuleGroupMap) .setCostCharacteristic(Map.of(costCharacteristic.key(), costCharacteristic)) .setLatencyCharacteristic(Map.of(latencyCharacteristic.key(), latencyCharacteristic)) .setRiskParameterPac(riskParamPac) diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertTapiTopoToAbstracted.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertTapiTopoToAbstracted.java new file mode 100644 index 000000000..e9bc55a28 --- /dev/null +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertTapiTopoToAbstracted.java @@ -0,0 +1,194 @@ +/* + * Copyright © 2024 Orange, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.tapi.topology; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import org.opendaylight.transportpce.tapi.TapiStringConstants; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmNodeType; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.AdministrativeState; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LayerProtocolName; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LifecycleState; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.OperationalState; +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.topology.rev221121.node.InterRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroupKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePoint; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.RiskParameterPac; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.RiskParameterPacBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.risk.parameter.pac.RiskCharacteristic; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.risk.parameter.pac.RiskCharacteristicBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Link; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.LinkKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.cost.pac.CostCharacteristic; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.cost.pac.CostCharacteristicBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.timing.pac.LatencyCharacteristic; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.timing.pac.LatencyCharacteristicBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ConvertTapiTopoToAbstracted { + + private static final Logger LOG = LoggerFactory.getLogger(ConvertTapiTopoToAbstracted.class); + private Map + tapiNodes; + private Map tapiLinks; + private Map tapiSips; + private Uuid refTopoUuid; + + public ConvertTapiTopoToAbstracted(Uuid reftopoUuid) { + this.tapiNodes = new HashMap<>(); + this.tapiLinks = new HashMap<>(); + this.tapiSips = new HashMap<>(); + this.refTopoUuid = reftopoUuid; + } + + public void convertRoadmInfrastructure() { + LOG.info("abstraction of the ROADM infrastructure towards a photonic node"); + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.RDM_INFRA + .getBytes(Charset.forName("UTF-8"))).toString()); + Name nodeName = new NameBuilder().setValueName("otsi node name").setValue(TapiStringConstants.RDM_INFRA) + .build(); + Name nameNodeType = new NameBuilder().setValueName("Node Type") + .setValue(OpenroadmNodeType.ROADM.getName()).build(); + Set nodeLayerProtocols = Set.of(LayerProtocolName.PHOTONICMEDIA); + Map onepMap = pruneTapiRoadmNeps(); + var tapiFactory = new ConvertORToTapiTopology(this.refTopoUuid); + Map nodeRuleGroupMap + = tapiFactory.createAllNodeRuleGroupForRdmNode("Abstracted", nodeUuid, null, onepMap.values()); + Map interRuleGroupMap + = tapiFactory.createInterRuleGroupForRdmNode("Abstracted", nodeUuid, null, + nodeRuleGroupMap.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList())); + // Empty random creation of mandatory fields for avoiding errors.... + CostCharacteristic costCharacteristic = new CostCharacteristicBuilder() + .setCostAlgorithm("Restricted Shortest Path - RSP") + .setCostName("HOP_COUNT") + .setCostValue(TapiStringConstants.COST_HOP_VALUE) + .build(); + LatencyCharacteristic latencyCharacteristic = new LatencyCharacteristicBuilder() + .setFixedLatencyCharacteristic(TapiStringConstants.FIXED_LATENCY_VALUE) + .setQueuingLatencyCharacteristic(TapiStringConstants.QUEING_LATENCY_VALUE) + .setJitterCharacteristic(TapiStringConstants.JITTER_VALUE) + .setWanderCharacteristic(TapiStringConstants.WANDER_VALUE) + .setTrafficPropertyName("FIXED_LATENCY") + .build(); + RiskCharacteristic riskCharacteristic = new RiskCharacteristicBuilder() + .setRiskCharacteristicName("risk characteristic") + .setRiskIdentifierList(Set.of("risk identifier1", "risk identifier2")) + .build(); + RiskParameterPac riskParamPac = new RiskParameterPacBuilder() + .setRiskCharacteristic(Map.of(riskCharacteristic.key(), riskCharacteristic)) + .build(); + // build RDM infra node abstraction + Node rdmNode = new NodeBuilder() + .setUuid(nodeUuid) + .setName(Map.of(nodeName.key(), nodeName, nameNodeType.key(), nameNodeType)) + .setLayerProtocolName(nodeLayerProtocols) + .setAdministrativeState(AdministrativeState.UNLOCKED) + .setOperationalState(OperationalState.ENABLED) + .setLifecycleState(LifecycleState.INSTALLED) + .setOwnedNodeEdgePoint(onepMap) + .setNodeRuleGroup(nodeRuleGroupMap) + .setInterRuleGroup(interRuleGroupMap) + .setCostCharacteristic(Map.of(costCharacteristic.key(), costCharacteristic)) + .setLatencyCharacteristic(Map.of(latencyCharacteristic.key(), latencyCharacteristic)) + .setRiskParameterPac(riskParamPac) + .build(); + purgeTapiNodes(); + tapiNodes.put(rdmNode.key(), rdmNode); + purgeTapiLinks(); + } + + private Map pruneTapiRoadmNeps() { + List tapiPhotonicNodes + = this.tapiNodes.values().stream() + .filter(n -> n.getLayerProtocolName().contains(LayerProtocolName.PHOTONICMEDIA) + && !n.getLayerProtocolName().contains(LayerProtocolName.DIGITALOTN) + && !n.getLayerProtocolName().contains(LayerProtocolName.DSR) + && !n.getLayerProtocolName().contains(LayerProtocolName.ODU)) + .collect(Collectors.toList()); + Map onepMap = new HashMap<>(); + for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node node + : tapiPhotonicNodes) { + for (Map.Entry entry : node.getOwnedNodeEdgePoint().entrySet()) { + if (entry.getValue().getName().values().stream() + .filter(name -> name.getValueName().equals("PHOTONIC_MEDIA_OTSNodeEdgePoint")).count() > 0 + && !(entry.getValue().getName().values().stream() + .filter(name -> name.getValue().contains("DEG")).count() > 0)) { + onepMap.put(entry.getKey(), entry.getValue()); + } + if (entry.getValue().getName().values().stream() + .filter(name -> name.getValueName().equals("OTSI_MCNodeEdgePoint")).count() > 0 + && !(entry.getValue().getName().values().stream() + .filter(name -> name.getValue().contains("DEG")).count() > 0)) { + onepMap.put(entry.getKey(), entry.getValue()); + } + } + } + return onepMap; + } + + private void purgeTapiLinks() { + this.tapiLinks = this.tapiLinks.values().stream() + .filter(l -> l.getName().containsKey(new NameKey(TapiStringConstants.VALUE_NAME_OTS_XPDR_RDM_LINK)) + || l.getName().containsKey(new NameKey(TapiStringConstants.VALUE_NAME_OTN_XPDR_XPDR_LINK))) + .collect(Collectors.toMap(Link::key, link -> link)); + } + + private void purgeTapiNodes() { + this.tapiNodes = this.tapiNodes.values().stream() + .filter(n -> !n.getName().containsKey(new NameKey(TapiStringConstants.VALUE_NAME_ROADM_NODE))) + .collect(Collectors.toMap(Node::key, node -> node)); + } + + + public void setTapiNodes(Map nodeMap) { + this.tapiNodes.putAll(nodeMap); + } + + public Map + getTapiNodes() { + return tapiNodes; + } + + public void setTapiLinks(Map linkMap) { + this.tapiLinks.putAll(linkMap); + } + + public Map getTapiLinks() { + return tapiLinks; + } + + public Map getTapiSips() { + return tapiSips; + } + + public void setTapiSips(Map tapiSip) { + this.tapiSips.putAll(tapiSip); + } +} + diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java index 2c3cde2da..8706dc301 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java @@ -7,6 +7,7 @@ */ package org.opendaylight.transportpce.tapi.topology; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; @@ -21,21 +22,19 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import org.opendaylight.mdsal.binding.api.NotificationPublishService; -import org.opendaylight.mdsal.binding.api.ReadTransaction; import org.opendaylight.mdsal.common.api.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.fixedflex.GridConstant; import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.tapi.R2RTapiLinkDiscovery; import org.opendaylight.transportpce.tapi.TapiStringConstants; import org.opendaylight.transportpce.tapi.utils.TapiLink; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.mapping.Mapping; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.network.Nodes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.TerminationPoint1; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.NodeTypes; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.XpdrNodeTypes; @@ -46,6 +45,7 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.re import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev230526.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingListBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev230526.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingListKey; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmNodeType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmTpType; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.xpdr.tp.supported.interfaces.SupportedInterfaceCapability; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.xpdr.tp.supported.interfaces.SupportedInterfaceCapabilityBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.xpdr.tp.supported.interfaces.SupportedInterfaceCapabilityKey; @@ -96,14 +96,19 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev22112 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.ChangedAttributes; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.ChangedAttributesBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.ChangedAttributesKey; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIERMC; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROMS; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTS; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTSiMC; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.context.topology.context.topology.node.owned.node.edge.point.PhotonicMediaNodeEdgePointSpec; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.FORWARDINGRULEMAYFORWARDACROSSGROUP; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.NodeEdgePointRef; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.RuleType; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.TOPOLOGYOBJECTTYPENODEEDGEPOINT; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.context.TopologyContext; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroup; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroupKey; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroup; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupBuilder; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupKey; @@ -157,8 +162,10 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { .getBytes(StandardCharsets.UTF_8)).toString()); private final NetworkTransactionService networkTransactionService; private final R2RTapiLinkDiscovery linkDiscovery; -// private final TapiLink tapiLink; + private final TapiLink tapiLink; private final ConvertORToTapiTopology tapiFactory; + private String topologicalMode; + private final ConvertORTopoToTapiFullTopo tapiFullFactory; private final NotificationPublishService notificationPublishService; private Map sipMap = new HashMap<>(); @@ -171,6 +178,9 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { this.linkDiscovery = new R2RTapiLinkDiscovery(networkTransactionService, deviceTransactionManager, tapiLink); this.notificationPublishService = notificationPublishService; this.tapiFactory = new ConvertORToTapiTopology(tapiTopoUuid); + this.tapiLink = tapiLink; + this.tapiFullFactory = new ConvertORTopoToTapiFullTopo(tapiTopoUuid, tapiLink); + this.topologicalMode = tapiFullFactory.getTopologicalMode(); } @Override @@ -209,23 +219,51 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { } // Transform LCPs into ONEP Map onepMap = - new HashMap<>(transformDegToOnep(orNodeId, mapDeg)); - onepMap.putAll(transformSrgToOnep(orNodeId, mapSrg)); - - // create tapi Node - Node roadmNode = createRoadmTapiNode(orNodeId, onepMap); - mergeNodeinTopology(Map.of(roadmNode.key(), roadmNode)); - mergeSipsinContext(this.sipMap); - // TODO add states corresponding to device config -> based on mapping. - // This should be possible after Gilles work is merged - - // rdm to rdm link creation if neighbour roadm is mounted - LOG.info("checking if neighbor roadm exists"); - Map rdm2rdmLinks = this.linkDiscovery.readLLDP(new NodeId(orNodeId), orNodeVersion, - this.tapiTopoUuid); - if (!rdm2rdmLinks.isEmpty()) { - mergeLinkinTopology(rdm2rdmLinks); + new HashMap<>(transformSrgToOnep(orNodeId, mapSrg)); + LOG.debug("CreateTapiNode NetworkModelServiceImpl, TopologicalMode = {}", topologicalMode); + LOG.debug("TAPINETWORKMODELSERVICEIMPL call transformSRGtoONEP (OrNodeId {} ", orNodeId); + LOG.debug("TAPINETWORKMODELSERVICEIMPL SRG OTSNode of retrieved OnepMap {} ", + onepMap.entrySet().stream().filter(e -> e.getValue() + .getSupportedCepLayerProtocolQualifierInstances() + .contains(new SupportedCepLayerProtocolQualifierInstancesBuilder() + .setNumberOfCepInstances(Uint64.valueOf(1)) + .setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTS.VALUE) + .build())) + .collect(Collectors.toList())); + if (topologicalMode.equals("Full")) { + onepMap.putAll(transformDegToOnep(orNodeId, mapDeg)); + LOG.debug("TAPINETWORKMODELSERVICEIMPL DEG+SRG OTSNode of retrieved OnepMap {} ", + onepMap.entrySet().stream().filter(e -> e.getValue() + .getSupportedCepLayerProtocolQualifierInstances() + .contains(new SupportedCepLayerProtocolQualifierInstancesBuilder() + .setNumberOfCepInstances(Uint64.valueOf(1)) + .setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTS.VALUE) + .build())) + .collect(Collectors.toList())); + LOG.debug("TAPINETWORKMODELSERVICEIMPL DEG+SRG complete retrieved OnepMap {} ", onepMap); + // create tapi Node + Node roadmNode = createRoadmTapiNode(orNodeId, onepMap); + mergeNodeinTopology(Map.of(roadmNode.key(), roadmNode)); + mergeSipsinContext(this.sipMap); + // TODO add states corresponding to device config -> based on mapping. + // This should be possible after Gilles work is merged + + // rdm to rdm link creation if neighbour roadm is mounted + LOG.info("checking if neighbor roadm exists"); + Map rdm2rdmLinks = this.linkDiscovery.readLLDP(new NodeId(orNodeId), orNodeVersion, + this.tapiTopoUuid); + if (!rdm2rdmLinks.isEmpty()) { + mergeLinkinTopology(rdm2rdmLinks); + } + } else { + // create tapi Node + Node roadmNode = createRoadmTapiNode("ROADMINFRA", onepMap); + mergeNodeinTopology(Map.of(roadmNode.key(), roadmNode)); + mergeSipsinContext(this.sipMap); + // TODO add states corresponding to device config -> based on mapping. + // This should be possible after Gilles work is merged } + LOG.info("TAPI node for or node {} successfully merged", orNodeId); } else if (NodeTypes.Xpdr.getIntValue() == node.getNodeInfo().getNodeType().getIntValue()) { List networkMappings = node.nonnullMapping().values() @@ -478,46 +516,79 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { } private Map transformSrgToOnep(String orNodeId, - Map> mapSrg) { - Map onepMap = new HashMap<>(); + Map> mapSrg) { + LOG.debug("CREATENEP transformSrgToOnep, ListOfMapping {}, of NodeId {} ", mapSrg, orNodeId); + Map tpMap = new HashMap<>(); + //List tpList = new ArrayList<>(); for (Map.Entry> entry : mapSrg.entrySet()) { // For each srg node. Loop through the LCPs and create neps and sips for PP for (Mapping m:entry.getValue()) { - if (!m.getLogicalConnectionPoint().contains("PP")) { - LOG.info("LCP {} is not an external TP of SRG node", m.getLogicalConnectionPoint()); + String tpId = m.getLogicalConnectionPoint(); + String overlayNodeId = String.join("-", orNodeId, tpId.split("\\-")[0]); + if (!tpId.contains("PP")) { + LOG.info("LCP {} is not an external TP of SRG node", tpId); continue; } - Map srgNeps = - createRoadmNeps(orNodeId, m.getLogicalConnectionPoint(), true, - transformOperState(m.getPortOperState()), transformAdminState(m.getPortAdminState()), - TapiStringConstants.PHTNC_MEDIA_OTS); - onepMap.putAll(srgNeps); + int counter = 50; + do { + counter--; + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOG.debug("Waiting until PP is backported in Topology, Exception raised", e); + } + } while (getNetworkTerminationPoint1FromDatastore(overlayNodeId, tpId) == null && counter != 0); + if (getNetworkTerminationPoint1FromDatastore(overlayNodeId, tpId) != null) { + //tpList.add(getNetworkTerminationPointFromDatastore(overlayNodeId, tpId)); + tpMap.put(tpId, getNetworkTerminationPoint1FromDatastore(overlayNodeId, tpId)); + LOG.debug("LCP {} is not empty for augmentation TP1", tpId); + } else { + LOG.error("CREATENEP transformSrgToOnep, No Tp1 found in topology for LCP {}, of NodeId {} ", + tpId, overlayNodeId); + } + if (getNetworkTerminationPoint11FromDatastore(overlayNodeId, tpId) != null) { + LOG.info("LCP {} is not empty for augmentation TP11", tpId); + } else { + LOG.error("CREATENEP transformSrgToOnep, No Tp11 found in topology for LCP {}, of NodeId {} ", + tpId, overlayNodeId); + } } } - return onepMap; + LOG.debug("TransformSRGToONep for tps {}, of NodeId {} ", + tpMap.entrySet().stream().map(tp -> tp.getKey()).collect(Collectors.toList()).toString(), orNodeId); + return populateNepsForRdmNode(orNodeId, tpMap, false, TapiStringConstants.PHTNC_MEDIA_OTS); } private Map transformDegToOnep(String orNodeId, - Map> mapDeg) { - Map onepMap = new HashMap<>(); + Map> mapDeg) { + LOG.debug("CREATENEP transformDegToOnep, ListOfMapping {}, of NodeId {} ", + mapDeg.toString(), orNodeId); + Map degOnepMap = new HashMap<>(); + Map tpMap = new HashMap<>(); + //List tpList = new ArrayList<>(); for (Map.Entry> entry : mapDeg.entrySet()) { // For each degree node. Loop through the LCPs and create neps and sips for TTP for (Mapping m:entry.getValue()) { - if (!m.getLogicalConnectionPoint().contains("TTP")) { - LOG.info("LCP {} is not an external TP of DEGREE node", m.getLogicalConnectionPoint()); + String tpId = m.getLogicalConnectionPoint(); + String overlayNodeId = String.join("-", orNodeId, tpId.split("\\-")[0]); + if (!tpId.contains("TTP")) { + LOG.info("LCP {} is not an external TP of DEGREE node", tpId); continue; } - Map degNeps = - createRoadmNeps(orNodeId, m.getLogicalConnectionPoint(), false, - transformOperState(m.getPortOperState()), transformAdminState(m.getPortAdminState()), - TapiStringConstants.PHTNC_MEDIA_OTS); - degNeps.putAll(createRoadmNeps(orNodeId, m.getLogicalConnectionPoint(), false, - transformOperState(m.getPortOperState()), transformAdminState(m.getPortAdminState()), - TapiStringConstants.PHTNC_MEDIA_OMS)); - onepMap.putAll(degNeps); + if (getNetworkTerminationPoint1FromDatastore(overlayNodeId, tpId) != null) { + //tpList.add(getNetworkTerminationPointFromDatastore(overlayNodeId, tpId)); + tpMap.put(tpId, getNetworkTerminationPoint1FromDatastore(overlayNodeId, tpId)); + LOG.info("LCP {} is not empty for augmentation TP1", tpId); + } else { + LOG.error("CREATENEP transformDegToOnep, No Tp found in topology for LCP {}, of NodeId {} ", + tpId, overlayNodeId); + } } } - return onepMap; + degOnepMap.putAll(populateNepsForRdmNode(orNodeId, tpMap, false, TapiStringConstants.PHTNC_MEDIA_OTS)); + degOnepMap.putAll(populateNepsForRdmNode(orNodeId, tpMap, false, TapiStringConstants.PHTNC_MEDIA_OMS)); + return degOnepMap; } private List getRoadmNodelist(List mappingList) { @@ -564,10 +635,15 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { return; } if (nodeId.contains("ROADM")) { - // Node is in photonic media layer and UUID can be built from nodeId + PHTN_MEDIA - Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", nodeId, - TapiStringConstants.PHTNC_MEDIA)).getBytes(StandardCharsets.UTF_8)).toString()); - deleteNodeFromTopo(nodeUuid); + if (topologicalMode.equals("Full")) { + // Node is in photonic media layer and UUID can be built from nodeId + PHTN_MEDIA + Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", nodeId, + TapiStringConstants.PHTNC_MEDIA)).getBytes(StandardCharsets.UTF_8)).toString()); + deleteNodeFromTopo(nodeUuid); + } else { + LOG.info("Abstracted Topo Mode in TAPI topology Datastore for OR topology representation. Node" + + " {} is not represented in the abstraction and will not be deleted", nodeId); + } } if (nodeId.contains("XPDR") || nodeId.contains("SPDR") || nodeId.contains("MXPDR")) { // Node is either XPDR, MXPDR or SPDR. Retrieve nodes from topology and check names @@ -640,6 +716,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { Map nodeRuleGroupList = createNodeRuleGroupForDsrNode( nodeId, oorOduSwitchingPool, ruleList, onepl); onepl.putAll(createXpdrPhtnMdNeps(nodeId, xpdrNetMaps)); + LOG.debug("TapiNetworkModelServiceImpl line 721, total NEP map = {}", onepl.toString()); // Empty random creation of mandatory fields for avoiding errors.... CostCharacteristic costCharacteristic = new CostCharacteristicBuilder() @@ -661,7 +738,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { RiskParameterPac riskParamPac = new RiskParameterPacBuilder() .setRiskCharacteristic(Map.of(riskCharacteristic.key(), riskCharacteristic)) .build(); - return new NodeBuilder() + Node builtNode = new NodeBuilder() .setUuid(nodeUuid) .setName(nameMap) .setLayerProtocolName(layerProtocols) @@ -680,10 +757,27 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { .setServerIntegrityProcessCharacteristic("server integrity process") .setRiskParameterPac(riskParamPac) .build(); + List pmnepspecList = new ArrayList<>(); + for (Map.Entry entry : + builtNode.getOwnedNodeEdgePoint().entrySet()) { + if (!entry.getValue().getSupportedCepLayerProtocolQualifierInstances().stream() + .filter(sclpqi -> sclpqi.getLayerProtocolQualifier().equals(PHOTONICLAYERQUALIFIEROTS.VALUE)) + .collect(Collectors.toList()).isEmpty() + && entry.getValue().augmentationOrElseThrow(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang + .tapi.photonic.media.rev221121.OwnedNodeEdgePoint1.class) != null + && entry.getValue().augmentationOrElseThrow(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi + .photonic.media.rev221121.OwnedNodeEdgePoint1.class).getPhotonicMediaNodeEdgePointSpec() + != null) { + pmnepspecList.add(entry.getValue().augmentationOrElseThrow(org.opendaylight.yang.gen.v1.urn.onf.otcc + .yang.tapi.photonic.media.rev221121.OwnedNodeEdgePoint1.class).getPhotonicMediaNodeEdgePointSpec()); + } + } + LOG.debug("TapiNetworkModelServiceImpl line 775, List of non empty PMNEPSEC is = {}", pmnepspecList); + return builtNode; } private Map createXpdrPhtnMdNeps(String nodeId, - List xpdrNetMaps) { + List xpdrNetMaps) { Map onepl = new HashMap<>(); // eNep creation on otsi node @@ -883,52 +977,28 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { } else { LOG.error("CREATENEP, No Tp found in topology for LCP {}, of NodeId {} ", tpid, nodeId); } - onepBldr = tapiFactory.addPayloadStructureAndPhotSpecToOnep(nodeId, freqWidthMap, keyedOpModeList, sicColl, - onepBldr, keyword); + onepBldr = tapiFactory.addPayloadStructureAndPhotSpecToOnep(nodeId, freqWidthMap, keyedOpModeList, + sicColl, onepBldr, keyword); + LOG.debug("TapiNetworkServiceImpl line982, onep = {}", onepBldr.build()); } return onepBldr.build(); } - private Map createRoadmNeps(String orNodeId, String tpId, - boolean withSip, OperationalState operState, AdministrativeState adminState, String nepPhotonicSublayer) { - Map onepMap = new HashMap<>(); - // PHOTONIC MEDIA nep - Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", orNodeId, - nepPhotonicSublayer, tpId)).getBytes(StandardCharsets.UTF_8)).toString()); - Name nepName = new NameBuilder() - .setValueName(TapiStringConstants.PHTNC_MEDIA + "NodeEdgePoint") - .setValue(String.join("+", orNodeId, nepPhotonicSublayer, tpId)) + private Node createRoadmTapiNode(String orNodeId, Map onepMap) { + // UUID and Node Names + Uuid nodeUuid; + Name nodeNames; + if (orNodeId.equals("ROADMINFRA")) { + nodeUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.RDM_INFRA + .getBytes(Charset.forName("UTF-8"))).toString()); + nodeNames = new NameBuilder().setValueName("roadm node name").setValue(TapiStringConstants.RDM_INFRA) .build(); - List sclpqiList = new ArrayList<>(); - sclpqiList.add( - new SupportedCepLayerProtocolQualifierInstancesBuilder() - .setLayerProtocolQualifier( - TapiStringConstants.PHTNC_MEDIA_OMS.equals(nepPhotonicSublayer) - ? PHOTONICLAYERQUALIFIEROMS.VALUE - : PHOTONICLAYERQUALIFIEROTS.VALUE) - .setNumberOfCepInstances(Uint64.valueOf(1)) - .build()); - OwnedNodeEdgePoint onep = new OwnedNodeEdgePointBuilder() - .setUuid(nepUuid) - .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA) - .setName(Map.of(nepName.key(), nepName)) - .setSupportedCepLayerProtocolQualifierInstances(sclpqiList) - .setDirection(Direction.BIDIRECTIONAL) - .setLinkPortRole(PortRole.SYMMETRIC) - .setAdministrativeState(adminState).setOperationalState(operState) - .setLifecycleState(LifecycleState.INSTALLED) - .build(); - onepMap.put(onep.key(), onep); - return onepMap; - } - - private Node createRoadmTapiNode(String orNodeId, Map oneplist) { - // UUID - Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", orNodeId, - TapiStringConstants.PHTNC_MEDIA)).getBytes(StandardCharsets.UTF_8)).toString()); - // Names - Name nodeNames = new NameBuilder().setValueName("roadm node name") - .setValue(String.join("+", orNodeId, TapiStringConstants.PHTNC_MEDIA)).build(); + } else { + nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", orNodeId, + TapiStringConstants.PHTNC_MEDIA)).getBytes(StandardCharsets.UTF_8)).toString()); + nodeNames = new NameBuilder().setValueName("roadm node name") + .setValue(String.join("+", orNodeId, TapiStringConstants.PHTNC_MEDIA)).build(); + } Name nameNodeType = new NameBuilder().setValueName("Node Type") .setValue(OpenroadmNodeType.ROADM.getName()).build(); // Protocol Layer @@ -953,6 +1023,11 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { RiskParameterPac riskParamPac = new RiskParameterPacBuilder() .setRiskCharacteristic(Map.of(riskCharacteristic.key(), riskCharacteristic)) .build(); + Map nodeRuleGroupMap + = tapiFactory.createAllNodeRuleGroupForRdmNode(topologicalMode, nodeUuid, orNodeId, onepMap.values()); + Map interRuleGroupMap + = tapiFactory.createInterRuleGroupForRdmNode(topologicalMode, nodeUuid, orNodeId, + nodeRuleGroupMap.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList())); return new NodeBuilder() .setUuid(nodeUuid) .setName(Map.of(nodeNames.key(), nodeNames, nameNodeType.key(), nameNodeType)) @@ -960,9 +1035,9 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { .setAdministrativeState(AdministrativeState.UNLOCKED) .setOperationalState(OperationalState.ENABLED) .setLifecycleState(LifecycleState.INSTALLED) - .setOwnedNodeEdgePoint(oneplist) - .setNodeRuleGroup(this.tapiFactory - .createNodeRuleGroupForRdmNode("Full", nodeUuid, orNodeId, oneplist.values())) + .setOwnedNodeEdgePoint(onepMap) + .setNodeRuleGroup(nodeRuleGroupMap) + .setInterRuleGroup(interRuleGroupMap) .setCostCharacteristic(Map.of(costCharacteristic.key(), costCharacteristic)) .setLatencyCharacteristic(Map.of(latencyCharacteristic.key(), latencyCharacteristic)) .setErrorCharacteristic("error") @@ -1056,7 +1131,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { LOG.info("No switching pool created for node = {}", nodeId); return new HashMap<>(); } - LOG.info("ONEPL = {}", onepl.values()); + LOG.debug("ONEPL = {}", onepl.values()); Map nodeRuleGroupMap = new HashMap<>(); int count = 1; for (NonBlockingList nbl : oorOduSwitchingPool.nonnullNonBlockingList().values()) { @@ -1323,6 +1398,108 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { } } + private Map populateNepsForRdmNode(String nodeId, + Map tpMap, boolean withSip, String nepPhotonicSublayer) { + // create neps for MC and and Photonic Media OTS/OMS + Map onepMap = new HashMap<>(); + for (Map.Entry entry : tpMap.entrySet()) { + // Admin and oper state common for all tps + OpenroadmTpType tpType = entry.getValue().getTpType(); + // PHOTONIC MEDIA nep + LOG.debug("PHOTO NEP = {}", String.join("+", nodeId, nepPhotonicSublayer, + entry.getKey())); + SupportedCepLayerProtocolQualifierInstancesBuilder sclpqiBd = + new SupportedCepLayerProtocolQualifierInstancesBuilder() + .setNumberOfCepInstances(Uint64.valueOf(1)); + switch (nepPhotonicSublayer) { + case TapiStringConstants.PHTNC_MEDIA_OMS: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROMS.VALUE); + break; + case TapiStringConstants.PHTNC_MEDIA_OTS: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTS.VALUE); + break; + case TapiStringConstants.MC: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIERMC.VALUE); + break; + case TapiStringConstants.OTSI_MC: + sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTSiMC.VALUE); + break; + default: + break; + } + + List sclpqiList = new ArrayList<>(List.of(sclpqiBd.build())); + OwnedNodeEdgePointBuilder onepBd = new OwnedNodeEdgePointBuilder(); + if (!nepPhotonicSublayer.equals(TapiStringConstants.MC) + && !nepPhotonicSublayer.equals(TapiStringConstants.OTSI_MC)) { + Map usedFreqMap = new HashMap<>(); + Map availableFreqMap = new HashMap<>(); + switch (tpType) { + // Whatever is the TP and its type we consider that it is handled in a bidirectional way : + // same wavelength(s) used in both direction. + case SRGRXPP: + case SRGTXPP: + case SRGTXRXPP: + usedFreqMap = tapiFactory.getPP11UsedWavelength( + getNetworkTerminationPoint11FromDatastore(nodeId, entry.getKey())); + if (usedFreqMap == null || usedFreqMap.isEmpty()) { + availableFreqMap.put(GridConstant.START_EDGE_FREQUENCY * 1E09, + GridConstant.START_EDGE_FREQUENCY * 1E09 + + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E06); + } else { + LOG.debug("EnteringLOOPcreateOTSiMC & MC with usedFreqMap non empty {} for Node {}, tp {}", + usedFreqMap.toString(), nodeId, tpMap.toString()); + onepMap.putAll(populateNepsForRdmNode(nodeId, + new HashMap<>(Map.of(entry.getKey(), entry.getValue())), + true, TapiStringConstants.MC)); + onepMap.putAll(populateNepsForRdmNode(nodeId, + new HashMap<>(Map.of(entry.getKey(), entry.getValue())), + true, TapiStringConstants.OTSI_MC)); + } + break; + case DEGREERXTTP: + case DEGREETXTTP: + case DEGREETXRXTTP: + usedFreqMap = tapiFactory.getTTP11UsedFreqMap( + getNetworkTerminationPoint11FromDatastore(nodeId, entry.getKey())); + availableFreqMap = tapiFactory.getTTP11AvailableFreqMap( + getNetworkTerminationPoint11FromDatastore(nodeId, entry.getKey())); + break; + default: + break; + } + LOG.debug("calling add Photonic NEP spec for Roadm"); + onepBd = tapiFactory.addPhotSpecToRoadmOnep(nodeId, usedFreqMap, availableFreqMap, onepBd, + nepPhotonicSublayer); + } + AdminStates admin = entry.getValue().getAdministrativeState(); + State oper = entry.getValue().getOperationalState(); + Name nepName = new NameBuilder() + .setValueName(nepPhotonicSublayer + "NodeEdgePoint") + .setValue(String.join("+", nodeId, nepPhotonicSublayer, + entry.getKey())) + .build(); + OwnedNodeEdgePoint onep = onepBd + .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", nodeId, + nepPhotonicSublayer, entry.getKey())) + .getBytes(Charset.forName("UTF-8"))).toString())) + .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA) + .setName(Map.of(nepName.key(), nepName)) + .setSupportedCepLayerProtocolQualifierInstances(sclpqiList) + .setDirection(Direction.BIDIRECTIONAL) + .setLinkPortRole(PortRole.SYMMETRIC) + .setAdministrativeState(this.tapiLink.setTapiAdminState(admin.getName())) + .setOperationalState(this.tapiLink.setTapiOperationalState(oper.getName())) + .setLifecycleState(LifecycleState.INSTALLED) + .build(); + LOG.debug("ROADMNEPPopulation TapiNetworkModelServiceImpl populate NEP {} for Node {}", + onep.getName().entrySet(), nodeId); + onepMap.put(onep.key(), onep); + } + LOG.debug("ROADMNEPPopulation FINISH for Node {}", nodeId); + return onepMap; + } + /** * Get a network termination point for nodeId and tpId. * @param nodeId String @@ -1344,22 +1521,100 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService { new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226 .networks.network.node.TerminationPointKey(new TpId(tpId))) .build(); - try (ReadTransaction readTx = this.networkTransactionService.getDataBroker().newReadOnlyTransaction()) { - Optional optionalTerminationPoint = readTx - .read(LogicalDatastoreType.CONFIGURATION, tpIID) - .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS); - return optionalTerminationPoint.isEmpty() ? null : optionalTerminationPoint.orElseThrow(); - } catch (ExecutionException | TimeoutException e) { + try { + Optional tpOptional = + networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, tpIID).get(); + if (tpOptional.isEmpty()) { + LOG.error("readMdSal: Error reading tp {} , empty list",tpIID); + return null; + } + LOG.debug("SUCCES getting LCP TP for NodeId {} TpId {} while creating NEP in TapiNetworkModelServiceImpl", + nodeId, tpId); + LOG.debug(" The Tp in Datastore is as follows {}", tpOptional); + return tpOptional.orElseThrow(); + } catch (ExecutionException | InterruptedException e) { LOG.warn("Exception while getting termination {} for node id {} point from {} topology", tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e); return null; - } catch (InterruptedException e) { - LOG.warn("Getting termination {} for node id {} point from {} topology was interrupted", + } + } + + /** + * Get a network termination point with Common TerminationPoint1 augmentation for nodeId and tpId. + * @param nodeId String + * @param tpId String + * @return network termination point, null otherwise + */ + private TerminationPoint1 getNetworkTerminationPoint1FromDatastore(String nodeId, String tpId) { + InstanceIdentifier tpIID = InstanceIdentifier.builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .child( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226 + .networks.network.Node.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226 + .networks.network.NodeKey(new NodeId(nodeId))) + .augmentation(Node1.class) + .child( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226 + .networks.network.node.TerminationPoint.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226 + .networks.network.node.TerminationPointKey(new TpId(tpId))) + .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526 + .TerminationPoint1.class) + .build(); + try { + Optional tpOptional = + networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, tpIID).get(); + if (tpOptional.isEmpty()) { + LOG.error("readMdSal: Error reading tp {} , empty list",tpIID); + return null; + } + LOG.debug("SUCCES getting LCP TP1 for NodeId {} TpId {} while creating NEP in TapiNetworkModelServiceImpl", + nodeId, tpId); + LOG.debug(" The Tp in Datastore is as follows {}", tpOptional); + return tpOptional.orElseThrow(); + } catch (ExecutionException | InterruptedException e) { + LOG.warn("Exception while getting termination {} for node id {} point from {} topology", tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e); - Thread.currentThread().interrupt(); return null; } } + private org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1 + getNetworkTerminationPoint11FromDatastore(String nodeId, String tpId) { + InstanceIdentifier + tpIID = InstanceIdentifier.builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .child( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226 + .networks.network.Node.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226 + .networks.network.NodeKey(new NodeId(nodeId))) + .augmentation(Node1.class) + .child( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226 + .networks.network.node.TerminationPoint.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226 + .networks.network.node.TerminationPointKey(new TpId(tpId))) + .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1 + .class) + .build(); + try { + Optional + tpOptional = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, tpIID).get(); + if (tpOptional.isEmpty()) { + LOG.error("readMdSal: Error reading tp {} , empty list",tpIID); + return null; + } + LOG.debug("SUCCESS getting LCP TP11 for NodeId {} TpId {} while creating NEP in TapiNetworkModelServiceImpl" + + " The Tp in Datastore is as follows {}", + nodeId, tpId, tpOptional.toString()); + return tpOptional.orElseThrow(); + } catch (ExecutionException | InterruptedException e) { + LOG.warn("Exception while getting termination {} for node id {} point from {} topology", + tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e); + return null; + } + } } diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiPortMappingListener.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiPortMappingListener.java index 95b0d9856..a25858a70 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiPortMappingListener.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiPortMappingListener.java @@ -67,6 +67,10 @@ public class TapiPortMappingListener implements DataTreeChangeListener { } } } + } else if (change.getRootNode().getDataAfter() != null && change.getRootNode().getDataBefore() == null) { + Nodes nodesAft = change.getRootNode().getDataAfter(); + this.tapiNetworkModelService.createTapiNode(nodesAft.getNodeId(), + nodesAft.getNodeInfo().getOpenroadmVersion().getIntValue(), nodesAft); } } } 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 640fc9f5c..9eca76d69 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 @@ -77,6 +77,7 @@ public final class TopologyUtils { private static final Logger LOG = LoggerFactory.getLogger(TopologyUtils.class); private Map tapiSips; private final TapiLink tapiLink; + 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, @@ -85,6 +86,8 @@ public final class TopologyUtils { this.dataBroker = dataBroker; this.tapiSips = new HashMap<>(); this.tapiLink = tapiLink; + // TODO: Initially set topological mode to Full. Shall be set through the setter at controller initialization + this.topologicalMode = "Full"; } public Network readTopology(InstanceIdentifier networkIID) throws TapiTopologyException { @@ -138,10 +141,11 @@ public final class TopologyUtils { public Topology createFullOtnTopology() throws TapiTopologyException { // read openroadm-topology Network openroadmTopo = readTopology(InstanceIdentifiers.OVERLAY_NETWORK_II); - Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER - .getBytes(Charset.forName("UTF-8"))).toString()); + 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(TapiStringConstants.T0_FULL_MULTILAYER) + .setValue(topoType) .setValueName("TAPI Topology Name") .build(); if (openroadmTopo != null) { @@ -212,28 +216,38 @@ public final class TopologyUtils { .equals(OpenroadmNodeType.ROADM)) .count() > 0) { // map roadm nodes - 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); + 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"); this.tapiSips.putAll(tapiFullFactory.getTapiSips()); tapiNodeList.putAll(tapiFullFactory.getTapiNodes()); tapiLinkList.putAll(tapiFullFactory.getTapiLinks()); } + } else { LOG.warn("No roadm nodes exist in the network"); } - // 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()); + // map xpdr_input to roadm and xpdr_output to roadm links. xponderInLinkList.addAll(xponderOutLinkList); tapiFullFactory.convertXpdrToRdmLinks(xponderInLinkList); @@ -241,27 +255,19 @@ public final class TopologyUtils { // Retrieve created sips map in TapiFactory when mapping all the nodes this.tapiSips.putAll(tapiFullFactory.getTapiSips()); - var topo = new TopologyBuilder() - .setName(Map.of(name.key(), name)) - .setUuid(topoUuid) - .setNode(tapiNodeList) - .setLayerProtocolName(Set.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU, - LayerProtocolName.DSR)) - .setLink(tapiLinkList).build(); - LOG.error("TOPOUTIL, Initial FullTopology Builder.build = {}", topo.toString()); return new TopologyBuilder() .setName(Map.of(name.key(), name)) .setUuid(topoUuid) .setNode(tapiNodeList) .setLayerProtocolName(Set.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU, - LayerProtocolName.DSR)) + 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.DSR, LayerProtocolName.DIGITALOTN)) .build(); } @@ -378,4 +384,12 @@ public final class TopologyUtils { return tapiSips; } + public void setTopologicalMode(String topoMode) { + this.topologicalMode = topoMode; + } + + public String getTopologicalMode() { + return topologicalMode; + } + } diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java index b75cb2d70..f2e5b8ddb 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiContext.java @@ -232,7 +232,7 @@ public class TapiContext { Optional optionalOnep = this.networkTransactionService.read( LogicalDatastoreType.OPERATIONAL, onepIID).get(); if (!optionalOnep.isPresent()) { - LOG.error("ONEP is not present in datastore"); + LOG.error("ONEP is not present in datastore for topoUuid {}, NodeUuid {}", topoUuid, nodeUuid); return; } OwnedNodeEdgePoint onep = optionalOnep.orElseThrow(); @@ -587,7 +587,7 @@ public class TapiContext { try { Optional optNode = this.networkTransactionService .read(LogicalDatastoreType.OPERATIONAL, nepIID).get(); - if (!optNode.isPresent()) { + if (optNode.isEmpty()) { LOG.error(NODE_NOT_PRESENT); return null; } diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiLinkImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiLinkImpl.java index 0213e03fa..25d0e64d4 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiLinkImpl.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/utils/TapiLinkImpl.java @@ -108,7 +108,7 @@ public class TapiLinkImpl implements TapiLink { case TapiStringConstants.OMS_RDM_RDM_LINK: LOG.info("Roadm to roadm link"); linkName - .setValueName("OMS link name") + .setValueName(TapiStringConstants.VALUE_NAME_OMS_RDM_RDM_LINK) .setValue(linkKey); break; case TapiStringConstants.TRANSITIONAL_LINK: @@ -118,7 +118,7 @@ public class TapiLinkImpl implements TapiLink { .setValue(linkKey); break; case TapiStringConstants.OMS_XPDR_RDM_LINK: - LOG.info("Xpdr to roadm link"); + LOG.info(TapiStringConstants.VALUE_NAME_OTS_XPDR_RDM_LINK); linkName .setValueName("XPDR-RDM link name") .setValue(linkKey); @@ -126,7 +126,7 @@ public class TapiLinkImpl implements TapiLink { case TapiStringConstants.OTN_XPDR_XPDR_LINK: LOG.info("OTN Xpdr to roadm link"); linkName - .setValueName("otn link name") + .setValueName(TapiStringConstants.VALUE_NAME_OTN_XPDR_XPDR_LINK) .setValue(linkKey); break; default: diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java index 0c371e95d..57e4ba097 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToFullTapiTopoTest.java @@ -87,6 +87,7 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.dsr.rev221121.DIGITAL import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROMS; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTS; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTSi; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.FORWARDINGRULECANNOTFORWARDACROSSGROUP; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.FORWARDINGRULEMAYFORWARDACROSSGROUP; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.RuleType; import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroup; @@ -375,7 +376,7 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { @Test void convertNodeForRoadmWhenNoOtnMuxAttached() { ConvertORTopoToTapiFullTopo tapiFullFactory = new ConvertORTopoToTapiFullTopo(topologyUuid, tapiLink); - tapiFullFactory.convertRoadmNode(roadmA, openroadmNet); + tapiFullFactory.convertRoadmNode(roadmA, openroadmNet, "Full"); assertEquals(1, tapiFullFactory.getTapiNodes().size(), "Node list size should be 1"); assertEquals(0, tapiFullFactory.getTapiLinks().size(), "Link list size should be empty"); @@ -389,8 +390,8 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { @Test void convertNodeForRoadmWhenRoadmNeighborAttached() { ConvertORTopoToTapiFullTopo tapiFullFactory = new ConvertORTopoToTapiFullTopo(topologyUuid, tapiLink); - tapiFullFactory.convertRoadmNode(roadmA, openroadmNet); - tapiFullFactory.convertRoadmNode(roadmC, openroadmNet); + tapiFullFactory.convertRoadmNode(roadmA, openroadmNet, "Full"); + tapiFullFactory.convertRoadmNode(roadmC, openroadmNet, "Full"); List rdmTordmLinkList = ortopoLinks.values().stream() .filter(lk -> lk.augmentation(Link1.class).getLinkType().equals(OpenroadmLinkType.ROADMTOROADM)) @@ -448,7 +449,7 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { } tapiFactory.convertNode(otnMuxA, networkPortListA); tapiFullFactory.setTapiNodes(tapiFactory.getTapiNodes()); - tapiFullFactory.convertRoadmNode(roadmA, openroadmNet); + tapiFullFactory.convertRoadmNode(roadmA, openroadmNet, "Full"); List xponderOutLinkList = ortopoLinks.values().stream() .filter(lk -> lk.augmentation(Link1.class).getLinkType().equals(OpenroadmLinkType.XPONDEROUTPUT)) .filter(lk1 -> ((lk1.getSource().getSourceNode().equals(otnMuxA.getNodeId()) @@ -804,9 +805,12 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { checkNepOtsiRdmNode(otsNep4, otsNep4Uuid, nodeId + "+PHOTONIC_MEDIA_OTS+SRG1-PP3-TXRX", "PHOTONIC_MEDIA_OTSNodeEdgePoint", false); List nrgList4 = node.nonnullNodeRuleGroup().values().stream() - .sorted((nrg1, nrg2) -> nrg1.getUuid().getValue().compareTo(nrg2.getUuid().getValue())) + .sorted((nrg1, nrg2) -> nrg1.getName().entrySet().iterator().next().getValue().toString() + .compareTo(nrg2.getName().entrySet().iterator().next().getValue().toString())) .collect(Collectors.toList()); - checkNodeRuleGroupForRdm(nrgList4, 12); + LOG.info("NODERULEGROUP List nrgLIst4 is as follows {}", nrgList4.toString()); + List nepNumber = new ArrayList<>(List.of(2, 4, 4)); + checkNodeRuleGroupForRdm(nrgList4, nepNumber); break; default: fail(); @@ -973,22 +977,27 @@ public class ConvertORTopoToFullTapiTopoTest extends AbstractTest { "the rule type should be 'FORWARDING'"); } - private void checkNodeRuleGroupForRdm(List nrgList, int nbNeps) { - assertEquals(1, nrgList.size(), "RDM infra node - OTSi should contain a single node rule groups"); - if (nbNeps > 0) { - List nodeEdgePointList = new ArrayList<>(nrgList.get(0).getNodeEdgePoint().values()); - assertEquals(nbNeps, nodeEdgePointList.size(), - "RDM infra node -rule-group should contain " + nbNeps + " NEP"); - } else { - assertNull(nrgList.get(0).getNodeEdgePoint(), "RDM infra node -rule-group should contain no NEP"); + private void checkNodeRuleGroupForRdm(List nrgList, List nbNeps) { + assertEquals(3, nrgList.size(), "RDM infra node - OTS should contain 3 node rule groups"); + int index = 0; + for (NodeRuleGroup nrg : nrgList) { + List nodeEdgePointList = new ArrayList<>(nrg.getNodeEdgePoint().values()); + assertEquals(nbNeps.get(index), nodeEdgePointList.size(), + "RDM infra node -rule-group should contain " + nbNeps.get(index) + " NEP"); + List ruleList = new ArrayList<>(nrg.nonnullRule().values()); + assertEquals(1, ruleList.size(), "node-rule-group should contain a single rule"); + assertEquals("forward", ruleList.get(0).getLocalId(), "local-id of the rule should be 'forward'"); + assertEquals(RuleType.FORWARDING, ruleList.get(0).getRuleType().stream().findFirst().orElseThrow(), + "the rule type should be 'FORWARDING'"); + if (nrg.getName().entrySet().iterator().next().getValue().toString().contains("DEG")) { + assertEquals(FORWARDINGRULEMAYFORWARDACROSSGROUP.VALUE, ruleList.get(0).getForwardingRule(), + "the forwarding rule should be 'MAYFORWARDACROSSGROUP'"); + } else { + assertEquals(FORWARDINGRULECANNOTFORWARDACROSSGROUP.VALUE, ruleList.get(0).getForwardingRule(), + "the forwarding rule should be 'CANNOTFORWARDACROSSGROUP'"); + } + index++; } - List ruleList = new ArrayList<>(nrgList.get(0).nonnullRule().values()); - assertEquals(1, ruleList.size(), "node-rule-group should contain a single rule"); - assertEquals("forward", ruleList.get(0).getLocalId(), "local-id of the rule should be 'forward'"); - assertEquals(FORWARDINGRULEMAYFORWARDACROSSGROUP.VALUE, ruleList.get(0).getForwardingRule(), - "the forwarding rule should be 'MAYFORWARDACROSSGROUP'"); - assertEquals(RuleType.FORWARDING, ruleList.get(0).getRuleType().stream().findFirst().orElseThrow(), - "the rule type should be 'FORWARDING'"); } private void checkNodeRuleGroupForTpdrOTSi(List nrgList, Uuid enepUuid, Uuid inepUuid, diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java index b017dd0c6..395f9b34f 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORTopoToTapiTopoTest.java @@ -14,6 +14,7 @@ import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import com.google.common.util.concurrent.FluentFuture; @@ -1000,7 +1001,12 @@ public class ConvertORTopoToTapiTopoTest extends AbstractTest { } private void checkNodeRuleGroupForRdmInfra(List nrgList, int nbNeps) { - assertEquals(1, nrgList.size(), "RDM infra node - OTSi should contain a single node rule groups"); + // if no XPDR is connected, no OTS is created and no NodeRuleGroup is created + assertTrue(nrgList.size() <= 1, "RDM infra node - OTSi should contain maximum one node rule groups"); + // When a nrg is present it shall respect the following + if (nrgList.isEmpty()) { + return; + } if (nbNeps > 0) { List nodeEdgePointList = new ArrayList<>(nrgList.get(0).getNodeEdgePoint().values()); assertEquals(nbNeps, nodeEdgePointList.size(), diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java index 3277b98fd..427b63757 100644 --- a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/TapiTopologyImplTest.java @@ -334,7 +334,7 @@ public class TapiTopologyImplTest extends AbstractTest { @Nullable Topology topology = rpcResult.getResult().getTopology(); assertNotNull(topology, "Topology should not be null"); - // 2 Nodes per Xpdr/Spdr node (DSR-ODU & PHOT) + 3 Node per Roadm + // 2 ROADM Nodes, 2 XPDR Nodes, 6 SPDR Nodes assertEquals(10, topology.getNode().size(), "Node list size should be 10"); List> nodeNames = topology.getNode().values().stream() .filter(node -> node.getLayerProtocolName().contains(LayerProtocolName.PHOTONICMEDIA)) diff --git a/tests/transportpce_tests/tapi/test01_abstracted_topology.py b/tests/transportpce_tests/tapi/test01_abstracted_topology.py index 69800bab3..2a2cec4e8 100644 --- a/tests/transportpce_tests/tapi/test01_abstracted_topology.py +++ b/tests/transportpce_tests/tapi/test01_abstracted_topology.py @@ -269,8 +269,8 @@ class TransportTapitesting(unittest.TestCase): 'Topology should contain 1 otsi nodes') self.assertIn("PHOTONIC_MEDIA", response["output"]["topology"]["node"][0]["layer-protocol-name"], 'Node layer protocol should contain PHOTONIC_MEDIA') - self.assertEqual(1, len(response["output"]["topology"]["node"][0]["node-rule-group"]), - 'node should contain 1 node rule group') + self.assertNotIn("node-rule-group", response["output"]["topology"]["node"][0], + 'Topology should contain no node-rule-group') def test_11_connect_xpdra_n1_to_roadma_pp1(self): response = test_utils.transportpce_api_rpc_request( -- 2.36.6