Use version 13.1.0 of openroadm-network models
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / util / OpenRoadmTopology.java
1 /*
2  * Copyright © 2016 AT&T and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.transportpce.networkmodel.util;
10
11 import static org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.XpdrNodeTypes.Tpdr;
12
13 import java.util.ArrayList;
14 import java.util.Comparator;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.TimeoutException;
22 import java.util.stream.Collectors;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.transportpce.common.NetworkUtils;
25 import org.opendaylight.transportpce.common.fixedflex.GridUtils;
26 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
27 import org.opendaylight.transportpce.networkmodel.dto.TopologyShard;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.mapping.Mapping;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.Nodes;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Link1;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Link1Builder;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.Node1;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.Node1Builder;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.DegreeAttributes;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.DegreeAttributesBuilder;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.SrgAttributes;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.SrgAttributesBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmLinkType;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmNodeType;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmTpType;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeBuilder;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeKey;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNode;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNodeBuilder;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNodeKey;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkBuilder;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkKey;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.link.DestinationBuilder;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.link.SourceBuilder;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointBuilder;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
65 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
66 import org.opendaylight.yangtools.yang.common.Uint16;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
69
70 public final class OpenRoadmTopology {
71
72     private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmTopology.class);
73
74     private static Map<String, OpenroadmTpType> PORTQUAL_ORD_TYPE_MAP = Map.of(
75         "xpdr-network", OpenroadmTpType.XPONDERNETWORK,
76         "switch-network", OpenroadmTpType.XPONDERNETWORK,
77         "xpdr-client", OpenroadmTpType.XPONDERCLIENT
78     );
79     private static Map<String, List<OpenroadmTpType>> PORTDIR_ORD_TYPE_MAP = Map.of(
80         "bidirectional", List.of(OpenroadmTpType.DEGREETXRXTTP, OpenroadmTpType.SRGTXRXPP),
81         "tx", List.of(OpenroadmTpType.DEGREETXTTP, OpenroadmTpType.SRGTXPP),
82         "rx", List.of(OpenroadmTpType.DEGREERXTTP, OpenroadmTpType.SRGRXPP)
83     );
84
85     private OpenRoadmTopology() {
86     }
87
88     public static TopologyShard createTopologyShard(Nodes mappingNode) {
89         return createTopologyShard(mappingNode, true);
90     }
91
92     public static TopologyShard createTopologyShard(Nodes mappingNode, boolean firstMount) {
93         switch (mappingNode.getNodeInfo().getNodeType()) {
94             case Rdm :
95                 return createRdmTopologyShard(mappingNode, firstMount);
96             case Xpdr :
97                 return createXpdrTopologyShard(mappingNode);
98             default :
99                 LOG.error("Device node Type not managed yet");
100                 return null;
101         }
102     }
103
104     public static TopologyShard createRdmTopologyShard(Nodes mappingNode, boolean firstMount) {
105         List<Node> nodes = new ArrayList<>();
106         LOG.info("creating rdm node in openroadmtopology for node {}",
107                 mappingNode.getNodeId());
108         // transform flat mapping list to per degree and per srg mapping lists
109         Map<String, List<Mapping>> mapDeg = new HashMap<>();
110         Map<String, List<Mapping>> mapSrg = new HashMap<>();
111         List<Mapping> mappingList = new ArrayList<>(mappingNode.nonnullMapping().values());
112         mappingList.sort(Comparator.comparing(Mapping::getLogicalConnectionPoint));
113         List<String> nodeShardList = new ArrayList<>();
114         for (Mapping mapping : mappingList) {
115             String str = mapping.getLogicalConnectionPoint().split("-")[0];
116             if (!nodeShardList.contains(str)) {
117                 nodeShardList.add(str);
118             }
119         }
120         for (String str : nodeShardList) {
121             List<Mapping> interList =
122                     mappingList.stream()
123                             .filter(x -> x.getLogicalConnectionPoint().split("-")[0].equals(str))
124                             .collect(Collectors.toList());
125             if (str.contains("DEG")) {
126                 mapDeg.put(str, interList);
127             } else if (str.contains("SRG")) {
128                 mapSrg.put(str, interList);
129             } else {
130                 LOG.error("unknow element");
131             }
132         }
133         // create degree nodes
134         for (Map.Entry<String, List<Mapping>> entry : mapDeg.entrySet()) {
135             nodes.add(
136                 createDegree(entry.getKey(), entry.getValue(), mappingNode.getNodeId(),
137                         mappingNode.getNodeInfo().getNodeClli(), firstMount)
138                     .build());
139         }
140         // create srg nodes
141         for (Map.Entry<String, List<Mapping>> entry : mapSrg.entrySet()) {
142             nodes.add(
143                 createSrg(entry.getKey(), entry.getValue(), mappingNode.getNodeId(),
144                         mappingNode.getNodeInfo().getNodeClli(), firstMount)
145                     .build());
146         }
147         LOG.info("adding links numOfDegrees={} numOfSrgs={}", mapDeg.size(), mapSrg.size());
148         List<Link> links = createNewLinks(nodes);
149         LOG.info("created nodes/links: {}/{}", nodes.size(), links.size());
150         return new TopologyShard(nodes, links);
151     }
152
153     public static TopologyShard createXpdrTopologyShard(Nodes mappingNode) {
154         List<Node> nodes = new ArrayList<>();
155         List<Mapping> networkMappings =
156                 mappingNode.nonnullMapping().values()
157                         .stream().filter(k -> k.getLogicalConnectionPoint().contains("NETWORK"))
158                         .collect(Collectors.toList());
159         List<Integer> tpdrList = new ArrayList<>();
160         for (Mapping mapping : networkMappings) {
161             Integer xpdrNb = Integer.parseInt(mapping.getLogicalConnectionPoint().split("XPDR")[1].split("-")[0]);
162             if (!tpdrList.contains(xpdrNb)) {
163                 tpdrList.add(xpdrNb);
164                 List<Mapping> extractedMappings = mappingNode.nonnullMapping().values()
165                         .stream().filter(lcp -> lcp.getLogicalConnectionPoint().contains("XPDR" + xpdrNb))
166                         .collect(Collectors.toList());
167                 Boolean isOtn;
168                 String xpdrType;
169                 switch (mapping.getXpdrType() == null ? Tpdr : mapping.getXpdrType()) {
170                     case Tpdr :
171                         isOtn = false;
172                         xpdrType = "Tpdr";
173                         break;
174                     case Mpdr :
175                     case Switch :
176                         isOtn = true;
177                         xpdrType = mapping.getXpdrType().getName();
178                         break;
179                     // Both regen and regen-uni are added here, though initial support is
180                     // only for regen xpdr-type
181                     case Regen:
182                     case RegenUni:
183                         isOtn = false;
184                         xpdrType = mapping.getXpdrType().getName();
185                         break;
186                     default :
187                         LOG.warn("cannot create xpdr node {} in openroadm-topology: type {} not supported",
188                              mappingNode.getNodeId() + "-XPDR" + xpdrNb, mapping.getXpdrType().getName());
189                         continue;
190                 }
191                 LOG.info("creating xpdr node {} of type {} in openroadm-topology",
192                         mappingNode.getNodeId() + "-XPDR" + xpdrNb, xpdrType);
193                 nodes.add(createXpdr(
194                                 mappingNode.getNodeId(),
195                                 mappingNode.getNodeInfo().getNodeClli(),
196                                 xpdrNb,
197                                 extractedMappings,
198                                 isOtn)
199                           .build());
200             }
201         }
202         return nodes.isEmpty() ? null : new TopologyShard(nodes, new ArrayList<Link>());
203     }
204
205     private static NodeBuilder createXpdr(String nodeId, String clli, Integer xpdrNb, List<Mapping> mappings,
206                                           boolean isOtn) {
207         // Create ietf node setting supporting-node data
208         String nodeIdtopo = new StringBuilder().append(nodeId).append("-XPDR").append(xpdrNb).toString();
209         NodeBuilder ietfNodeBldr = createTopoLayerNode(nodeId, clli)
210                 .setNodeId(new NodeId(nodeIdtopo))
211                 .withKey((new NodeKey(new NodeId(nodeIdtopo))))
212                 .addAugmentation(
213                     // Create openroadm-network-topo augmentation to set node type to Xponder
214                     new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1Builder()
215                         .setNodeType(OpenroadmNodeType.XPONDER)
216                         .setAdministrativeState(AdminStates.InService)
217                         .setOperationalState(State.InService)
218                         .build());
219         // Create tp-map
220         Map<TerminationPointKey, TerminationPoint> tpMap = new HashMap<>();
221         for (Mapping m : mappings) {
222             if (!PORTQUAL_ORD_TYPE_MAP.containsKey(m.getPortQual())) {
223                 continue;
224             }
225             if (isOtn && m.getPortQual().equals("xpdr-client")) {
226                 continue;
227             }
228             var ocnTp1Bldr = new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
229                     .TerminationPoint1Builder()
230                 .setTpType(PORTQUAL_ORD_TYPE_MAP.get(m.getPortQual()))
231                 .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
232                 .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()));
233             if (!isOtn && m.getConnectionMapLcp() != null) {
234                 ocnTp1Bldr.setAssociatedConnectionMapTp(Set.of(new TpId(m.getConnectionMapLcp())));
235             }
236             TerminationPointBuilder ietfTpBldr = createTpBldr(m.getLogicalConnectionPoint())
237                 .addAugmentation(
238                     // Add openroadm-network-topology tp augmentations
239                         ocnTp1Bldr.build());
240             TerminationPoint ietfTp = ietfTpBldr.build();
241             tpMap.put(ietfTp.key(),ietfTp);
242         }
243         // Create ietf node augmentation to support ietf tp-list
244         return ietfNodeBldr.addAugmentation(
245             new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1Builder()
246                     .setTerminationPoint(tpMap)
247                     .build());
248     }
249
250     private static NodeBuilder createDegree(String degNb, List<Mapping> degListMap, String nodeId, String clli,
251                                             boolean firstMount) {
252         // Create tp-list
253         Map<TerminationPointKey,TerminationPoint> tpMap = new HashMap<>();
254         for (Mapping m : degListMap) {
255             // Add openroadm-common-network tp type augmentations
256             // Added states to degree port. TODO: add to mapping relation between abstracted and physical node states
257             if (!PORTDIR_ORD_TYPE_MAP.containsKey(m.getPortDirection())) {
258                 LOG.error("impossible to set tp-type to {}", m.getLogicalConnectionPoint());
259             }
260             TerminationPoint ietfTp =  createTpBldr(m.getLogicalConnectionPoint())
261                 .addAugmentation(
262                     new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
263                             .TerminationPoint1Builder()
264                         .setTpType(PORTDIR_ORD_TYPE_MAP.get(m.getPortDirection()).get(0))
265                         .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
266                         .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()))
267                         .build())
268                 .build();
269             tpMap.put(ietfTp.key(),ietfTp);
270         }
271         // Add CTP to tp-list + added states. TODO: same comment as before with the relation between states
272         TerminationPoint ietfTp = createTpBldr(degNb + "-CTP-TXRX")
273                 .addAugmentation(new org.opendaylight.yang.gen.v1.http
274                     .org.openroadm.common.network.rev230526.TerminationPoint1Builder()
275                          .setTpType(OpenroadmTpType.DEGREETXRXCTP)
276                          .setAdministrativeState(AdminStates.InService)
277                          .setOperationalState(State.InService)
278                          .build())
279                  .build();
280         tpMap.put(ietfTp.key(),ietfTp);
281         // set degree-attributes
282         DegreeAttributesBuilder degAttBldr = new DegreeAttributesBuilder()
283                 .setDegreeNumber(Uint16.valueOf(degNb.split("DEG")[1]));
284         if (firstMount) {
285             degAttBldr.setAvailFreqMaps(GridUtils.initFreqMaps4FixedGrid2Available());
286         }
287         DegreeAttributes degAtt = degAttBldr.build();
288         // set node-id
289         String nodeIdtopo = new StringBuilder().append(nodeId).append("-").append(degNb).toString();
290         // Create ietf node setting supporting-node data
291         return createTopoLayerNode(nodeId, clli)
292                 .setNodeId(new NodeId(nodeIdtopo))
293                 .withKey((new NodeKey(new NodeId(nodeIdtopo))))
294                 .addAugmentation(new Node1Builder().setDegreeAttributes(degAtt).build())
295                 .addAugmentation(
296                     new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
297                             .Node1Builder()
298                         .setNodeType(OpenroadmNodeType.DEGREE)
299                         .setAdministrativeState(AdminStates.InService)
300                         .setOperationalState(State.InService)
301                         .build())
302                 .addAugmentation(
303                     new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
304                             .Node1Builder()
305                         .setTerminationPoint(tpMap)
306                         .build());
307     }
308
309     private static NodeBuilder createSrg(String srgNb, List<Mapping> srgListMap, String nodeId, String clli,
310                                          boolean firstMount) {
311         // Create tp-list
312         Map<TerminationPointKey,TerminationPoint> tpMap = new HashMap<>();
313         for (Mapping m : srgListMap) {
314             // Added states to srg port. TODO: add to mapping relation between abstracted and physical node states
315             if (!PORTDIR_ORD_TYPE_MAP.containsKey(m.getPortDirection())) {
316                 LOG.error("impossible to set tp-type to {}", m.getLogicalConnectionPoint());
317             }
318             TerminationPoint ietfTp = createTpBldr(m.getLogicalConnectionPoint())
319                 .addAugmentation(
320                     // Add openroadm-common-network tp type augmentations
321                     new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
322                             .TerminationPoint1Builder()
323                         .setTpType(PORTDIR_ORD_TYPE_MAP.get(m.getPortDirection()).get(1))
324                         .setAdministrativeState(TopologyUtils.setNetworkAdminState(m.getPortAdminState()))
325                         .setOperationalState(TopologyUtils.setNetworkOperState(m.getPortOperState()))
326                         .build())
327                 .build();
328             tpMap.put(ietfTp.key(),ietfTp);
329         }
330         // Add CP to tp-list + added states. TODO: same comment as before with the relation between states
331         TerminationPoint ietfTp = createTpBldr(srgNb + "-CP-TXRX")
332             .addAugmentation(
333                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
334                         .TerminationPoint1Builder()
335                     .setTpType(OpenroadmTpType.SRGTXRXCP)
336                     .setAdministrativeState(AdminStates.InService)
337                     .setOperationalState(State.InService)
338                     .build())
339             .build();
340         tpMap.put(ietfTp.key(),ietfTp);
341         // set srg-attributes
342         SrgAttributesBuilder srgAttrBldr = new SrgAttributesBuilder();
343         if (firstMount) {
344             srgAttrBldr.setAvailFreqMaps(GridUtils.initFreqMaps4FixedGrid2Available());
345         }
346         SrgAttributes srgAttr = srgAttrBldr.build();
347         // Create ietf node augmentation to support ietf tp-list
348         // Create ietf node setting supporting-node data
349         String nodeIdtopo = new StringBuilder().append(nodeId).append("-").append(srgNb).toString();
350         return createTopoLayerNode(nodeId, clli)
351             .setNodeId(new NodeId(nodeIdtopo))
352             .withKey((new NodeKey(new NodeId(nodeIdtopo))))
353             .addAugmentation(new Node1Builder().setSrgAttributes(srgAttr).build())
354             .addAugmentation(
355                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
356                         .Node1Builder()
357                     .setNodeType(OpenroadmNodeType.SRG)
358                     .setAdministrativeState(AdminStates.InService)
359                     .setOperationalState(State.InService)
360                     .build())
361             .addAugmentation(
362                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
363                        .Node1Builder()
364                     .setTerminationPoint(tpMap)
365                     .build());
366     }
367
368     private static NodeBuilder createTopoLayerNode(String nodeId, String clli) {
369         // Sets the value of Network-ref and Node-ref as a part of the supporting node
370         // attribute
371         SupportingNode support1 = new SupportingNodeBuilder()
372                 .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID), new NodeId(nodeId)))
373                 .setNetworkRef(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))
374                 .setNodeRef(new NodeId(nodeId))
375                 .build();
376         SupportingNode support2 = new SupportingNodeBuilder()
377                 .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID), new NodeId(clli)))
378                 .setNetworkRef(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))
379                 .setNodeRef(new NodeId(clli))
380                 .build();
381         Map<SupportingNodeKey, SupportingNode> supportlist = new HashMap<>();
382         supportlist.put(support1.key(), support1);
383         supportlist.put(support2.key(), support2);
384         return new NodeBuilder().setSupportingNode(supportlist);
385     }
386
387
388     // This method returns a generic termination point builder for a given tpid
389     private static TerminationPointBuilder createTpBldr(String tpId) {
390         TpId tp = new TpId(tpId);
391         return new TerminationPointBuilder().withKey(new TerminationPointKey(tp)).setTpId(tp);
392     }
393
394     private static LinkBuilder createLink(String srcNode, String destNode, String srcTp, String destTp) {
395         LinkId linkId = LinkIdUtil.buildLinkId(srcNode, srcTp, destNode, destTp);
396         return new LinkBuilder()
397                 .setSource(
398                     new SourceBuilder()
399                         .setSourceNode(new NodeId(srcNode))
400                         .setSourceTp(new TpId(srcTp))
401                         .build())
402                 .setDestination(
403                     new DestinationBuilder()
404                         .setDestNode(new NodeId(destNode))
405                         .setDestTp(new TpId(destTp))
406                         .build())
407                 .setLinkId(linkId)
408                 .withKey(new LinkKey(linkId));
409     }
410
411     private static List<Link> createNewLinks(List<Node> nodes) {
412         List<Link> links = new ArrayList<>();
413         String srcNode;
414         String destNode;
415         String srcTp;
416         String destTp;
417         for (int i = 0; i < nodes.size() - 1; i++) {
418             for (int j = i + 1; j < nodes.size(); j++) {
419                 srcNode = nodes.get(i).getNodeId().getValue();
420                 destNode = nodes.get(j).getNodeId().getValue();
421                 // A to Z direction
422                 srcTp = nodes.get(i)
423                         .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
424                                 .ietf.network.topology.rev180226.Node1.class)
425                         .nonnullTerminationPoint().values().stream()
426                         .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
427                         .findFirst().orElseThrow().getTpId().getValue();
428                 destTp = nodes.get(j)
429                         .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
430                                 .ietf.network.topology.rev180226.Node1.class)
431                         .nonnullTerminationPoint().values().stream()
432                         .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
433                         .findFirst().orElseThrow().getTpId().getValue();
434                 Link1Builder ocnAzLinkBldr = new Link1Builder();
435                 Link1Builder ocnZaLinkBldr = new Link1Builder();
436                 int srcNodeType = nodes.get(i).augmentation(org.opendaylight.yang.gen.v1.http
437                         .org.openroadm.common.network.rev230526.Node1.class).getNodeType().getIntValue();
438                 int destNodeType = nodes.get(j).augmentation(org.opendaylight.yang.gen.v1.http
439                         .org.openroadm.common.network.rev230526.Node1.class).getNodeType().getIntValue();
440
441                 if (srcNodeType == 11 && destNodeType == 11) {
442                     ocnAzLinkBldr.setLinkType(OpenroadmLinkType.EXPRESSLINK);
443                     ocnZaLinkBldr.setLinkType(OpenroadmLinkType.EXPRESSLINK);
444                 } else if (srcNodeType == 11 && destNodeType == 12) {
445                     ocnAzLinkBldr.setLinkType(OpenroadmLinkType.DROPLINK);
446                     ocnZaLinkBldr.setLinkType(OpenroadmLinkType.ADDLINK);
447                 } else if (srcNodeType == 12 && destNodeType == 11) {
448                     ocnAzLinkBldr.setLinkType(OpenroadmLinkType.ADDLINK);
449                     ocnZaLinkBldr.setLinkType(OpenroadmLinkType.DROPLINK);
450                 } else {
451                     continue;
452                 }
453
454                 // Add state to link. Based on the operational state of the TPs at the edge of the link.
455                 // Similar to getting srcTp and destTp
456                 State srcTpState = nodes.get(i)
457                         .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
458                             .ietf.network.topology.rev180226.Node1.class)
459                         .getTerminationPoint().values().stream()
460                         .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
461                         .findFirst().orElseThrow()
462                         .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
463                             .TerminationPoint1.class)
464                         .getOperationalState();
465                 State destTpState = nodes.get(j)
466                         .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
467                             .ietf.network.topology.rev180226.Node1.class)
468                         .getTerminationPoint().values().stream()
469                         .filter(tp -> tp.getTpId().getValue().contains("CP") || tp.getTpId().getValue().contains("CTP"))
470                         .findFirst().orElseThrow()
471                         .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
472                             .TerminationPoint1.class)
473                         .getOperationalState();
474                 if (State.InService.equals(srcTpState) && State.InService.equals(destTpState)) {
475                     ocnAzLinkBldr.setAdministrativeState(AdminStates.InService)
476                             .setOperationalState(State.InService);
477                     ocnZaLinkBldr.setAdministrativeState(AdminStates.InService)
478                             .setOperationalState(State.InService);
479                 } else {
480                     ocnAzLinkBldr.setAdministrativeState(AdminStates.OutOfService)
481                             .setOperationalState(State.OutOfService);
482                     ocnZaLinkBldr.setAdministrativeState(AdminStates.OutOfService)
483                             .setOperationalState(State.OutOfService);
484                 }
485                 // set opposite link augmentations
486                 LinkBuilder ietfAzLinkBldr = createLink(srcNode, destNode, srcTp, destTp);
487                 LinkBuilder ietfZaLinkBldr = createLink(destNode, srcNode, destTp, srcTp);
488                 ocnAzLinkBldr.setOppositeLink(ietfZaLinkBldr.getLinkId());
489                 ietfAzLinkBldr.addAugmentation(ocnAzLinkBldr.build());
490                 ocnZaLinkBldr.setOppositeLink(ietfAzLinkBldr.getLinkId());
491                 ietfZaLinkBldr.addAugmentation(ocnZaLinkBldr.build());
492                 links.add(ietfAzLinkBldr.build());
493                 links.add(ietfZaLinkBldr.build());
494             }
495         }
496         return links;
497     }
498
499     // This method returns the linkBuilder object for given source and destination
500     public static boolean deleteLink(String srcNode, String dstNode, String srcTp, String destTp,
501                                      NetworkTransactionService networkTransactionService) {
502         LOG.info("deleting link for {}-{}", srcNode, dstNode);
503         LinkId linkId = LinkIdUtil.buildLinkId(srcNode, srcTp, dstNode, destTp);
504         if (deleteLinkLinkId(linkId, networkTransactionService)) {
505             LOG.debug("Link Id {} updated to have admin state down", linkId);
506             return true;
507         } else {
508             LOG.debug("Link Id not found for Source {} and Dest {}", srcNode, dstNode);
509             return false;
510         }
511     }
512
513     // This method returns the linkBuilder object for given source and destination
514     public static boolean deleteLinkLinkId(LinkId linkId , NetworkTransactionService networkTransactionService) {
515         LOG.info("deleting link for LinkId: {}", linkId.getValue());
516         try {
517             InstanceIdentifier.Builder<Link> linkIID = InstanceIdentifier.builder(Networks.class)
518                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
519                 .augmentation(Network1.class)
520                 .child(Link.class, new LinkKey(linkId));
521             java.util.Optional<Link> link =
522                     networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,linkIID.build()).get();
523             if (link.isEmpty()) {
524                 LOG.error("No link found for given LinkId: {}", linkId);
525                 return false;
526             }
527             LinkBuilder linkBuilder = new LinkBuilder(link.orElseThrow());
528             networkTransactionService.merge(
529                 LogicalDatastoreType.CONFIGURATION,
530                 linkIID.build(),
531                 linkBuilder
532                     .removeAugmentation(Link1.class)
533                     .addAugmentation(
534                         new org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526
535                             .Link1Builder(linkBuilder
536                                 .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526
537                                     .Link1.class))
538                                 .build())
539                     .build());
540             networkTransactionService.commit().get(1, TimeUnit.SECONDS);
541             return true;
542
543         } catch (InterruptedException | ExecutionException | TimeoutException e) {
544             LOG.error("Error deleting link {}", linkId.getValue(), e);
545             return false;
546         }
547     }
548
549     /**
550      * Get a builder for instance identifier related to common network termination point.
551      * @param nodeId String
552      * @param tpId String
553      * @return InstanceIdentifierBuilder
554      */
555     public static InstanceIdentifier.Builder<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
556             .TerminationPoint1> createCommonNetworkTerminationPointIIDBuilder(String nodeId, String tpId) {
557         return InstanceIdentifier.builder(Networks.class)
558                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
559                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
560                         .networks.network.Node.class,
561                     new NodeKey(new NodeId(nodeId)))
562                 .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
563                     .Node1.class)
564                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
565                         .networks.network.node.TerminationPoint.class,
566                     new TerminationPointKey(new TpId(tpId)))
567                 .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
568                         .TerminationPoint1.class);
569     }
570
571     /**
572      * Get an instance identifier related to network node.
573      * @param nodeId String
574      * @return InstanceIdentifier
575      */
576     public static InstanceIdentifier<Node1> createNetworkNodeIID(String nodeId) {
577         return InstanceIdentifier.builder(Networks.class)
578                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
579                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
580                         .networks.network.Node.class,
581                      new NodeKey(new NodeId(nodeId)))
582                 .augmentation(Node1.class).build();
583     }
584
585     /**
586      * Get an instance identifier related to common network node.
587      * @param nodeId String
588      * @return InstanceIdentifier
589      */
590     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526
591             .Node1> createCommonNetworkNodeIID(String nodeId) {
592         return InstanceIdentifier.builder(Networks.class)
593                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
594                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
595                         .networks.network.Node.class,
596                     new NodeKey(new NodeId(nodeId)))
597                 .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class)
598                 .build();
599     }
600 }