2 * Copyright © 2021 Nokia. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.transportpce.tapi.topology;
10 import java.nio.charset.Charset;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
16 import java.util.UUID;
17 import java.util.stream.Collectors;
18 import org.opendaylight.transportpce.tapi.TapiStringConstants;
19 import org.opendaylight.transportpce.tapi.utils.TapiLink;
20 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Link1;
21 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.TerminationPoint1;
22 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmNodeType;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmTpType;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev230526.Node1;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
30 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.AdministrativeState;
31 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Direction;
32 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LayerProtocolName;
33 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LifecycleState;
34 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.OperationalState;
35 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.PortRole;
36 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Uuid;
37 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.Name;
38 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameBuilder;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameKey;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePoint;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePointKey;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROMS;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTS;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePoint;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointBuilder;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointKey;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.RiskParameterPacBuilder;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.edge.point.SupportedCepLayerProtocolQualifierInstancesBuilder;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.risk.parameter.pac.RiskCharacteristic;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.risk.parameter.pac.RiskCharacteristicBuilder;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Link;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.LinkKey;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeBuilder;
54 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeKey;
55 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.cost.pac.CostCharacteristic;
56 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.cost.pac.CostCharacteristicBuilder;
57 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.timing.pac.LatencyCharacteristic;
58 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.timing.pac.LatencyCharacteristicBuilder;
59 import org.opendaylight.yangtools.yang.common.Uint64;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
64 public class ConvertORTopoToTapiFullTopo {
66 private static final Logger LOG = LoggerFactory.getLogger(ConvertORTopoToTapiFullTopo.class);
67 private String ietfNodeId;
68 private OpenroadmNodeType ietfNodeType;
69 private Uuid tapiTopoUuid;
70 private Map<NodeKey, org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node>
72 private Map<LinkKey, Link> tapiLinks;
73 private Map<ServiceInterfacePointKey, ServiceInterfacePoint> tapiSips;
74 private final TapiLink tapiLink;
77 public ConvertORTopoToTapiFullTopo(Uuid tapiTopoUuid, TapiLink tapiLink) {
78 this.tapiTopoUuid = tapiTopoUuid;
79 this.tapiNodes = new HashMap<>();
80 this.tapiLinks = new HashMap<>();
81 this.tapiSips = new HashMap<>();
82 this.tapiLink = tapiLink;
85 public void convertRdmToRdmLinks(
86 List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
87 .networks.network.Link> rdmTordmLinkList) {
88 List<String> linksToNotConvert = new ArrayList<>();
89 LOG.info("creation of {} roadm to roadm links", rdmTordmLinkList.size() / 2);
90 for (var link : rdmTordmLinkList) {
91 if (!linksToNotConvert.contains(link.getLinkId().getValue())) {
92 var oppositeLink = rdmTordmLinkList.stream()
93 .filter(l -> l.getLinkId().equals(link.augmentation(Link1.class).getOppositeLink()))
94 .findAny().orElse(null);
95 AdminStates oppLnkAdmState = null;
96 State oppLnkOpState = null;
97 if (oppositeLink != null) {
98 oppLnkAdmState = oppositeLink.augmentation(Link1.class).getAdministrativeState();
99 oppLnkOpState = oppositeLink.augmentation(Link1.class).getOperationalState();
102 Link tapLink = this.tapiLink.createTapiLink(
104 link.getSource().getSourceNode().getValue().split("-")[0],
105 link.getSource().getSourceNode().getValue().split("-")[1]),
106 link.getSource().getSourceTp().getValue(),
108 link.getDestination().getDestNode().getValue().split("-")[0],
109 link.getDestination().getDestNode().getValue().split("-")[1]),
110 link.getDestination().getDestTp().getValue(), TapiStringConstants.OMS_RDM_RDM_LINK,
111 TapiStringConstants.PHTNC_MEDIA, TapiStringConstants.PHTNC_MEDIA,
112 TapiStringConstants.PHTNC_MEDIA_OTS, TapiStringConstants.PHTNC_MEDIA_OTS,
114 link.augmentation(Link1.class).getAdministrativeState() == null || oppLnkAdmState == null
116 : this.tapiLink.setTapiAdminState(
117 link.augmentation(Link1.class).getAdministrativeState(), oppLnkAdmState).getName(),
119 link.augmentation(Link1.class).getOperationalState() == null || oppLnkOpState == null
121 : this.tapiLink.setTapiOperationalState(
122 link.augmentation(Link1.class).getOperationalState(), oppLnkOpState).getName(),
123 Set.of(LayerProtocolName.PHOTONICMEDIA), Set.of(LayerProtocolName.PHOTONICMEDIA.getName()),
125 linksToNotConvert.add(link.augmentation(Link1.class).getOppositeLink().getValue());
126 tapiLinks.put(tapLink.key(), tapLink);
131 public void convertRoadmNode(Node roadm, Network openroadmTopo) {
132 this.ietfNodeId = roadm.getNodeId().getValue();
133 this.ietfNodeType = roadm.augmentation(
134 org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class)
136 Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> oneplist = new HashMap<>();
137 // 1. Get degree and srg nodes to map TPs into NEPs
138 if (openroadmTopo.getNode() == null) {
139 LOG.warn("Openroadm-topology is null.");
144 List<Node> nodeList = new ArrayList<Node>(openroadmTopo.getNode().values());
145 for (Node node:nodeList) {
146 if (node.getSupportingNode().values().stream()
147 .noneMatch(sp -> sp.getNodeRef().getValue().equals(this.ietfNodeId))) {
148 LOG.debug("Abstracted node {} is not part of {}", node.getNodeId().getValue(), this.ietfNodeId);
151 if (node.augmentation(Node1.class) == null
152 && node.augmentation(
153 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
154 .Node1.class) == null) {
155 LOG.warn("Abstracted node {} doesnt have type of node or is not disaggregated",
156 node.getNodeId().getValue());
159 OpenroadmNodeType nodeType = node.augmentation(
160 org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class)
162 var node1 = node.augmentation(
163 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class);
164 LOG.info("TPs of node: {}", node1.getTerminationPoint().values());
165 switch (nodeType.getIntValue()) {
167 LOG.info("Degree node");
168 // Get only external TPs of the degree
169 List<TerminationPoint> degPortList = node1.getTerminationPoint().values().stream()
170 .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
171 == OpenroadmTpType.DEGREETXRXTTP.getIntValue()
172 || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
173 == OpenroadmTpType.DEGREERXTTP.getIntValue()
174 || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
175 == OpenroadmTpType.DEGREETXTTP.getIntValue())
176 .collect(Collectors.toList());
177 // Convert TP List in NEPs and put it in onepl
178 LOG.info("Degree port List: {}", degPortList);
179 // TODO: deg port could be sip. e.g. MDONS
180 oneplist.putAll(populateNepsForRdmNode(degPortList, false, TapiStringConstants.PHTNC_MEDIA_OTS));
181 oneplist.putAll(populateNepsForRdmNode(degPortList, false, TapiStringConstants.PHTNC_MEDIA_OMS));
182 numNeps += degPortList.size() * 2;
185 LOG.info("SRG node");
186 // Get only external TPs of the srg
187 List<TerminationPoint> srgPortList = node1.getTerminationPoint().values().stream()
188 .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
189 == OpenroadmTpType.SRGTXRXPP.getIntValue()
190 || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
191 == OpenroadmTpType.SRGRXPP.getIntValue()
192 || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
193 == OpenroadmTpType.SRGTXPP.getIntValue())
194 .collect(Collectors.toList());
195 // Convert TP List in NEPs and put it in onepl
196 LOG.info("Srg port List: {}", srgPortList);
197 oneplist.putAll(populateNepsForRdmNode(srgPortList, true, TapiStringConstants.PHTNC_MEDIA_OTS));
198 numNeps += srgPortList.size();
199 numSips += srgPortList.size();
202 LOG.error("Node {} type not supported", nodeType.getName());
207 String nodeIdPhMed = String.join("+", roadm.getNodeId().getValue(), TapiStringConstants.PHTNC_MEDIA);
208 Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeIdPhMed.getBytes(Charset.forName("UTF-8"))).toString());
209 LOG.info("Creation of PHOTONIC node for {}, of Uuid {}", roadm.getNodeId().getValue(), nodeUuid);
211 Name nodeNames = new NameBuilder().setValueName("roadm node name").setValue(nodeIdPhMed).build();
212 Name nameNodeType = new NameBuilder().setValueName("Node Type").setValue(this.ietfNodeType.getName()).build();
214 Set<LayerProtocolName> layerProtocols = Set.of(LayerProtocolName.PHOTONICMEDIA);
216 var roadmNode = createRoadmTapiNode(
217 nodeUuid, Map.of(nodeNames.key(), nodeNames, nameNodeType.key(), nameNodeType), layerProtocols, oneplist);
218 // TODO add states corresponding to device config
219 LOG.info("ROADM node {} should have {} NEPs and {} SIPs", roadm.getNodeId().getValue(), numNeps, numSips);
220 LOG.info("ROADM node {} has {} NEPs and {} SIPs",
221 roadm.getNodeId().getValue(),
222 roadmNode.nonnullOwnedNodeEdgePoint().values().size(),
223 roadmNode.nonnullOwnedNodeEdgePoint().values().stream()
224 .filter(nep -> nep.getMappedServiceInterfacePoint() != null).count());
225 tapiNodes.put(roadmNode.key(), roadmNode);
228 private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node createRoadmTapiNode(
229 Uuid nodeUuid, Map<NameKey, Name> nameMap, Set<LayerProtocolName> layerProtocols,
230 Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> oneplist) {
231 // Empty random creation of mandatory fields for avoiding errors....
232 CostCharacteristic costCharacteristic = new CostCharacteristicBuilder()
233 .setCostAlgorithm("Restricted Shortest Path - RSP")
234 .setCostName("HOP_COUNT")
235 .setCostValue(TapiStringConstants.COST_HOP_VALUE)
237 LatencyCharacteristic latencyCharacteristic = new LatencyCharacteristicBuilder()
238 .setFixedLatencyCharacteristic(TapiStringConstants.FIXED_LATENCY_VALUE)
239 .setQueuingLatencyCharacteristic(TapiStringConstants.QUEING_LATENCY_VALUE)
240 .setJitterCharacteristic(TapiStringConstants.JITTER_VALUE)
241 .setWanderCharacteristic(TapiStringConstants.WANDER_VALUE)
242 .setTrafficPropertyName("FIXED_LATENCY")
244 RiskCharacteristic riskCharacteristic = new RiskCharacteristicBuilder()
245 .setRiskCharacteristicName("risk characteristic")
246 .setRiskIdentifierList(Set.of("risk identifier1", "risk identifier2"))
248 return new NodeBuilder()
251 .setLayerProtocolName(layerProtocols)
252 .setAdministrativeState(AdministrativeState.UNLOCKED)
253 .setOperationalState(OperationalState.ENABLED)
254 .setLifecycleState(LifecycleState.INSTALLED)
255 .setOwnedNodeEdgePoint(oneplist)
256 .setNodeRuleGroup(new ConvertORToTapiTopology(this.tapiTopoUuid)
257 .createNodeRuleGroupForRdmNode("Full",nodeUuid, this.ietfNodeId, oneplist.values()))
258 .setCostCharacteristic(Map.of(costCharacteristic.key(), costCharacteristic))
259 .setLatencyCharacteristic(Map.of(latencyCharacteristic.key(), latencyCharacteristic))
260 .setRiskParameterPac(
261 new RiskParameterPacBuilder()
262 .setRiskCharacteristic(Map.of(riskCharacteristic.key(), riskCharacteristic))
264 .setErrorCharacteristic("error")
265 .setLossCharacteristic("loss")
266 .setRepeatDeliveryCharacteristic("repeat delivery")
267 .setDeliveryOrderCharacteristic("delivery order")
268 .setUnavailableTimeCharacteristic("unavailable time")
269 .setServerIntegrityProcessCharacteristic("server integrity process")
273 private Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> populateNepsForRdmNode(
274 List<TerminationPoint> tpList, boolean withSip, String nepPhotonicSublayer) {
275 // create neps for MC and OTSiMC and Photonic Media
276 Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> onepMap = new HashMap<>();
277 for (TerminationPoint tp:tpList) {
278 // PHOTONIC MEDIA nep
279 String nodeIdNepTp = String.join("+", this.ietfNodeId, nepPhotonicSublayer, tp.getTpId().getValue());
280 LOG.info("PHOTO NEP = {}", nodeIdNepTp);
281 Name nepName = new NameBuilder()
282 .setValueName(nepPhotonicSublayer + "NodeEdgePoint")
283 .setValue(nodeIdNepTp)
285 OwnedNodeEdgePoint onep = new OwnedNodeEdgePointBuilder()
286 .setUuid(new Uuid(UUID.nameUUIDFromBytes(nodeIdNepTp.getBytes(Charset.forName("UTF-8"))).toString()))
287 .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA)
288 .setName(Map.of(nepName.key(), nepName))
289 .setSupportedCepLayerProtocolQualifierInstances(
290 new ArrayList<>(List.of(
291 new SupportedCepLayerProtocolQualifierInstancesBuilder()
292 .setLayerProtocolQualifier(
293 TapiStringConstants.PHTNC_MEDIA_OMS.equals(nepPhotonicSublayer)
294 ? PHOTONICLAYERQUALIFIEROMS.VALUE
295 : PHOTONICLAYERQUALIFIEROTS.VALUE)
296 .setNumberOfCepInstances(Uint64.valueOf(1))
298 .setDirection(Direction.BIDIRECTIONAL)
299 .setLinkPortRole(PortRole.SYMMETRIC)
300 .setAdministrativeState(this.tapiLink.setTapiAdminState(
301 // Admin state common for all tps
302 tp.augmentation(TerminationPoint1.class).getAdministrativeState().getName()))
303 .setOperationalState(this.tapiLink.setTapiOperationalState(
304 // Oper state common for all tps
305 tp.augmentation(TerminationPoint1.class).getOperationalState().getName()))
306 .setLifecycleState(LifecycleState.INSTALLED)
308 onepMap.put(onep.key(), onep);
313 public void convertXpdrToRdmLinks(
314 List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
315 .networks.network.Link> xpdrRdmLinkList) {
316 List<String> linksToNotConvert = new ArrayList<>();
317 LOG.info("creation of {} xpdr to roadm links", xpdrRdmLinkList.size() / 2);
318 // LOG.info("Link list = {}", xpdrRdmLinkList.toString());
319 for (var link:xpdrRdmLinkList) {
320 if (!linksToNotConvert.contains(link.getLinkId().getValue())) {
321 var oppositeLink = xpdrRdmLinkList.stream()
322 .filter(l -> l.getLinkId().equals(link.augmentation(Link1.class).getOppositeLink())).findAny()
324 AdminStates oppLnkAdmState = null;
325 State oppLnkOpState = null;
326 if (oppositeLink != null) {
327 oppLnkAdmState = oppositeLink.augmentation(Link1.class).getAdministrativeState();
328 oppLnkOpState = oppositeLink.augmentation(Link1.class).getOperationalState();
331 link.getSource().getSourceNode().getValue().contains("ROADM")
332 ? getIdBasedOnModelVersion(link.getSource().getSourceNode().getValue())
333 : link.getSource().getSourceNode().getValue();
335 link.getDestination().getDestNode().getValue().contains("ROADM")
336 ? getIdBasedOnModelVersion(link.getDestination().getDestNode().getValue())
337 : link.getDestination().getDestNode().getValue();
338 Link tapLink = this.tapiLink.createTapiLink(
339 sourceNode, link.getSource().getSourceTp().getValue(),
340 destNode, link.getDestination().getDestTp().getValue(),
341 TapiStringConstants.OMS_XPDR_RDM_LINK,
342 sourceNode.contains("ROADM") ? TapiStringConstants.PHTNC_MEDIA : TapiStringConstants.XPDR,
343 destNode.contains("ROADM") ? TapiStringConstants.PHTNC_MEDIA : TapiStringConstants.XPDR,
344 TapiStringConstants.PHTNC_MEDIA_OTS, TapiStringConstants.PHTNC_MEDIA_OTS,
346 link.augmentation(Link1.class).getAdministrativeState() == null || oppLnkAdmState == null
348 : this.tapiLink.setTapiAdminState(
349 link.augmentation(Link1.class).getAdministrativeState(), oppLnkAdmState).getName(),
351 link.augmentation(Link1.class).getOperationalState() == null || oppLnkOpState == null
353 : this.tapiLink.setTapiOperationalState(
354 link.augmentation(Link1.class).getOperationalState(), oppLnkOpState).getName(),
355 Set.of(LayerProtocolName.PHOTONICMEDIA), Set.of(LayerProtocolName.PHOTONICMEDIA.getName()),
357 linksToNotConvert.add(link.augmentation(Link1.class).getOppositeLink().getValue());
358 this.tapiLinks.put(tapLink.key(), tapLink);
363 private String getIdBasedOnModelVersion(String linknodeid) {
364 if (linknodeid.matches("[A-Z]{5}-[A-Z0-9]{2}-.*")) {
365 LOG.info("OpenROADM version > 1.2.1 {}", linknodeid);
366 return String.join("-", linknodeid.split("-")[0], linknodeid.split("-")[1]);
368 LOG.info("OpenROADM version <= 1.2.1 {}", linknodeid);
369 return linknodeid.split("-")[0];
373 public void setTapiNodes(Map<NodeKey,
374 org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node> nodeMap) {
375 this.tapiNodes.putAll(nodeMap);
378 public Map<NodeKey, org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node>
383 public Map<LinkKey, Link> getTapiLinks() {
387 public void setTapiSips(Map<ServiceInterfacePointKey, ServiceInterfacePoint> tapiSip) {
388 this.tapiSips.putAll(tapiSip);
391 public Map<ServiceInterfacePointKey, ServiceInterfacePoint> getTapiSips() {