Bug corrections in topo and portmapping modules
[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 java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Optional;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.TimeUnit;
17 import java.util.concurrent.TimeoutException;
18
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.transportpce.common.NetworkUtils;
23 import org.opendaylight.transportpce.common.Timeouts;
24 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
25 import org.opendaylight.transportpce.networkmodel.dto.NodeData;
26 import org.opendaylight.transportpce.networkmodel.dto.TopologyShard;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.NodeTypes;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes.AvailableWavelengths;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes.AvailableWavelengthsBuilder;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes.AvailableWavelengthsKey;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.Ports;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.PortsKey;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksKey;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.degree.ConnectionPorts;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Degree;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.DegreeKey;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Info;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroup;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroupKey;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1Builder;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.NetworkTypes1;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.NetworkTypes1Builder;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1Builder;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1Builder;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.network.types.OpenroadmTopologyBuilder;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.DegreeAttributesBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.SrgAttributesBuilder;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrClientAttributesBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrNetworkAttributesBuilder;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmLinkType;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmNodeType;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmTpType;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkBuilder;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkId;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkKey;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NodeId;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NetworkTypesBuilder;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.Node;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NodeBuilder;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NodeKey;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.node.SupportingNode;
68 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.node.SupportingNodeBuilder;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.node.SupportingNodeKey;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.LinkId;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Network1;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Network1Builder;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.TpId;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.Link;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.LinkBuilder;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.LinkKey;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.link.DestinationBuilder;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.link.SourceBuilder;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.node.TerminationPoint;
80 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.node.TerminationPointBuilder;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.node.TerminationPointKey;
82 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
83 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
86
87 public class OpenRoadmTopology {
88
89     private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmTopology.class);
90     private static final int DEFAULT_PORT_DIRECTION = -1;
91     private static final int MAX_DEGREE = 20;
92     private static final int MAX_SRG = 20;
93
94     private final DataBroker dataBroker;
95     private final DeviceTransactionManager deviceTransactionManager;
96
97     public OpenRoadmTopology(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager) {
98         this.dataBroker = dataBroker;
99         this.deviceTransactionManager = deviceTransactionManager;
100     }
101
102     /**
103      * This public method creates the OpenROADM Topology Layer and posts it to
104      * the controller.
105      */
106     public void createTopoLayer(DataBroker controllerdb) {
107         try {
108             Network openRoadmTopology = createOpenRoadmTopology();
109             InstanceIdentifierBuilder<Network> nwIID = InstanceIdentifier.builder(Network.class,
110                     new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)));
111             WriteTransaction wrtx = controllerdb.newWriteOnlyTransaction();
112             wrtx.put(LogicalDatastoreType.CONFIGURATION, nwIID.build(), openRoadmTopology);
113             wrtx.submit().get(1, TimeUnit.SECONDS);
114             LOG.info("OpenRoadm-Topology created successfully.");
115         } catch (ExecutionException | TimeoutException | InterruptedException e) {
116             LOG.warn("Failed to create OpenRoadm-Topology", e);
117         }
118     }
119
120     /**
121      * Create empty OpenROADM topology.
122      */
123     private Network createOpenRoadmTopology() {
124         NetworkBuilder nwBuilder = new NetworkBuilder();
125         NetworkId nwId = new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID);
126         nwBuilder.setNetworkId(nwId);
127         nwBuilder.setKey(new NetworkKey(nwId));
128         // set network type to Transport Underlay
129         NetworkTypes1Builder topoNetworkTypesBldr = new NetworkTypes1Builder();
130         topoNetworkTypesBldr.setOpenroadmTopology(new OpenroadmTopologyBuilder().build());
131         NetworkTypesBuilder nwTypeBuilder = new NetworkTypesBuilder();
132         nwTypeBuilder.addAugmentation(NetworkTypes1.class, topoNetworkTypesBldr.build());
133         nwBuilder.setNetworkTypes(nwTypeBuilder.build());
134         // Array to store nodes in the topolayer of a roadm/Xponder
135         Network1Builder nwBldr1 = new Network1Builder();
136         // adding expressLinks
137         nwBldr1.setLink(Collections.emptyList());
138         nwBuilder.addAugmentation(Network1.class, nwBldr1.build());
139         nwBuilder.setNode(Collections.emptyList());
140         return nwBuilder.build();
141     }
142
143     public TopologyShard createTopologyShard(String nodeId) {
144         int numOfDegrees;
145         int numOfSrgs;
146         int portDirectionEnum = DEFAULT_PORT_DIRECTION;
147
148         InstanceIdentifier<Info> infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class);
149         java.util.Optional<Info> deviceInfoOpt = this.deviceTransactionManager.getDataFromDevice(nodeId,
150                 LogicalDatastoreType.OPERATIONAL, infoIID, Timeouts.DEVICE_READ_TIMEOUT,
151                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
152         Info deviceInfo;
153         if (deviceInfoOpt.isPresent()) {
154             deviceInfo = deviceInfoOpt.get();
155         } else {
156             LOG.error("Unable to get device info for device {}!", nodeId);
157             return null;
158         }
159         List<Node> nodes = new ArrayList<>();
160
161         // Check if node is ROADM
162         if (NodeTypes.Rdm.equals(deviceInfo.getNodeType())) {
163
164             /*
165              * Adding Degree Node Get Degree Number -> x
166              * then get connection ports
167              * then find the port directions to decide whether TX/RX/TXRX
168              * Get value for max degree from info subtree, required for iteration
169              * if not present assume to be 20 (temporary)
170              */
171
172             Integer maxDegree;
173             if (deviceInfo.getMaxDegrees() != null) {
174                 maxDegree = deviceInfo.getMaxDegrees();
175             } else {
176                 maxDegree = MAX_DEGREE;
177             }
178
179             // Starting with degree Number = 1
180             Integer degreeCounter = 1;
181
182             while (degreeCounter <= maxDegree) {
183                 LOG.info("creating degree node {}/{}", degreeCounter, maxDegree);
184                 NodeData nodeData = createDegreeNode(nodeId, degreeCounter);
185                 if (nodeData != null) {
186                     NodeBuilder tempNode = nodeData.getNodeBuilder();
187                     portDirectionEnum = nodeData.getPortDirectionEnum();
188                     nodes.add(tempNode.build());
189                     degreeCounter++;
190                 } else {
191                     // null returned if Degree number= degreeCounter not present in the device
192                     break;
193                 }
194             }
195             numOfDegrees = degreeCounter - 1;
196
197             Integer maxSrg;
198             if (deviceInfo.getMaxSrgs() != null) {
199                 maxSrg = deviceInfo.getMaxSrgs();
200             } else {
201                 maxSrg = MAX_SRG;
202             }
203
204             // Starting with degree Number = 1
205             Integer srgCounter = 1;
206
207             while (srgCounter <= maxSrg) {
208                 LOG.info("creating SRG node {}/{}", srgCounter, maxSrg);
209                 NodeBuilder tempNode = createSrgNode(nodeId, srgCounter, portDirectionEnum);
210
211                 if (tempNode != null) {
212                     nodes.add(tempNode.build());
213                     srgCounter++;
214                 } else {
215                     // null returned if Degree number= degreeCounter not present in the device
216                     break;
217                 }
218             }
219             numOfSrgs = srgCounter - 1;
220
221             LOG.info("adding links numOfDegrees={} numOfSrgs={}", numOfDegrees, numOfSrgs);
222             List<Link> links = new ArrayList<>();
223             links.addAll(createExpressLinks(nodeId, numOfDegrees, portDirectionEnum));
224             links.addAll(createAddDropLinks(nodeId, numOfDegrees, numOfSrgs, portDirectionEnum));
225             LOG.info("created nodes/links: {}/{}", nodes.size(), links.size());
226             return new TopologyShard(nodes, links);
227         } else if (NodeTypes.Xpdr.equals(deviceInfo.getNodeType())) {
228             // Check if node is XPONDER
229             Integer clientport = getNoOfClientPorts(nodeId);
230             List<Link> links = new ArrayList<>();
231             Integer clientCounter = 1;
232             Integer lineCounter = 1;
233             while (clientCounter <= clientport) {
234                 NodeBuilder tempNode = createXpdr(clientCounter, lineCounter, nodeId);
235                 if (tempNode == null) {
236                     break;
237                 }
238                 nodes.add(tempNode.build());
239                 clientCounter++;
240                 lineCounter++;
241                 LOG.info("Entered this loop");
242             }
243             return new TopologyShard(nodes, links);
244         }
245
246         return null;
247     }
248
249     /**
250      * This private method gets the list of circuit packs on a xponder.
251      * For each circuit pack on a Xponder, it does a get on circuit-pack subtree with
252      * circuit-pack-name as key in order to get the list of ports.
253      * It then iterates over the list of ports to get ports with port-qual as
254      * xpdr-network/xpdr-client. The line and client ports are saved as:
255      *
256      * <p>
257      * 1. LINEn
258      *
259      * <p>
260      * 2. CLNTn
261      */
262     private int getNoOfClientPorts(String deviceId) {
263         // Creating for Xponder Line and Client Ports
264         InstanceIdentifier<OrgOpenroadmDevice> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class);
265         Optional<OrgOpenroadmDevice> deviceObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
266                 LogicalDatastoreType.OPERATIONAL, deviceIID, Timeouts.DEVICE_READ_TIMEOUT,
267                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
268
269         // Variable to keep track of number of client ports
270         int client = 1;
271         if (deviceObject.isPresent()) {
272             for (CircuitPacks cp : deviceObject.get().getCircuitPacks()) {
273                 if (cp.getPorts() != null) {
274                     for (Ports port : cp.getPorts()) {
275                         if (port.getPortQual() != null) {
276                             if (port.getPortQual().getIntValue() == 4) {
277                                 client++;
278                             }
279                         }
280                     }
281                 }
282             }
283         } else {
284             return 0;
285         }
286         return client;
287     }
288
289     private NodeBuilder createXpdr(Integer clientCounter, Integer lineCounter, String nodeId) {
290         // Create a generic Topo Layer node
291         NodeBuilder nodebldr = createTopoLayerNode(nodeId);
292         // Create augmentation node to inorder to add degree
293         Node1Builder node1bldr = new Node1Builder();
294         TerminationPoint1Builder tp1Bldr = new TerminationPoint1Builder();
295         TerminationPointBuilder tempTpBldr;
296
297         // set node type to Xponder
298         node1bldr.setNodeType(OpenroadmNodeType.XPONDER);
299         List<TerminationPoint> tpList = new ArrayList<>();
300         String nodeIdtopo = new StringBuilder().append(nodeId).append("-XPDR1").toString();
301         // Ad degree node specific augmentation
302         nodebldr.setNodeId(new NodeId(nodeIdtopo));
303         nodebldr.setKey(new NodeKey(new NodeId(nodeIdtopo)));
304         nodebldr.addAugmentation(Node1.class, node1bldr.build());
305         while (clientCounter != 0) {
306             // Create CLNT-TX termination
307             tempTpBldr = createTpBldr("XPDR1-CLIENT" + clientCounter);
308             tp1Bldr.setTpType(OpenroadmTpType.XPONDERCLIENT);
309             XpdrClientAttributesBuilder xpdrClntBldr = new XpdrClientAttributesBuilder();
310             xpdrClntBldr.setTailEquipmentId("XPDR1-NETWORK" + clientCounter);
311             tp1Bldr.setXpdrClientAttributes(xpdrClntBldr.build());
312             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
313             tpList.add(tempTpBldr.build());
314             clientCounter--;
315         }
316         while (lineCounter != 0) {
317             // Create LINE-TX termination
318             tempTpBldr = (createTpBldr("XPDR1-NETWORK" + lineCounter));
319             tp1Bldr.setTpType(OpenroadmTpType.XPONDERNETWORK);
320             XpdrNetworkAttributesBuilder xpdrNwAttrBldr = new XpdrNetworkAttributesBuilder();
321             xpdrNwAttrBldr.setTailEquipmentId("XPDR1-CLIENT" + lineCounter);
322             tp1Bldr.setXpdrNetworkAttributes(xpdrNwAttrBldr.build());
323             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
324             tpList.add(tempTpBldr.build());
325             lineCounter--;
326         }
327         LOG.info("printing tpList {}", tpList);
328         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder tpNode1 =
329             new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder();
330         tpNode1.setTerminationPoint(tpList);
331         nodebldr.addAugmentation(
332                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class,
333                 tpNode1.build());
334         LOG.info("The nodebldr {}", nodebldr);
335         return nodebldr;
336     }
337
338     private NodeData createDegreeNode(String nodeId, int degreeCounter) {
339         // Create augmentation node to inorder to add degree
340         Node1Builder node1bldr = new Node1Builder();
341         // set node type to degree
342         node1bldr.setNodeType(OpenroadmNodeType.DEGREE);
343
344         // Get connection ports on degree number = degreeCounter in order to get port
345         // direction
346         List<ConnectionPorts> degreeConPorts = getDegreePorts(nodeId, degreeCounter);
347         if ((degreeConPorts == null) || degreeConPorts.isEmpty()) {
348             return null;
349         }
350
351         DegreeAttributesBuilder degAttBldr = new DegreeAttributesBuilder();
352         degAttBldr.setDegreeNumber(degreeCounter);
353         degAttBldr.setAvailableWavelengths(create96AvalWaveDegree());
354         node1bldr.setDegreeAttributes(degAttBldr.build());
355
356         String nodeIdtopo = new StringBuilder(nodeId).append("-DEG").append(degreeCounter).toString();
357         // Create a generic Topo Layer node
358         NodeBuilder nodebldr = createTopoLayerNode(nodeId);
359         nodebldr.setNodeId(new NodeId(nodeIdtopo));
360         // Ad degree node specific augmentation
361         nodebldr.addAugmentation(Node1.class, node1bldr.build());
362         // Get Port direction
363         int portDirectionEnum = getPortDirection(nodeId, degreeConPorts.get(0).getCircuitPackName(),
364                 degreeConPorts.get(0).getPortName().toString());
365
366         /*
367          * if bi-directional then create 2 tp's :
368          *
369          * --> TTP-TXRX --> CTP-TXRX
370          *
371          * if uni-directional :
372          *
373          * --> TTP-TX --> TTP-RX --> CTP-TX --> CTP-RX
374          */
375         TerminationPoint1Builder tp1Bldr = new TerminationPoint1Builder();
376         TerminationPointBuilder tempTpBldr;
377
378         List<TerminationPoint> tpList = new ArrayList<>();
379         if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) {
380             // ports are uni Directional on a degree, therefore 4 termination points
381             // Create TTP-TX termination
382
383             tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-TX");
384             tp1Bldr.setTpType(OpenroadmTpType.DEGREETXTTP);
385             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
386             tpList.add(tempTpBldr.build());
387
388             // Create TTP-RX termination
389             tp1Bldr = new TerminationPoint1Builder();
390             tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-RX");
391             tp1Bldr.setTpType(OpenroadmTpType.DEGREERXTTP);
392
393             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
394             tpList.add(tempTpBldr.build());
395
396             // Create CTP-TX termination
397             tp1Bldr = new TerminationPoint1Builder();
398             tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-TX");
399             tp1Bldr.setTpType(OpenroadmTpType.DEGREETXCTP);
400             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
401             tpList.add(tempTpBldr.build());
402
403             // Create CTP-RX termination
404             tp1Bldr = new TerminationPoint1Builder();
405             tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-RX");
406             tp1Bldr.setTpType(OpenroadmTpType.DEGREERXCTP);
407             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
408             tpList.add(tempTpBldr.build());
409
410         } else if (portDirectionEnum == 3) {
411             // Ports are bi directional therefore 2 termination points
412             // Create TTP-TXRX termination
413             tp1Bldr = new TerminationPoint1Builder();
414             tempTpBldr = createTpBldr("DEG" + degreeCounter + "-TTP-TXRX");
415             tp1Bldr.setTpType(OpenroadmTpType.DEGREETXRXTTP);
416             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
417             tpList.add(tempTpBldr.build());
418
419             // Create CTP-TXRX termination
420             tp1Bldr = new TerminationPoint1Builder();
421             tempTpBldr = createTpBldr("DEG" + degreeCounter + "-CTP-TXRX");
422             tp1Bldr.setTpType(OpenroadmTpType.DEGREETXRXCTP);
423             tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
424             tpList.add(tempTpBldr.build());
425
426         }
427
428         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder tpNode1 =
429             new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder();
430
431         tpNode1.setTerminationPoint(tpList);
432
433         nodebldr.addAugmentation(
434                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class,
435                 tpNode1.build());
436         return new NodeData(nodebldr, portDirectionEnum);
437     }
438
439     private NodeBuilder createSrgNode(String nodeId, int srgCounter, int portDirectionEnum) {
440         // Create augmentation node to inorder to add degree
441         Node1Builder node1bldr = new Node1Builder();
442         // set node type to degree
443         node1bldr.setNodeType(OpenroadmNodeType.SRG);
444
445         node1bldr.setNodeType(OpenroadmNodeType.SRG);
446
447         SrgAttributesBuilder srgAttrBldr = new SrgAttributesBuilder();
448         srgAttrBldr.setAvailableWavelengths(create96AvalWaveSrg());
449         node1bldr.setSrgAttributes(srgAttrBldr.build());
450
451         // Create a generic Topo Layer node
452         NodeBuilder nodebldr = createTopoLayerNode(nodeId);
453         nodebldr.addAugmentation(Node1.class, node1bldr.build());
454
455         // Get connection ports on degree number = degreeCounter in order to get port
456         // direction
457         int maxPpPorts = getMaxPp(nodeId, srgCounter);
458         if (maxPpPorts == -1) {
459             return null;
460         }
461
462         String nodeIdtopo = new StringBuilder().append(nodeId).append("-SRG").append(srgCounter).toString();
463         nodebldr.setNodeId(new NodeId(nodeIdtopo));
464         List<TerminationPoint> tpList = new ArrayList<>();
465
466         TerminationPoint1Builder tp1Bldr;
467         TerminationPointBuilder tempTpBldr;
468
469         for (int i = 1; i <= maxPpPorts; i++) {
470             if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) {
471                 if (i >= (maxPpPorts / 2)) {
472                     break;
473                 }
474                 // ports are uni Directional on a degree, therefore 4 termination points
475                 // Create PP-TX termination
476                 tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-TX");
477                 tp1Bldr = new TerminationPoint1Builder();
478                 tp1Bldr.setTpType(OpenroadmTpType.SRGTXPP);
479                 tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
480                 tpList.add(tempTpBldr.build());
481
482                 // Create PP-RX termination
483                 tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-RX");
484                 tp1Bldr = new TerminationPoint1Builder();
485                 tp1Bldr.setTpType(OpenroadmTpType.SRGRXPP);
486                 tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
487                 tpList.add(tempTpBldr.build());
488
489             } else if (portDirectionEnum == 3) {
490                 // Ports are bi directional therefore 2 termination points
491                 // Create PP-TXRX termination
492                 tempTpBldr = createTpBldr("SRG" + srgCounter + "-PP" + i + "-TXRX");
493                 tp1Bldr = new TerminationPoint1Builder();
494                 tp1Bldr.setTpType(OpenroadmTpType.SRGTXRXPP);
495                 tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
496                 tpList.add(tempTpBldr.build());
497             }
498         }
499
500         switch (portDirectionEnum) {
501             case 1: // ports are uni Directional on a degree
502                 // Create CP-TX termination
503                 tempTpBldr = createTpBldr("SRG" + srgCounter + "-CP" + "-TX");
504                 tp1Bldr = new TerminationPoint1Builder();
505                 tp1Bldr.setTpType(OpenroadmTpType.SRGTXCP);
506                 tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
507                 tpList.add(tempTpBldr.build());
508                 break;
509             case 2:
510                 // Create CP-RX termination
511                 tempTpBldr = createTpBldr("SRG" + srgCounter + "-CP" + "-RX");
512                 tp1Bldr = new TerminationPoint1Builder();
513                 tp1Bldr.setTpType(OpenroadmTpType.SRGRXCP);
514                 tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
515                 tpList.add(tempTpBldr.build());
516                 break;
517             case 3:
518                 // Ports are bi directional therefore 2 termination points
519                 // Create CP-TXRX termination
520                 tempTpBldr = createTpBldr("SRG" + srgCounter + "-CP" + "-TXRX");
521                 tp1Bldr = new TerminationPoint1Builder();
522                 tp1Bldr.setTpType(OpenroadmTpType.SRGTXRXCP);
523                 tempTpBldr.addAugmentation(TerminationPoint1.class, tp1Bldr.build());
524                 tpList.add(tempTpBldr.build());
525                 break;
526             default:
527                 LOG.error("No correponsding direction to the value: {}", portDirectionEnum);
528                 break;
529         }
530
531         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder tpNode1 =
532             new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1Builder();
533
534         tpNode1.setTerminationPoint(tpList);
535
536         nodebldr.addAugmentation(
537                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class,
538                 tpNode1.build());
539
540         return nodebldr;
541     }
542
543     /*
544      * This method will return the TTP ports in the device for a given degree number to
545      * be used by the node to create TTP and CTP termination point on the device.
546      */
547     private List<ConnectionPorts> getDegreePorts(String deviceId, Integer degreeCounter) {
548         List<ConnectionPorts> degreeConPorts = new ArrayList<>();
549         LOG.info("Getting Connection ports for Degree Number {}", degreeCounter);
550         InstanceIdentifier<Degree> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Degree.class,
551                 new DegreeKey(degreeCounter));
552
553         Optional<Degree> ordmDegreeObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
554                 LogicalDatastoreType.CONFIGURATION, deviceIID, Timeouts.DEVICE_READ_TIMEOUT,
555                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
556
557         if (ordmDegreeObject.isPresent()) {
558             degreeConPorts.addAll(new ArrayList<>(ordmDegreeObject.get().getConnectionPorts()));
559         } else {
560             LOG.info("Device has {} degree", (degreeCounter - 1));
561             return Collections.emptyList();
562         }
563         return degreeConPorts;
564     }
565
566     private int getMaxPp(String deviceId, Integer srgCounter) {
567         int maxPpPorts;
568         LOG.info("Getting max pp ports for Srg Number {}", srgCounter);
569         InstanceIdentifier<SharedRiskGroup> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
570                 .child(SharedRiskGroup.class, new SharedRiskGroupKey(srgCounter));
571         Optional<SharedRiskGroup> ordmSrgObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
572                 LogicalDatastoreType.OPERATIONAL, deviceIID, Timeouts.DEVICE_READ_TIMEOUT,
573                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
574         if (ordmSrgObject.isPresent()) {
575             if (ordmSrgObject.get().getMaxAddDropPorts() != null) {
576                 maxPpPorts = ordmSrgObject.get().getMaxAddDropPorts();
577             } else {
578                 LOG.info("Max add drop ports absent");
579                 return -1;
580             }
581         } else {
582             LOG.info("SRG  absent");
583             return -1;
584         }
585         return maxPpPorts;
586     }
587
588     private NodeBuilder createTopoLayerNode(String nodeId) {
589         // Sets the value of Network-ref and Node-ref as a part of the supporting node
590         // attribute
591         SupportingNodeBuilder supportbldr = new SupportingNodeBuilder();
592         supportbldr.setKey(new SupportingNodeKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID), new NodeId(nodeId)));
593         supportbldr.setNetworkRef(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID));
594         supportbldr.setNodeRef(new NodeId(nodeId));
595         ArrayList<SupportingNode> supportlist = new ArrayList<>();
596         supportlist.add(supportbldr.build());
597         NodeBuilder nodebldr = new NodeBuilder();
598         nodebldr.setSupportingNode(supportlist);
599         return nodebldr;
600     }
601
602     // Return 0 for null/error values
603     // Return 1 for tx
604     // Return 2 for rx
605     // Return 3 for bi-directional
606
607     private int getPortDirection(String deviceId, String circuitPackName, String portName) {
608         InstanceIdentifier<Ports> portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
609                 .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName))
610                 .child(Ports.class, new PortsKey(portName));
611         LOG.info("Fetching Port Direction for port {} at circuit pack {}", portName, circuitPackName);
612         Optional<Ports> portObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
613                 LogicalDatastoreType.OPERATIONAL, portIID, Timeouts.DEVICE_READ_TIMEOUT,
614                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
615         if (portObject.isPresent()) {
616             Ports port = portObject.get();
617             if (port.getPortDirection() != null) {
618                 return port.getPortDirection().getIntValue();
619             } else {
620                 LOG.warn("Port direction value missing for {} {}", circuitPackName, port.getPortName());
621                 return 0;
622             }
623         }
624         return 0;
625     }
626
627     // This method returns a generic termination point builder for a given tpid
628     private TerminationPointBuilder createTpBldr(String tpId) {
629         TerminationPointBuilder tpBldr = new TerminationPointBuilder();
630         TpId tp = new TpId(tpId);
631         TerminationPointKey tpKey = new TerminationPointKey(tp);
632         tpBldr.setKey(tpKey);
633         tpBldr.setTpId(tp);
634         return tpBldr;
635     }
636
637     // This method returns the linkBuilder object for given source and destination.
638     public LinkBuilder createLink(String srcNode, String dstNode, String srcTp, String destTp) {
639         LOG.info("creating link for {}-{}", srcNode, dstNode);
640         // Create Destination for link
641         DestinationBuilder dstNodeBldr = new DestinationBuilder();
642         dstNodeBldr.setDestTp(destTp);
643         dstNodeBldr.setDestNode(new NodeId(dstNode));
644         // Create Source for the link
645         SourceBuilder srcNodeBldr = new SourceBuilder();
646         srcNodeBldr.setSourceNode(new NodeId(srcNode));
647         srcNodeBldr.setSourceTp(srcTp);
648         LinkBuilder lnkBldr = new LinkBuilder();
649         // set link builder attribute
650         lnkBldr.setDestination(dstNodeBldr.build());
651         lnkBldr.setSource(srcNodeBldr.build());
652         lnkBldr.setLinkId(LinkIdUtil.buildLinkId(srcNode, srcTp, dstNode, destTp));
653         lnkBldr.setKey(new LinkKey(lnkBldr.getLinkId()));
654         org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder lnk1Bldr =
655             new org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1Builder();
656         LinkId oppositeLinkId = LinkIdUtil.getOppositeLinkId(srcNode, srcTp, dstNode, destTp);
657         lnk1Bldr.setOppositeLink(oppositeLinkId);
658         lnkBldr.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.opposite.links.rev170929.Link1.class,
659                 lnk1Bldr.build());
660         return lnkBldr;
661     }
662
663     private List<Link> createExpressLinks(String nodeId, int numOfDegrees, int portDirectionEnum) {
664         LOG.info("creating express links {} {} {}", nodeId, numOfDegrees, portDirectionEnum);
665         List<Link> links = new ArrayList<>();
666
667         String srcNode;
668         String destNode;
669
670         String srcTp;
671         String destTp;
672
673         // ports are uni-directional
674         if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) {
675             LOG.info("creating uni-directional express links");
676             for (int i = 1; i <= numOfDegrees; i++) {
677                 for (int j = i + 1; j <= numOfDegrees; j++) {
678
679                     srcNode = nodeId + "-DEG" + i;
680                     destNode = nodeId + "-DEG" + j;
681
682                     // AtoZ direction
683                     srcTp = "DEG" + i + "-CTP-TX";
684                     destTp = "DEG" + j + "-CTP-RX";
685
686                     LinkBuilder expLinkBldr = createLink(srcNode, destNode, srcTp, destTp);
687
688                     Link1Builder lnk1Bldr = new Link1Builder();
689                     lnk1Bldr.setLinkType(OpenroadmLinkType.EXPRESSLINK);
690                     expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
691
692                     links.add(expLinkBldr.build());
693
694                     // ZtoA direction
695                     srcTp = "DEG" + i + "-CTP-RX";
696                     destTp = "DEG" + j + "-CTP-TX";
697
698                     expLinkBldr = createLink(destNode, srcNode, destTp, srcTp);
699                     expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
700
701                     links.add(expLinkBldr.build());
702
703                 }
704             }
705         }
706
707         // ports are bi-directional
708         if (portDirectionEnum == 3) {
709             LOG.info("creating bi-directional express links");
710             for (int i = 1; i <= numOfDegrees; i++) {
711                 for (int j = i + 1; j <= numOfDegrees; j++) {
712
713                     srcNode = nodeId + "-DEG" + i;
714                     destNode = nodeId + "-DEG" + j;
715
716                     // AtoZ direction
717                     srcTp = "DEG" + i + "-CTP-TXRX";
718                     destTp = "DEG" + j + "-CTP-TXRX";
719
720                     Link1Builder lnk1Bldr = new Link1Builder();
721                     lnk1Bldr.setLinkType(OpenroadmLinkType.EXPRESSLINK);
722
723                     LinkBuilder expLinkBldr = createLink(srcNode, destNode, srcTp, destTp);
724                     expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
725                     links.add(expLinkBldr.build());
726
727                     // ZtoA direction
728                     expLinkBldr = createLink(destNode, srcNode, destTp, srcTp);
729                     expLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
730                     links.add(expLinkBldr.build());
731                 }
732             }
733         }
734         return links;
735     }
736
737     private List<Link> createAddDropLinks(String nodeId, int numOfDegrees, int numOfSrgs, int portDirectionEnum) {
738         LOG.info("creating add-drop links {} {} {} {}", nodeId, numOfDegrees, numOfSrgs, portDirectionEnum);
739         List<Link> links = new ArrayList<>();
740
741         String srcNode;
742         String destNode;
743
744         String srcTp;
745         String destTp;
746
747         // ports are uni-directional
748         if ((portDirectionEnum == 1) || (portDirectionEnum == 2)) {
749             LOG.info("creating uni-directional add-drop links");
750             for (int i = 1; i <= numOfDegrees; i++) {
751                 for (int j = 1; j <= numOfSrgs; j++) {
752
753                     srcNode = nodeId + "-DEG" + i;
754                     destNode = nodeId + "-SRG" + j;
755
756                     // drop links
757                     srcTp = "DEG" + i + "-CTP-TX";
758                     destTp = "SRG" + j + "-CP-RX";
759
760                     LinkBuilder addDropLinkBldr = createLink(srcNode, destNode, srcTp, destTp);
761                     Link1Builder lnk1Bldr = new Link1Builder();
762                     lnk1Bldr.setLinkType(OpenroadmLinkType.DROPLINK);
763                     addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
764                     links.add(addDropLinkBldr.build());
765
766                     // add links direction
767                     srcTp = "DEG" + i + "-CTP-RX";
768                     destTp = "SRG" + j + "-CP-TX";
769
770                     addDropLinkBldr = createLink(destNode, srcNode, destTp, srcTp);
771                     lnk1Bldr.setLinkType(OpenroadmLinkType.ADDLINK);
772                     addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
773                     links.add(addDropLinkBldr.build());
774
775                 }
776             }
777         }
778         // ports are bi-directional
779         if (portDirectionEnum == 3) {
780             LOG.info("creating bi-directional add-drop links");
781             for (int i = 1; i <= numOfDegrees; i++) {
782                 for (int j = 1; j <= numOfSrgs; j++) {
783
784                     srcNode = nodeId + "-DEG" + i;
785                     destNode = nodeId + "-SRG" + j;
786
787                     // drop links
788                     srcTp = "DEG" + i + "-CTP-TXRX";
789                     destTp = "SRG" + j + "-CP-TXRX";
790
791                     LinkBuilder addDropLinkBldr = createLink(srcNode, destNode, srcTp, destTp);
792                     Link1Builder lnk1Bldr = new Link1Builder();
793                     lnk1Bldr.setLinkType(OpenroadmLinkType.DROPLINK);
794                     addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
795                     links.add(addDropLinkBldr.build());
796
797                     // add link
798                     addDropLinkBldr = createLink(destNode, srcNode, destTp, srcTp);
799                     lnk1Bldr.setLinkType(OpenroadmLinkType.ADDLINK);
800                     addDropLinkBldr.addAugmentation(Link1.class, lnk1Bldr.build());
801                     links.add(addDropLinkBldr.build());
802                 }
803             }
804         }
805         return links;
806     }
807
808     // This method returns the linkBuilder object for given source and destination.
809     public boolean deleteLink(String srcNode, String dstNode, String srcTp, String destTp) {
810         LOG.info("deleting link for {}-{}", srcNode, dstNode);
811         try {
812             InstanceIdentifierBuilder<Link> linkIID = InstanceIdentifier
813                     .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
814                     .augmentation(Network1.class)
815                     .child(Link.class, new LinkKey(LinkIdUtil.buildLinkId(srcNode, srcTp, dstNode, destTp)));
816             WriteTransaction wrtx = this.dataBroker.newWriteOnlyTransaction();
817             wrtx.delete(LogicalDatastoreType.CONFIGURATION, linkIID.build());
818             wrtx.submit().get(1, TimeUnit.SECONDS);
819         } catch (InterruptedException | ExecutionException | TimeoutException e) {
820             LOG.error(e.getMessage(), e);
821             return false;
822         }
823         return true;
824     }
825
826     private List<AvailableWavelengths> create96AvalWaveDegree() {
827         List<AvailableWavelengths> waveList = new ArrayList<>();
828
829         for (int i = 1; i < 97; i++) {
830             AvailableWavelengthsBuilder avalBldr = new AvailableWavelengthsBuilder();
831             avalBldr.setIndex((long) i);
832             avalBldr.setKey(new AvailableWavelengthsKey((long) i));
833             waveList.add(avalBldr.build());
834         }
835
836         return waveList;
837     }
838
839     private List<org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes.AvailableWavelengths>
840         create96AvalWaveSrg() {
841
842         List<org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes.AvailableWavelengths>
843             waveList = new ArrayList<>();
844
845         for (int i = 1; i < 97; i++) {
846             org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes
847                 .AvailableWavelengthsBuilder avalBldr =
848                 new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes
849                     .AvailableWavelengthsBuilder();
850             avalBldr.setIndex((long) i);
851             avalBldr.setKey(
852                 new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes
853                     .AvailableWavelengthsKey((long) i));
854             waveList.add(avalBldr.build());
855         }
856
857         return waveList;
858     }
859 }