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