c8fc2a1acbe3db4531f28054c7bf237d99639469
[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
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.yang.gen.v1.http.org.openroadm.device.rev161014.circuit.pack.Ports;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.circuit.pack.PortsKey;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.circuit.packs.CircuitPacks;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.circuit.packs.CircuitPacksKey;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.degree.ConnectionPorts;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.org.openroadm.device.container.OrgOpenroadmDevice;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.org.openroadm.device.container.org.openroadm.device.Degree;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.org.openroadm.device.container.org.openroadm.device.DegreeKey;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.org.openroadm.device.container.org.openroadm.device.Info;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.org.openroadm.device.container.org.openroadm.device.SharedRiskGroup;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.org.openroadm.device.container.org.openroadm.device.SharedRiskGroupKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.Network;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.NetworkBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.Nodes;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.MappingBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.MappingKey;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 public class PortMapping {
57
58     private static final Logger LOG = LoggerFactory.getLogger(PortMapping.class);
59     private final DataBroker db;
60     private final MountPointService mps;
61
62     private final String nodeId;
63
64     public PortMapping(DataBroker db, MountPointService mps, String nodeId) {
65         this.db = db;
66         this.mps = mps;
67         this.nodeId = nodeId;
68
69     }
70
71     /**
72     * This method creates logical to physical port mapping
73     * for a given device.
74     * Instead of parsing all the circuit packs/ports in the device
75     * this methods does a selective read operation on degree/srg
76     * subtree to get circuit packs/ports that map to :
77     *   DEGn-TTP-TX
78     *   DEGn-TTP-RX
79     *   DEGn-TTP-TXRX
80     *   SRGn-PPp
81     * This methods skips the logical ports that are internal.
82     * if operation is successful the mapping gets stored in
83     * datastore corresponding to portmapping.yang data model.
84     *
85     * @return true/false based on status of operation
86     */
87     public boolean createMappingData() {
88
89         LOG.info(" Create Mapping Data for node " + nodeId);
90
91         DataBroker deviceDb = getDeviceDataBroker(nodeId, mps);
92         Info deviceInfo = getDeviceInfo(deviceDb);
93
94         InstanceIdentifier<Network> nodesIID = InstanceIdentifier.builder(Network.class).build();
95
96         NetworkBuilder nwBldr = new NetworkBuilder();
97         List<Mapping> portMapList = new ArrayList<>();
98         List<Nodes> nodesList = new ArrayList<>();
99
100         if (deviceDb != null && deviceInfo != null) {
101
102             // Creating mapping data for degree TTP's
103             List<ConnectionPorts> degreeConPorts = getDegreePorts(deviceDb, deviceInfo);
104
105             //Getting circuit-pack-name/port-name corresponding to TTP's
106             for (ConnectionPorts cp : degreeConPorts) {
107
108                 InstanceIdentifier<Ports> portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
109                     CircuitPacks.class, new CircuitPacksKey(cp.getCircuitPackName())).child(Ports.class, new PortsKey(cp
110                         .getPortName().toString()));
111                 try {
112                     LOG.info("Fetching logical Connection Point value for port " + cp.getPortName().toString()
113                         + " at circuit pack " + cp.getCircuitPackName());
114                     ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
115                     Optional<Ports> portObject = rtx.read(LogicalDatastoreType.OPERATIONAL, portIID).get();
116
117                     if (portObject.isPresent()) {
118                         Ports port = portObject.get();
119                         if (port.getLogicalConnectionPoint() != null) {
120
121                             LOG.info("Logical Connection Point for " + cp.getCircuitPackName() + " " + port
122                                 .getPortName() + " is " + port.getLogicalConnectionPoint());
123                             MappingBuilder mpBldr = new MappingBuilder();
124                             mpBldr.setKey(new MappingKey(port.getLogicalConnectionPoint())).setLogicalConnectionPoint(
125                                 port.getLogicalConnectionPoint()).setSupportingCircuitPackName(cp.getCircuitPackName())
126                                 .setSupportingPort(port.getPortName());
127                             portMapList.add(mpBldr.build());
128
129                         } else {
130
131                             LOG.warn("Logical Connection Point value missing for " + cp.getCircuitPackName() + " "
132                                 + port.getPortName());
133                         }
134                     }
135                 } catch (InterruptedException | ExecutionException ex) {
136                     LOG.warn("Read failed for Logical Connection Point value missing for " + cp.getCircuitPackName()
137                         + " " + cp.getPortName());
138                 }
139             }
140             // Creating mapping data for degree PP's
141             List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.srg.CircuitPacks> srgCps = getSrgCps(
142                 deviceDb, deviceInfo);
143
144             for (org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.srg.CircuitPacks cps : srgCps) {
145                 InstanceIdentifier<CircuitPacks> cpIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
146                     CircuitPacks.class, new CircuitPacksKey(cps.getCircuitPackName()));
147                 try {
148
149                     ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
150                     Optional<CircuitPacks> circuitPackObject = rtx.read(LogicalDatastoreType.OPERATIONAL, cpIID).get();
151
152                     if (circuitPackObject.isPresent()) {
153                         CircuitPacks circuitPack = circuitPackObject.get();
154                         if (!circuitPack.getPorts().isEmpty()) {
155                             for (Ports port : circuitPack.getPorts()) {
156
157                                 if (port.getLogicalConnectionPoint() != null && port.getPortQual().getIntValue() == 2) {
158
159                                     LOG.info("Logical Connection Point for " + circuitPack.getCircuitPackName() + " "
160                                         + port.getPortName() + " is " + port.getLogicalConnectionPoint());
161                                     MappingBuilder mpBldr = new MappingBuilder();
162                                     mpBldr.setKey(new MappingKey(port.getLogicalConnectionPoint()))
163                                         .setLogicalConnectionPoint(port.getLogicalConnectionPoint())
164                                         .setSupportingCircuitPackName(circuitPack.getCircuitPackName())
165                                         .setSupportingPort(port.getPortName());
166                                     portMapList.add(mpBldr.build());
167
168                                 } else if (port.getPortQual().getIntValue() == 1) {
169
170                                     LOG.info("Port is internal, skipping Logical Connection Point missing for "
171                                         + circuitPack.getCircuitPackName() + " " + port.getPortName());
172
173                                 } else if (port.getLogicalConnectionPoint() == null) {
174
175                                     LOG.info("Value missing, Skipping Logical Connection Point missing for "
176                                         + circuitPack.getCircuitPackName() + " " + port.getPortName());
177                                 }
178
179                             }
180
181                         }
182
183                     }
184                 } catch (InterruptedException | ExecutionException ex) {
185                     LOG.warn("Read failed for " + cps.getCircuitPackName());
186                 }
187
188             }
189
190             NodesBuilder nodesBldr = new NodesBuilder();
191             nodesBldr.setKey(new NodesKey(deviceInfo.getNodeId())).setNodeId(deviceInfo.getNodeId());
192             nodesBldr.setMapping(portMapList);
193             nodesList.add(nodesBldr.build());
194             nwBldr.setNodes(nodesList);
195             final WriteTransaction writeTransaction = db.newWriteOnlyTransaction();
196             writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodesIID, nwBldr.build());
197             CheckedFuture<Void, TransactionCommitFailedException> submit = writeTransaction.submit();
198             try {
199                 submit.checkedGet();
200                 return true;
201
202             } catch (TransactionCommitFailedException e) {
203                 LOG.warn("Failed to post {} ", nwBldr.build(), e);
204                 return false;
205
206             }
207         } else {
208             LOG.info(" Unable to get Data broker for node " + nodeId);
209             return false;
210         }
211
212     }
213
214     /**
215      * This method does a get operation on info subtree
216      * of the netconf device's config datastore and returns
217      * info object.It is required to get device attributes such
218      * as maxDegrees,maxSrgs.
219      *
220      * @param deviceDb Reference to device's databroker
221      * @return Info object
222      *
223      */
224     public Info getDeviceInfo(DataBroker deviceDb) {
225         ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
226         InstanceIdentifier<Info> infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class);
227         try {
228             Optional<Info> ordmInfoObject = rtx.read(LogicalDatastoreType.CONFIGURATION, infoIID).get();
229             if (ordmInfoObject.isPresent()) {
230                 return ordmInfoObject.get();
231             } else {
232                 LOG.info("Info subtree is not present");
233             }
234         } catch (InterruptedException | ExecutionException ex) {
235             LOG.info("Read failed on info subtree for");
236             return null;
237         }
238         return null;
239     }
240
241     /**
242      * This method does a get operation on degree subtree
243      * of the netconf device's config datastore and returns a list
244      * of all connection port objects.
245      * It is required for doing a selective get on ports that
246      * correspond to logical connection points of interest.
247      *
248      * @param deviceDb Reference to device's databroker
249      * @param ordmInfo Info subtree from the device
250      * @return List of connection ports object belonging to-
251      *         degree subtree
252      */
253     public List<ConnectionPorts> getDegreePorts(DataBroker deviceDb, Info ordmInfo) {
254
255         List<ConnectionPorts> degreeConPorts = new ArrayList<>();
256         ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
257         Integer maxDegree;
258
259         //Get value for max degree from info subtree, required for iteration
260         //if not present assume to be 20 (temporary)
261         if (ordmInfo.getMaxDegrees() != null) {
262             maxDegree = ordmInfo.getMaxDegrees();
263         } else {
264             maxDegree = 20;
265         }
266         Integer degreeCounter = 1;
267         while (degreeCounter <= maxDegree) {
268             LOG.info("Getting Connection ports for Degree Number " + degreeCounter);
269             InstanceIdentifier<Degree> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
270                 Degree.class, new DegreeKey(degreeCounter));
271             try {
272                 Optional<Degree> ordmDegreeObject = rtx.read(LogicalDatastoreType.CONFIGURATION, deviceIID).get();
273
274                 if (ordmDegreeObject.isPresent()) {
275                     degreeConPorts.addAll(new ArrayList<ConnectionPorts>(ordmDegreeObject.get().getConnectionPorts()));
276
277                 } else {
278                     LOG.info("Device has " + (degreeCounter - 1) + " degree");
279                     break;
280                 }
281             } catch (InterruptedException | ExecutionException ex) {
282                 LOG.info("Failed to read degree " + degreeCounter);
283                 break;
284
285             }
286             degreeCounter++;
287         }
288         return degreeConPorts;
289     }
290
291     /**
292      * This method does a get operation on shared risk group subtree
293      * of the netconf device's config datastore and returns a list
294      * of all circuit packs objects that are part of srgs.
295      * It is required to do a selective get on all the circuit packs
296      * that contain add/drop ports of interest.
297      *
298      * @param deviceDb Reference to device's databroker
299      * @param ordmInfo Info subtree from the device
300      * @return List of circuit packs object belonging to-
301      *         shared risk group subtree
302      */
303
304     public List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.srg.CircuitPacks> getSrgCps(
305         DataBroker deviceDb, Info ordmInfo) {
306
307         List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.srg.CircuitPacks> srgCps =
308             new ArrayList<>();
309         ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
310         Integer maxSrg;
311         //Get value for max Srg from info subtree, required for iteration
312         //if not present assume to be 20 (temporary)
313         if (ordmInfo.getMaxSrgs() != null) {
314             maxSrg = ordmInfo.getMaxSrgs();
315         } else {
316             maxSrg = 20;
317         }
318
319         Integer srgCounter = 1;
320         while (srgCounter <= maxSrg) {
321             LOG.info("Getting Circuitpacks for Srg Number " + srgCounter);
322             InstanceIdentifier<SharedRiskGroup> srgIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
323                 SharedRiskGroup.class, new SharedRiskGroupKey(srgCounter));
324             try {
325                 Optional<SharedRiskGroup> ordmSrgObject = rtx.read(LogicalDatastoreType.CONFIGURATION, srgIID).get();
326
327                 if (ordmSrgObject.isPresent()) {
328
329                     srgCps.addAll(
330                         new ArrayList<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev161014.srg
331                             .CircuitPacks>(ordmSrgObject.get().getCircuitPacks()));
332
333                 } else {
334                     LOG.info("Device has " + (srgCounter - 1) + " Srg");
335                     break;
336                 }
337             } catch (InterruptedException | ExecutionException ex) {
338                 LOG.warn("Failed to read Srg " + srgCounter);
339                 break;
340             }
341             srgCounter++;
342         }
343
344         return srgCps;
345     }
346
347     /**
348      * This static method returns the DataBroker for a netconf
349      * node.
350      *
351      * @param nodeId Unique identifier for the mounted netconf-
352      *               node
353      * @param mps Reference to mount service
354      * @return Databroker for the given device
355      */
356
357     public static DataBroker getDeviceDataBroker(String nodeId, MountPointService mps) {
358         InstanceIdentifier<Node> netconfNodeIID = InstanceIdentifier.builder(NetworkTopology.class).child(
359             Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))).child(Node.class,
360                 new NodeKey(new NodeId(nodeId))).build();
361
362         // Get the mount point for the specified node
363         final Optional<MountPoint> netconfNodeOptional = mps.getMountPoint(netconfNodeIID);
364         if (netconfNodeOptional.isPresent()) {
365             MountPoint netconfNode = netconfNodeOptional.get();
366             // Get the DataBroker for the mounted node
367             DataBroker netconfNodeDataBroker = netconfNode.getService(DataBroker.class).get();
368             return netconfNodeDataBroker;
369         } else {
370             LOG.info("Device Data broker not found for :" + nodeId);
371         }
372         return null;
373     }
374 }