f22c3eb9420979cd3b8549f5aa813fab4869c1d2
[transportpce.git] / common / src / main / java / org / opendaylight / transportpce / common / crossconnect / CrossConnectImpl221.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 package org.opendaylight.transportpce.common.crossconnect;
9
10 import com.google.common.util.concurrent.FluentFuture;
11 import java.math.BigDecimal;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Optional;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.opendaylight.mdsal.binding.api.MountPoint;
20 import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
21 import org.opendaylight.mdsal.common.api.CommitInfo;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.transportpce.common.Timeouts;
24 import org.opendaylight.transportpce.common.device.DeviceTransaction;
25 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
26 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
27 import org.opendaylight.transportpce.common.fixedflex.SpectrumInformation;
28 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.OpticalControlMode;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.PowerDBm;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.GetConnectionPortTrailInputBuilder;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.GetConnectionPortTrailOutput;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.OduConnection.Direction;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.OrgOpenroadmDeviceService;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.connection.DestinationBuilder;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.connection.SourceBuilder;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.get.connection.port.trail.output.Ports;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.OrgOpenroadmDevice;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.OduConnectionBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.OduConnectionKey;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.RoadmConnections;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.RoadmConnectionsBuilder;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.RoadmConnectionsKey;
44 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.otn.renderer.nodes.Nodes;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.opendaylight.yangtools.yang.common.RpcResult;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 public class CrossConnectImpl221 {
51
52     private static final Logger LOG = LoggerFactory.getLogger(CrossConnectImpl221.class);
53     private static final String DEV_TRANSACTION_NOT_FOUND = "Device transaction for device {} was not found!";
54     private static final String UNABLE_DEV_TRANSACTION = "Unable to obtain device transaction for device {}!";
55     private final DeviceTransactionManager deviceTransactionManager;
56
57     public CrossConnectImpl221(DeviceTransactionManager deviceTransactionManager) {
58         this.deviceTransactionManager = deviceTransactionManager;
59     }
60
61     public Optional<RoadmConnections> getCrossConnect(String deviceId, String connectionNumber) {
62         //TODO Change it to Operational later for real device
63         return deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.CONFIGURATION,
64                 generateRdmConnectionIID(connectionNumber), Timeouts.DEVICE_READ_TIMEOUT,
65                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
66     }
67
68     public Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org
69         .openroadm.device.OduConnection> getOtnCrossConnect(String deviceId, String connectionNumber) {
70         //TODO Change it to Operational later for real device
71         return deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.CONFIGURATION,
72                 generateOduConnectionIID(connectionNumber), Timeouts.DEVICE_READ_TIMEOUT,
73                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
74     }
75
76     public Optional<String> postCrossConnect(String deviceId, String srcTp, String destTp,
77             SpectrumInformation spectrumInformation) {
78         String connectionNumber = spectrumInformation.getIdentifierFromParams(srcTp, destTp);
79         RoadmConnectionsBuilder rdmConnBldr = new RoadmConnectionsBuilder()
80                 .setConnectionName(connectionNumber)
81                 .setOpticalControlMode(OpticalControlMode.Off)
82                 .setSource(new SourceBuilder()
83                         .setSrcIf(spectrumInformation.getIdentifierFromParams(srcTp,"nmc"))
84                         .build())
85                 .setDestination(new DestinationBuilder()
86                         .setDstIf(spectrumInformation.getIdentifierFromParams(destTp,"nmc"))
87                         .build());
88
89         InstanceIdentifier<RoadmConnections> rdmConnectionIID =
90                 InstanceIdentifier.create(OrgOpenroadmDevice.class)
91                     .child(RoadmConnections.class, new RoadmConnectionsKey(rdmConnBldr.getConnectionName()));
92
93         Future<Optional<DeviceTransaction>> deviceTxFuture = deviceTransactionManager.getDeviceTransaction(deviceId);
94         DeviceTransaction deviceTx;
95         try {
96             Optional<DeviceTransaction> deviceTxOpt = deviceTxFuture.get();
97             if (deviceTxOpt.isPresent()) {
98                 deviceTx = deviceTxOpt.get();
99             } else {
100                 LOG.error(DEV_TRANSACTION_NOT_FOUND, deviceId);
101                 return Optional.empty();
102             }
103         } catch (InterruptedException | ExecutionException e) {
104             LOG.error(UNABLE_DEV_TRANSACTION, deviceId, e);
105             return Optional.empty();
106         }
107
108         // post the cross connect on the device
109         deviceTx.merge(LogicalDatastoreType.CONFIGURATION, rdmConnectionIID, rdmConnBldr.build());
110         FluentFuture<? extends @NonNull CommitInfo> commit =
111                 deviceTx.commit(Timeouts.DEVICE_WRITE_TIMEOUT, Timeouts.DEVICE_WRITE_TIMEOUT_UNIT);
112         try {
113             commit.get();
114             LOG.info("Roadm-connection successfully created: {}-{}-{}-{}", srcTp, destTp,
115                     spectrumInformation.getLowerSpectralSlotNumber(),
116                     spectrumInformation.getHigherSpectralSlotNumber());
117             return Optional.of(connectionNumber);
118         } catch (InterruptedException | ExecutionException e) {
119             LOG.warn("Failed to post {}. Exception: ", rdmConnBldr.build(), e);
120         }
121         return Optional.empty();
122     }
123
124
125     public List<String> deleteCrossConnect(String deviceId, String connectionName, boolean isOtn) {
126         List<String> interfList = new ArrayList<>();
127         Optional<RoadmConnections> xc = getCrossConnect(deviceId, connectionName);
128         Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device.container.org
129             .openroadm.device.OduConnection> otnXc = getOtnCrossConnect(deviceId, connectionName);
130         //Check if cross connect exists before delete
131         if (xc.isPresent()) {
132             interfList.add(xc.get().getSource().getSrcIf());
133             interfList.add(xc.get().getDestination().getDstIf());
134             interfList.add(xc.get().getSource().getSrcIf().replace("nmc", "mc"));
135             interfList.add(xc.get().getDestination().getDstIf().replace("nmc", "mc"));
136         } else if (otnXc.isPresent()) {
137             interfList.add(otnXc.get().getSource().getSrcIf());
138             interfList.add(otnXc.get().getDestination().getDstIf());
139         } else {
140             LOG.warn("Cross connect {} does not exist, halting delete", connectionName);
141             return null;
142         }
143         Future<Optional<DeviceTransaction>> deviceTxFuture = deviceTransactionManager.getDeviceTransaction(deviceId);
144         DeviceTransaction deviceTx;
145         try {
146             Optional<DeviceTransaction> deviceTxOpt = deviceTxFuture.get();
147             if (deviceTxOpt.isPresent()) {
148                 deviceTx = deviceTxOpt.get();
149             } else {
150                 LOG.error(DEV_TRANSACTION_NOT_FOUND, deviceId);
151                 return null;
152             }
153         } catch (InterruptedException | ExecutionException e) {
154             LOG.error(UNABLE_DEV_TRANSACTION, deviceId, e);
155             return null;
156         }
157
158         // post the cross connect on the device
159         if (isOtn) {
160             deviceTx.delete(LogicalDatastoreType.CONFIGURATION, generateOduConnectionIID(connectionName));
161         } else {
162             deviceTx.delete(LogicalDatastoreType.CONFIGURATION, generateRdmConnectionIID(connectionName));
163         }
164         FluentFuture<? extends @NonNull CommitInfo> commit =
165                 deviceTx.commit(Timeouts.DEVICE_WRITE_TIMEOUT, Timeouts.DEVICE_WRITE_TIMEOUT_UNIT);
166         try {
167             commit.get();
168             LOG.info("Connection {} successfully deleted on {}", connectionName, deviceId);
169             return interfList;
170         } catch (InterruptedException | ExecutionException e) {
171             LOG.warn("Failed to delete {}", connectionName, e);
172         }
173         return null;
174     }
175
176
177     public List<Ports> getConnectionPortTrail(String nodeId, String srcTp, String destTp,
178             int lowerSpectralSlotNumber, int higherSpectralSlotNumber)
179             throws OpenRoadmInterfaceException {
180         String spectralSlotName = String.join(GridConstant.SPECTRAL_SLOT_SEPARATOR,
181                 String.valueOf(lowerSpectralSlotNumber),
182                 String.valueOf(higherSpectralSlotNumber));
183         String connectionName = generateConnectionName(srcTp, destTp, spectralSlotName);
184         Optional<MountPoint> mountPointOpt = deviceTransactionManager.getDeviceMountPoint(nodeId);
185         List<Ports> ports = null;
186         MountPoint mountPoint;
187         if (mountPointOpt.isPresent()) {
188             mountPoint = mountPointOpt.get();
189         } else {
190             LOG.error("Failed to obtain mount point for device {}!", nodeId);
191             return Collections.emptyList();
192         }
193         final Optional<RpcConsumerRegistry> service = mountPoint.getService(RpcConsumerRegistry.class);
194         if (!service.isPresent()) {
195             LOG.error("Failed to get RpcService for node {}", nodeId);
196         }
197         final OrgOpenroadmDeviceService rpcService = service.get().getRpcService(OrgOpenroadmDeviceService.class);
198         final GetConnectionPortTrailInputBuilder portTrainInputBuilder = new GetConnectionPortTrailInputBuilder();
199         portTrainInputBuilder.setConnectionName(connectionName);
200         final Future<RpcResult<GetConnectionPortTrailOutput>> portTrailOutput = rpcService.getConnectionPortTrail(
201                 portTrainInputBuilder.build());
202         if (portTrailOutput != null) {
203             try {
204                 RpcResult<GetConnectionPortTrailOutput> connectionPortTrailOutputRpcResult = portTrailOutput.get();
205                 GetConnectionPortTrailOutput connectionPortTrailOutput = connectionPortTrailOutputRpcResult.getResult();
206                 if (connectionPortTrailOutput == null) {
207                     throw new OpenRoadmInterfaceException(String.format("RPC get connection port trail called on"
208                             + " node %s returned null!", nodeId));
209                 }
210                 LOG.info("Getting port trail for node {}'s connection number {}", nodeId, connectionName);
211                 ports = connectionPortTrailOutput.getPorts();
212                 for (Ports port : ports) {
213                     LOG.info("{} - Circuit pack {} - Port {}", nodeId, port.getCircuitPackName(), port.getPortName());
214                 }
215             } catch (InterruptedException | ExecutionException e) {
216                 LOG.warn("Exception caught", e);
217             }
218         } else {
219             LOG.warn("Port trail is null in getConnectionPortTrail for nodeId {}", nodeId);
220         }
221         return ports != null ? ports : Collections.emptyList();
222     }
223
224
225     public boolean setPowerLevel(String deviceId, OpticalControlMode mode, BigDecimal powerValue, String ctName) {
226         Optional<RoadmConnections> rdmConnOpt = getCrossConnect(deviceId, ctName);
227         if (rdmConnOpt.isPresent()) {
228             RoadmConnectionsBuilder rdmConnBldr = new RoadmConnectionsBuilder(rdmConnOpt.get());
229             rdmConnBldr.setOpticalControlMode(mode);
230             if (powerValue != null) {
231                 rdmConnBldr.setTargetOutputPower(new PowerDBm(powerValue));
232             }
233             RoadmConnections newRdmConn = rdmConnBldr.build();
234
235             Future<Optional<DeviceTransaction>> deviceTxFuture =
236                     deviceTransactionManager.getDeviceTransaction(deviceId);
237             DeviceTransaction deviceTx;
238             try {
239                 Optional<DeviceTransaction> deviceTxOpt = deviceTxFuture.get();
240                 if (deviceTxOpt.isPresent()) {
241                     deviceTx = deviceTxOpt.get();
242                 } else {
243                     LOG.error("Transaction for device {} was not found!", deviceId);
244                     return false;
245                 }
246             } catch (InterruptedException | ExecutionException e) {
247                 LOG.error("Unable to get transaction for device {}!", deviceId, e);
248                 return false;
249             }
250
251             // post the cross connect on the device
252             InstanceIdentifier<RoadmConnections> roadmConnIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
253                     .child(RoadmConnections.class, new RoadmConnectionsKey(ctName));
254             deviceTx.merge(LogicalDatastoreType.CONFIGURATION, roadmConnIID, newRdmConn);
255             FluentFuture<? extends @NonNull CommitInfo> commit =
256                 deviceTx.commit(Timeouts.DEVICE_WRITE_TIMEOUT, Timeouts.DEVICE_WRITE_TIMEOUT_UNIT);
257             try {
258                 commit.get();
259                 LOG.info("Roadm connection power level successfully set ");
260                 return true;
261             } catch (InterruptedException | ExecutionException ex) {
262                 LOG.warn("Failed to post {}", newRdmConn, ex);
263             }
264
265         } else {
266             LOG.warn("Roadm-Connection is null in set power level ({})", ctName);
267         }
268         return false;
269     }
270
271     private InstanceIdentifier<RoadmConnections> generateRdmConnectionIID(String connectionNumber) {
272         return InstanceIdentifier.create(OrgOpenroadmDevice.class)
273                 .child(RoadmConnections.class, new RoadmConnectionsKey(connectionNumber));
274     }
275
276     private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device
277         .container.org.openroadm.device.OduConnection> generateOduConnectionIID(String connectionNumber) {
278         return InstanceIdentifier.create(OrgOpenroadmDevice.class).child(org.opendaylight.yang.gen.v1.http.org
279             .openroadm.device.rev181019.org.openroadm.device.container.org.openroadm.device.OduConnection.class,
280             new OduConnectionKey(connectionNumber));
281     }
282
283     private String generateConnectionName(String srcTp, String destTp, String spectralSlotName) {
284         return String.join(GridConstant.NAME_PARAMETERS_SEPARATOR,srcTp, destTp, spectralSlotName);
285     }
286
287     public Optional<String> postOtnCrossConnect(List<String> createdOduInterfaces, Nodes node) {
288         String deviceId = node.getNodeId();
289         String srcTp = createdOduInterfaces.get(0);
290         String dstTp = createdOduInterfaces.get(1);
291         OduConnectionBuilder oduConnectionBuilder = new OduConnectionBuilder()
292             .setConnectionName(srcTp + "-x-" + dstTp)
293             .setDestination(new org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.odu.connection
294                 .DestinationBuilder().setDstIf(dstTp).build())
295             .setSource(new org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.odu.connection
296                 .SourceBuilder().setSrcIf(srcTp).build())
297             .setDirection(Direction.Bidirectional);
298
299         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device
300                 .container.org.openroadm.device.OduConnection> oduConnectionIID =
301             InstanceIdentifier.create(OrgOpenroadmDevice.class)
302                 .child(org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device
303                         .container.org.openroadm.device.OduConnection.class,
304                     new OduConnectionKey(oduConnectionBuilder.getConnectionName())
305                 );
306
307         Future<Optional<DeviceTransaction>> deviceTxFuture = deviceTransactionManager.getDeviceTransaction(deviceId);
308         DeviceTransaction deviceTx;
309         try {
310             Optional<DeviceTransaction> deviceTxOpt = deviceTxFuture.get();
311             if (deviceTxOpt.isPresent()) {
312                 deviceTx = deviceTxOpt.get();
313             } else {
314                 LOG.error(DEV_TRANSACTION_NOT_FOUND, deviceId);
315                 return Optional.empty();
316             }
317         } catch (InterruptedException | ExecutionException e) {
318             LOG.error(UNABLE_DEV_TRANSACTION, deviceId, e);
319             return Optional.empty();
320         }
321
322         // post the cross connect on the device
323         deviceTx.merge(LogicalDatastoreType.CONFIGURATION, oduConnectionIID, oduConnectionBuilder.build());
324         FluentFuture<? extends @NonNull CommitInfo> commit =
325                 deviceTx.commit(Timeouts.DEVICE_WRITE_TIMEOUT, Timeouts.DEVICE_WRITE_TIMEOUT_UNIT);
326         try {
327             commit.get();
328             LOG.info("Otn-connection successfully created: {}-{}", srcTp, dstTp);
329             return Optional.of(srcTp + "-x-" + dstTp);
330         } catch (InterruptedException | ExecutionException e) {
331             LOG.warn("Failed to post {}.", oduConnectionBuilder.build(), e);
332         }
333         return Optional.empty();
334     }
335 }