Bug correction in LogicalConnectionPoint naming
[transportpce.git] / renderer / src / main / java / org / opendaylight / transportpce / renderer / mapping / PortMapping.java
1 /*
2  * Copyright © 2017 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.renderer.mapping;
10
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.TimeUnit;
18 import java.util.concurrent.TimeoutException;
19
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.MountPoint;
22 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
23 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
27 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaces;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.NodeTypes;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.Ports;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.PortsKey;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksKey;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.degree.ConnectionPorts;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Degree;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.DegreeKey;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Info;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroup;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroupKey;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.port.Interfaces;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.InterfaceType;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpenROADMOpticalMultiplex;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpticalTransport;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.Network;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.NetworkBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.Nodes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.MappingBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.MappingKey;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 public class PortMapping {
66
67     private static final Logger LOG = LoggerFactory.getLogger(PortMapping.class);
68     private final DataBroker db;
69     private final MountPointService mps;
70     private final String nodeId;
71
72     public PortMapping(DataBroker db, MountPointService mps, String nodeId) {
73         this.db = db;
74         this.mps = mps;
75         this.nodeId = nodeId;
76
77     }
78
79     /**
80      * This method creates logical to physical port mapping for a given device.
81      * Instead of parsing all the circuit packs/ports in the device this methods
82      * does a selective read operation on degree/srg subtree to get circuit
83      * packs/ports that map to :
84      *
85      * <p>
86      * 1. DEGn-TTP-TX, DEGn-TTP-RX, DEGn-TTP-TXRX
87      *
88      * <p>
89      * 2. SRGn-PPp-TX, SRGn-PPp-RX, SRGn-PPp-TXRX
90      *
91      * <p>
92      * 3. LINEn
93      *
94      * <p>
95      * 4. CLNTn.
96      *
97      * <p>
98      * If the port is Mw it also store the OMS, OTS interface provisioned on the
99      * port. It skips the logical ports that are internal. If operation is
100      * successful the mapping gets stored in datastore corresponding to
101      * portmapping.yang data model.
102      *
103      * @return true/false based on status of operation
104      */
105     public boolean createMappingData() {
106
107         LOG.info("Create Mapping Data for node " + nodeId);
108         DataBroker deviceDb = getDeviceDataBroker(nodeId, mps);
109         List<Mapping> portMapList = new ArrayList<>();
110         Info deviceInfo;
111         Integer nodeType = 1;
112         if (deviceDb != null) {
113             deviceInfo = getDeviceInfo(deviceDb);
114             if (deviceInfo != null) {
115                 if (deviceInfo.getNodeType() == null) {
116                     LOG.info("Node type mandatory field is missing");
117                     return false;
118                 }
119                 nodeType = deviceInfo.getNodeType().getIntValue();
120                 // Create Mapping for Roadm Node
121                 if (nodeType == 1) {
122                     // Get TTP port mapping
123                     if (!createTtpPortMapping(deviceDb, deviceInfo, portMapList)) {
124                         // return false if mapping creation for TTP's failed
125                         LOG.info("Unable to create mapping for TTP's");
126                         return false;
127                     }
128
129                     // Get PP port mapping
130                     if (!createPpPortMapping(deviceDb, deviceInfo, portMapList)) {
131                         // return false if mapping creation for PP's failed
132                         LOG.info("Unable tp create mapping for PP's");
133                         return false;
134                     }
135                 }
136                 // Create Mapping for Xponder Node
137                 if (nodeType == 2) {
138                     if (!createXpdrPortMapping(deviceDb, deviceInfo, portMapList)) {
139                         LOG.info("Unable to create mapping for Xponder");
140                         return false;
141                     }
142                 }
143             } else {
144                 LOG.info("Device info subtree is absent for " + nodeId);
145                 return false;
146             }
147
148         } else {
149             LOG.info("Unable to get Data broker for node " + nodeId);
150             return false;
151         }
152         return postPortMapping(deviceInfo, portMapList, nodeType);
153     }
154
155     /**
156      * This method removes mapping data from the datastore after disconnecting
157      * ODL from a Netconf device.
158      */
159     public void deleteMappingData() {
160         LOG.info("Deleting Mapping Data corresponding at node " + nodeId);
161         WriteTransaction rw = db.newWriteOnlyTransaction();
162         InstanceIdentifier<Nodes> nodesIID = InstanceIdentifier.create(Network.class)
163             .child(Nodes.class, new NodesKey(nodeId));
164         rw.delete(LogicalDatastoreType.CONFIGURATION, nodesIID);
165         try {
166             rw.submit().get(1, TimeUnit.SECONDS);
167             LOG.info("Port mapping removal for node " + nodeId);
168         } catch (InterruptedException | ExecutionException | TimeoutException e) {
169             LOG.error("Error for removing port mapping infos for node " + nodeId);
170         }
171     }
172
173     /**
174      * This private method gets the list of external ports on a degree. For each
175      * port in the degree, it does a get on port subtree with
176      * circuit-pack-name/port-name as key in order to get the logical connection
177      * point name corresponding to it.
178      *
179      * @param deviceDb
180      *            Reference to device's databroker
181      * @param deviceInfo
182      *            Info subtree read from the device
183      * @param portMapList
184      *            Reference to the list containing the mapping to be pushed to
185      *            MD-SAL
186      *
187      * @return true/false based on status of operation
188      */
189     private boolean createTtpPortMapping(DataBroker deviceDb, Info deviceInfo, List<Mapping> portMapList) {
190         // Creating mapping data for degree TTP's
191         List<ConnectionPorts> degreeConPorts = getDegreePorts(deviceDb, deviceInfo);
192
193         // Getting circuit-pack-name/port-name corresponding to TTP's
194         for (ConnectionPorts cp : degreeConPorts) {
195             String circuitPackName = cp.getCircuitPackName();
196             String portName = cp.getPortName().toString();
197             InstanceIdentifier<Ports> portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
198                 CircuitPacks.class, new CircuitPacksKey(circuitPackName)).child(Ports.class, new PortsKey(portName));
199             try {
200                 LOG.info("Fetching logical Connection Point value for port {} at circuit pack {}", portName,
201                     circuitPackName);
202                 ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
203                 Optional<Ports> portObject = rtx.read(LogicalDatastoreType.OPERATIONAL, portIID).get();
204                 if (portObject.isPresent()) {
205                     Ports port = portObject.get();
206                     if (port.getLogicalConnectionPoint() != null) {
207                         LOG.info("Logical Connection Point for {} {} is {}", circuitPackName, portName, port
208                             .getLogicalConnectionPoint());
209                         portMapList.add(createMappingObject(port, circuitPackName, port.getLogicalConnectionPoint(),
210                             deviceDb));
211                     } else {
212
213                         LOG.warn("Logical Connection Point value missing for {} {}", circuitPackName, port
214                             .getPortName());
215                     }
216                 }
217             } catch (InterruptedException | ExecutionException ex) {
218                 LOG.warn("Read failed for Logical Connection Point value missing for " + circuitPackName + " "
219                     + portName, ex);
220                 return false;
221             }
222         }
223         return true;
224     }
225
226     /**
227      * This private method gets the list of circuit packs on an Srg. For each
228      * circuit pack on an Srg, it does a get on circuit-pack subtree with
229      * circuit-pack-name as key in order to get the list of ports. It then
230      * iterates over the list of ports to get ports with port-qual as
231      * roadm-external. It appends a TX,RX,TXRX to the logical connection point
232      * name based on the direction of the port.
233      *
234      * @param deviceDb
235      *            Reference to device's databroker
236      * @param deviceInfo
237      *            Info subtree read from the device
238      * @param portMapList
239      *            Reference to the list containing the mapping to be pushed to
240      *            MD-SAL
241      *
242      * @return true/false based on status of operation
243      */
244
245     private boolean createPpPortMapping(DataBroker deviceDb, Info deviceInfo, List<Mapping> portMapList) {
246         // Creating mapping data for degree PP's
247
248         ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
249         Integer maxSrg;
250         // Get value for max Srg from subtree, required for iteration
251         // if it is not defined in the netconf node then set maxSrg to 20
252         if (deviceInfo.getMaxSrgs() != null) {
253             maxSrg = deviceInfo.getMaxSrgs();
254         } else {
255             maxSrg = 20;
256         }
257
258         Integer srgCounter = 1;
259         Integer nbSrg = 0;
260         while (srgCounter <= maxSrg) {
261             List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg.CircuitPacks> srgCps =
262                 new ArrayList<>();
263             LOG.info("Getting CircuitPacks for Srg Number {}", srgCounter);
264             InstanceIdentifier<SharedRiskGroup> srgIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
265                 SharedRiskGroup.class, new SharedRiskGroupKey(srgCounter));
266             try {
267                 Optional<SharedRiskGroup> ordmSrgObject = rtx.read(LogicalDatastoreType.CONFIGURATION, srgIID).get();
268
269                 if (ordmSrgObject.isPresent()) {
270                     srgCps.addAll(new ArrayList<>(ordmSrgObject.get().getCircuitPacks()));
271                     nbSrg++;
272                 }
273             } catch (InterruptedException | ExecutionException ex) {
274                 LOG.warn("Failed to read Srg {}", srgCounter, ex);
275                 break;
276             }
277
278             for (org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg.CircuitPacks cps : srgCps) {
279                 String circuitPackName = cps.getCircuitPackName();
280                 try {
281                     InstanceIdentifier<CircuitPacks> cpIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
282                         CircuitPacks.class, new CircuitPacksKey(circuitPackName));
283                     Optional<CircuitPacks> circuitPackObject = rtx.read(LogicalDatastoreType.OPERATIONAL, cpIID).get();
284
285                     if (circuitPackObject.isPresent()) {
286                         CircuitPacks cp = circuitPackObject.get();
287                         if (cp.getPorts() == null) {
288                             LOG.warn("No port found for {} {}", deviceInfo.getNodeId(), circuitPackName);
289                         } else if (!cp.getPorts().isEmpty()) {
290                             for (Ports port : cp.getPorts()) {
291
292                                 if (port.getLogicalConnectionPoint() != null && port.getPortQual().getIntValue() == 2) {
293                                     String logicalConnectionPoint = null;
294                                     if (port.getPortDirection().getIntValue() == 1) {
295                                         // Port direction is transmit
296                                         if (!port.getLogicalConnectionPoint().contains("SRG")) {
297                                             logicalConnectionPoint = "SRG" + srgCounter + "-" + port
298                                                 .getLogicalConnectionPoint() + "-TX";
299                                         } else {
300                                             logicalConnectionPoint = port.getLogicalConnectionPoint() + "-TX";
301                                         }
302                                     }
303                                     if (port.getPortDirection().getIntValue() == 2) {
304                                         // Port direction is receive
305                                         if (!port.getLogicalConnectionPoint().contains("SRG")) {
306                                             logicalConnectionPoint = "SRG" + srgCounter + "-" + port
307                                                 .getLogicalConnectionPoint() + "-RX";
308                                         } else {
309                                             logicalConnectionPoint = port.getLogicalConnectionPoint() + "-RX";
310                                         }
311                                     }
312                                     if (port.getPortDirection().getIntValue() == 3) {
313                                         // port is bi-directional
314                                         if (!port.getLogicalConnectionPoint().contains("SRG")) {
315                                             logicalConnectionPoint = "SRG" + srgCounter + "-" + port
316                                                 .getLogicalConnectionPoint() + "-TXRX";
317                                         } else {
318                                             logicalConnectionPoint = port.getLogicalConnectionPoint() + "-TXRX";
319                                         }
320                                     }
321
322                                     LOG.info("Logical Connection Point for {} {} is {}", circuitPackName, port
323                                         .getPortName(), logicalConnectionPoint);
324
325                                     portMapList.add(createMappingObject(port, circuitPackName, logicalConnectionPoint,
326                                         deviceDb));
327
328                                 } else if (port.getPortQual().getIntValue() == 1) {
329
330                                     LOG.info("Port is internal, skipping Logical Connection Point missing for "
331                                         + circuitPackName + " " + port.getPortName());
332
333                                 } else if (port.getLogicalConnectionPoint() == null) {
334
335                                     LOG.info("Value missing, Skipping Logical Connection Point missing for {} {}",
336                                         circuitPackName, port.getPortName());
337                                 }
338
339                             }
340
341                         }
342
343                     }
344                 } catch (InterruptedException | ExecutionException ex) {
345                     LOG.warn("Read failed for {}", circuitPackName, ex);
346                     return false;
347                 }
348             }
349             srgCounter++;
350         }
351         LOG.info("Device has {} Srg", nbSrg);
352         return true;
353     }
354
355     /**
356      * This private method gets the list of circuit packs on a xponder. For each
357      * circuit pack on a Xponder, it does a get on circuit-pack subtree with
358      * circuit-pack-name as key in order to get the list of ports. It then
359      * iterates over the list of ports to get ports with port-qual as
360      * xpdr-network/xpdr-client. The line and client ports are saved as:
361      *
362      * <p>
363      * 1. LINEn
364      *
365      * <p>
366      * 2. CLNTn
367      *
368      * @param deviceDb
369      *            Reference to device's databroker
370      * @param deviceInfo
371      *            Info subtree read from the device
372      * @param portMapList
373      *            Reference to the list containing the mapping to be pushed to
374      *            MD-SAL
375      *
376      * @return true/false based on status of operation
377      */
378
379     private boolean createXpdrPortMapping(DataBroker deviceDb, Info deviceInfo, List<Mapping> portMapList) {
380         // Creating for Xponder Line and Client Ports
381         try {
382             InstanceIdentifier<OrgOpenroadmDevice> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class);
383             ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
384             Optional<OrgOpenroadmDevice> deviceObject = rtx.read(LogicalDatastoreType.OPERATIONAL, deviceIID).get();
385
386             // Variable to keep track of number of line ports
387             int line = 1;
388             // Variable to keep track of number of client ports
389             int client = 1;
390             if (deviceObject.isPresent()) {
391                 for (CircuitPacks cp : deviceObject.get().getCircuitPacks()) {
392                     String circuitPackName = cp.getCircuitPackName();
393                     if (cp.getPorts() == null) {
394                         LOG.warn("No port found for {}, circuit pack {}", deviceInfo.getNodeId(), circuitPackName);
395                     } else {
396                         for (Ports port : cp.getPorts()) {
397                             if (port.getPortQual() != null) {
398                                 if (port.getPortQual().getIntValue() == 3) {
399                                     // Port is xpdr-network
400                                     portMapList.add(createMappingObject(port, circuitPackName, "XPDR-LINE"
401                                         + line, deviceDb));
402                                     LOG.info("Logical Connection Point for {} {} is XPDR-LINE{}", circuitPackName, port
403                                         .getPortName(), line);
404                                     line++;
405                                 }
406                                 if (port.getPortQual().getIntValue() == 4) {
407                                     // port is xpdr-client
408                                     portMapList.add(createMappingObject(port, circuitPackName, "XPDR-CLNT"
409                                         + client, deviceDb));
410                                     LOG.info("Logical Connection Point for {} {} is XPDR-CLNT{}", circuitPackName, port
411                                         .getPortName(), client);
412                                     client++;
413                                 }
414                             } else {
415                                 LOG.info("no PortQual for port {} of circuit pack {}", port.getPortName(), cp
416                                     .getCircuitPackName());
417                             }
418                         }
419                     }
420                 }
421             } else {
422                 LOG.info("No deviceObject present for {}", nodeId);
423                 return false;
424             }
425
426         } catch (InterruptedException | ExecutionException ex) {
427             LOG.warn("Read failed for CircuitPacks of {}", nodeId, ex);
428             return false;
429         }
430         return true;
431     }
432
433     /**
434      * This private method builds the mapping object to be pushed in MD-SAL in
435      * order to save port mapping. In case of TTP ports, it also saves the
436      * OTS,OMS interfaces provisioned on the port.
437      *
438      * @param port
439      *            Reference to device's port subtree object.
440      * @param circuitPackName
441      *            Name of cp where port exists.
442      * @param logicalConnectionPoint
443      *            logical name of the port.
444      * @param deviceDb
445      *            Reference to device's databroker.
446      *
447      * @return true/false based on status of operation
448      */
449
450     private Mapping createMappingObject(Ports port, String circuitPackName, String logicalConnectionPoint,
451         DataBroker deviceDb) {
452         MappingBuilder mpBldr = new MappingBuilder();
453         mpBldr.setKey(new MappingKey(logicalConnectionPoint)).setLogicalConnectionPoint(logicalConnectionPoint)
454             .setSupportingCircuitPackName(circuitPackName).setSupportingPort(port.getPortName());
455
456         // Get OMS and OTS interface provisioned on the TTP's
457         if (logicalConnectionPoint.contains("TTP") && port.getInterfaces() != null) {
458             for (Interfaces interfaces : port.getInterfaces()) {
459                 Class<? extends InterfaceType> interfaceType = new OpenRoadmInterfaces(db, mps, nodeId,
460                     logicalConnectionPoint).getInterface(interfaces.getInterfaceName()).getType();
461                 // Check if interface type is OMS or OTS
462                 if (interfaceType.equals(OpenROADMOpticalMultiplex.class)) {
463                     String omsInterfaceName = interfaces.getInterfaceName();
464                     mpBldr.setSupportingOms(omsInterfaceName);
465                 }
466                 if (interfaceType.equals(OpticalTransport.class)) {
467                     String otsInterfaceName = interfaces.getInterfaceName();
468                     mpBldr.setSupportingOts(otsInterfaceName);
469                 }
470             }
471         }
472         return mpBldr.build();
473     }
474
475     /**
476      * This method does a get operation on info subtree of the netconf device's
477      * configuration datastore and returns info object.It is required to get
478      * device attributes such as maxDegrees,maxSrgs and node-type.
479      *
480      * @param deviceDb
481      *            Reference to device's databroker
482      * @return Info object
483      *
484      */
485     private Info getDeviceInfo(DataBroker deviceDb) {
486         ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
487         InstanceIdentifier<Info> infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class);
488         try {
489             Optional<Info> ordmInfoObject = rtx.read(LogicalDatastoreType.OPERATIONAL, infoIID).get();
490             if (ordmInfoObject.isPresent()) {
491                 LOG.info("Info subtree is present {}", ordmInfoObject.get());
492                 return ordmInfoObject.get();
493             } else {
494                 LOG.error("Info subtree is not present");
495             }
496         } catch (NullPointerException ex) {
497             LOG.warn("Try to get Info from a non Open ROADM device {}", deviceDb);
498             return null;
499         } catch (InterruptedException | ExecutionException ex) {
500             LOG.error("Read failed on info subtree ", ex);
501             return null;
502         }
503         return null;
504     }
505
506     /**
507      * This method does a get operation on degree subtree of the netconf
508      * device's config datastore and returns a list of all connection port
509      * objects. It is required for doing a selective get on ports that
510      * correspond to logical connection points of interest.
511      *
512      * @param deviceDb
513      *            Reference to device's databroker
514      * @param ordmInfo
515      *            Info subtree from the device
516      * @return List of connection ports object belonging to- degree subtree
517      */
518     private List<ConnectionPorts> getDegreePorts(DataBroker deviceDb, Info ordmInfo) {
519
520         List<ConnectionPorts> degreeConPorts = new ArrayList<>();
521         ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
522         Integer maxDegree;
523
524         // Get value for max degree from info subtree, required for iteration
525         // if not present assume to be 20 (temporary)
526         if (ordmInfo.getMaxDegrees() != null) {
527             maxDegree = ordmInfo.getMaxDegrees();
528         } else {
529             maxDegree = 20;
530         }
531         Integer degreeCounter = 1;
532         while (degreeCounter <= maxDegree) {
533             LOG.info("Getting Connection ports for Degree Number " + degreeCounter);
534             InstanceIdentifier<Degree> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
535                 Degree.class, new DegreeKey(degreeCounter));
536             try {
537                 Optional<Degree> ordmDegreeObject = rtx.read(LogicalDatastoreType.CONFIGURATION, deviceIID).get();
538
539                 if (ordmDegreeObject.isPresent()) {
540                     degreeConPorts.addAll(new ArrayList<>(ordmDegreeObject.get().getConnectionPorts()));
541
542                 } else {
543                     LOG.info("Device has " + (degreeCounter - 1) + " degree");
544                     break;
545                 }
546             } catch (InterruptedException | ExecutionException ex) {
547                 LOG.error("Failed to read degree " + degreeCounter, ex);
548                 break;
549
550             }
551             degreeCounter++;
552         }
553         return degreeConPorts;
554     }
555
556     /**
557      * This method for ports the portMapping corresponding to the
558      * portmapping.yang file to the MD-SAL datastore.
559      *
560      * <p>
561      * 1. Supporting circuit pack 2. Supporting port 3. Supporting OMS interface
562      * (if port on ROADM)
563      *
564      * @param deviceInfo
565      *            Info subtree from the device.
566      * @param portMapList
567      *            Reference to the list containing the mapping to be pushed to
568      *            MD-SAL.
569      *
570      * @return Result true/false based on status of operation.
571      */
572     private boolean postPortMapping(Info deviceInfo, List<Mapping> portMapList, Integer nodeType) {
573
574         NodesBuilder nodesBldr = new NodesBuilder();
575         nodesBldr.setKey(new NodesKey(deviceInfo.getNodeId())).setNodeId(deviceInfo.getNodeId());
576         nodesBldr.setNodeType(NodeTypes.forValue(nodeType));
577         nodesBldr.setMapping(portMapList);
578         List<Nodes> nodesList = new ArrayList<>();
579         nodesList.add(nodesBldr.build());
580         NetworkBuilder nwBldr = new NetworkBuilder();
581         nwBldr.setNodes(nodesList);
582         final WriteTransaction writeTransaction = db.newWriteOnlyTransaction();
583         InstanceIdentifier<Network> nodesIID = InstanceIdentifier.builder(Network.class).build();
584         writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodesIID, nwBldr.build());
585         CheckedFuture<Void, TransactionCommitFailedException> submit = writeTransaction.submit();
586         try {
587             submit.checkedGet();
588             return true;
589
590         } catch (TransactionCommitFailedException e) {
591             LOG.warn("Failed to post {} ", nwBldr.build(), e);
592             return false;
593
594         }
595     }
596
597     /**
598      * This method for a given node's termination point returns the Mapping
599      * object based on portmapping.yang model stored in the MD-SAL data store
600      * which is created when the node is connected for the first time. The
601      * mapping object basically contains the following attributes of interest:
602      *
603      * <p>
604      * 1. Supporting circuit pack
605      *
606      * <p>
607      * 2. Supporting port
608      *
609      * <p>
610      * 3. Supporting OMS interface (if port on ROADM) 4. Supporting OTS
611      * interface (if port on ROADM)
612      *
613      * @param nodeId
614      *            Unique Identifier for the node of interest.
615      * @param logicalConnPoint
616      *            Name of the logical point
617      * @param db
618      *            Databroker / MD-SAL data store
619      *
620      * @return Result Mapping object if success otherwise null.
621      */
622     public static Mapping getMapping(String nodeId, String logicalConnPoint, DataBroker db) {
623
624         /*
625          * Getting physical mapping corresponding to logical connection point
626          */
627         InstanceIdentifier<Mapping> portMapping = InstanceIdentifier.builder(Network.class).child(Nodes.class,
628             new NodesKey(nodeId)).child(Mapping.class, new MappingKey(logicalConnPoint)).build();
629         ReadOnlyTransaction readTx = db.newReadOnlyTransaction();
630         Optional<Mapping> mapObject;
631         try {
632             mapObject = readTx.read(LogicalDatastoreType.CONFIGURATION, portMapping).get();
633             if (mapObject.isPresent()) {
634                 LOG.info("Found mapping for the logical port " + mapObject.get().toString());
635                 return mapObject.get();
636             } else {
637                 LOG.info("Could not find mapping for logical connection point : " + logicalConnPoint + " for nodeId "
638                     + nodeId);
639                 return null;
640             }
641         } catch (InterruptedException | ExecutionException ex) {
642             LOG.error("Unable to read mapping for logical connection point : " + logicalConnPoint + " for nodeId "
643                 + nodeId, ex);
644         }
645         return null;
646     }
647
648     /**
649      * This static method returns the DataBroker for a netconf node.
650      *
651      * @param nodeId
652      *            Unique identifier for the mounted netconf- node
653      * @param mps
654      *            Reference to mount service
655      * @return Databroker for the given device
656      */
657     public static DataBroker getDeviceDataBroker(String nodeId, MountPointService mps) {
658         MountPoint netconfNode = getDeviceMountPoint(nodeId, mps);
659         if (netconfNode != null) {
660             DataBroker netconfNodeDataBroker = netconfNode.getService(DataBroker.class).get();
661             return netconfNodeDataBroker;
662         } else {
663             LOG.error("Device Data broker not found for :" + nodeId);
664             return null;
665         }
666     }
667
668     public static MountPoint getDeviceMountPoint(String nodeId, MountPointService mps) {
669         InstanceIdentifier<Node> netconfNodeIID = InstanceIdentifier.builder(NetworkTopology.class).child(
670             Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))).child(Node.class,
671                 new NodeKey(new NodeId(nodeId))).build();
672
673         // Get mount point for specified device
674         final Optional<MountPoint> netconfNodeOptional = mps.getMountPoint(netconfNodeIID);
675         if (netconfNodeOptional.isPresent()) {
676             MountPoint netconfNode = netconfNodeOptional.get();
677             return netconfNode;
678         } else {
679             LOG.error("Mount Point not found for :" + nodeId);
680             return null;
681         }
682
683     }
684 }