Enabled flex-grid support for 2.2.1 Roadms
[transportpce.git] / renderer / src / main / java / org / opendaylight / transportpce / renderer / provisiondevice / DeviceRendererServiceImpl.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.renderer.provisiondevice;
9
10 import com.google.common.collect.Sets;
11 import com.google.common.util.concurrent.FluentFuture;
12 import java.math.BigDecimal;
13 import java.util.ArrayList;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Optional;
17 import java.util.Set;
18 import java.util.concurrent.ConcurrentLinkedQueue;
19 import java.util.concurrent.CopyOnWriteArrayList;
20 import java.util.concurrent.ExecutionException;
21 import java.util.concurrent.ForkJoinPool;
22 import java.util.concurrent.ForkJoinTask;
23 import java.util.concurrent.Future;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.TimeoutException;
26 import java.util.concurrent.atomic.AtomicBoolean;
27 import org.eclipse.jdt.annotation.NonNull;
28 import org.opendaylight.mdsal.binding.api.DataBroker;
29 import org.opendaylight.mdsal.binding.api.ReadTransaction;
30 import org.opendaylight.mdsal.binding.api.WriteTransaction;
31 import org.opendaylight.mdsal.common.api.CommitInfo;
32 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
33 import org.opendaylight.transportpce.common.StringConstants;
34 import org.opendaylight.transportpce.common.Timeouts;
35 import org.opendaylight.transportpce.common.crossconnect.CrossConnect;
36 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
37 import org.opendaylight.transportpce.common.mapping.PortMapping;
38 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
39 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
40 import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
41 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
42 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServiceListTopology;
43 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.ServiceNodelist;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service.nodelist.NodelistBuilder;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service.nodelist.NodelistKey;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev200827.network.nodes.Mapping;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.CreateOtsOmsInput;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.CreateOtsOmsOutput;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.CreateOtsOmsOutputBuilder;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.RendererRollbackInput;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.RendererRollbackOutput;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.RendererRollbackOutputBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.ServicePathInput;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.ServicePathOutput;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.ServicePathOutputBuilder;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.renderer.rollback.output.FailedToRollback;
58 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.renderer.rollback.output.FailedToRollbackBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.renderer.rollback.output.FailedToRollbackKey;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.Topology;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.OchAttributes.ModulationFormat;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceList;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.ServicesBuilder;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.ServicesKey;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.node.interfaces.NodeInterface;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.node.interfaces.NodeInterfaceBuilder;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.node.interfaces.NodeInterfaceKey;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.olm.renderer.input.Nodes;
70 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev200129.OtnLinkType;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75
76 public class DeviceRendererServiceImpl implements DeviceRendererService {
77     private static final String ODU4 = "-ODU4";
78     private static final Logger LOG = LoggerFactory.getLogger(DeviceRendererServiceImpl.class);
79     private final DataBroker dataBroker;
80     private final DeviceTransactionManager deviceTransactionManager;
81     private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
82     private final OpenRoadmInterfaces openRoadmInterfaces;
83     private final CrossConnect crossConnect;
84     private final PortMapping portMapping;
85     private final NetworkModelService networkModelService;
86
87     public DeviceRendererServiceImpl(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager,
88             OpenRoadmInterfaceFactory openRoadmInterfaceFactory, OpenRoadmInterfaces openRoadmInterfaces,
89             CrossConnect crossConnect, PortMapping portMapping, NetworkModelService networkModelService) {
90         this.dataBroker = dataBroker;
91         this.deviceTransactionManager = deviceTransactionManager;
92         this.openRoadmInterfaceFactory = openRoadmInterfaceFactory;
93         this.openRoadmInterfaces = openRoadmInterfaces;
94         this.crossConnect = crossConnect;
95         this.portMapping = portMapping;
96         this.networkModelService = networkModelService;
97     }
98
99     @Override
100     public ServicePathOutput setupServicePath(ServicePathInput input, ServicePathDirection direction) {
101         List<Nodes> nodes = input.getNodes();
102         // Register node for suppressing alarms
103         if (!alarmSuppressionNodeRegistration(input)) {
104             LOG.warn("Alarm suppresion node registration failed!!!!");
105         }
106         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
107         Set<NodeInterface> nodeInterfaces = Sets.newConcurrentHashSet();
108         Set<String> nodesProvisioned = Sets.newConcurrentHashSet();
109         CopyOnWriteArrayList<Nodes> otnNodesProvisioned = new CopyOnWriteArrayList<>();
110         ServiceListTopology topology = new ServiceListTopology();
111         AtomicBoolean success = new AtomicBoolean(true);
112         ForkJoinPool forkJoinPool = new ForkJoinPool();
113         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
114             String nodeId = node.getNodeId();
115             // take the index of the node
116             int nodeIndex = nodes.indexOf(node);
117             LOG.info("Starting provisioning for node : {}", nodeId);
118             List<String> createdEthInterfaces = new ArrayList<>();
119             List<String> createdOtuInterfaces = new ArrayList<>();
120             List<String> createdOduInterfaces = new ArrayList<>();
121             List<String> createdOchInterfaces = new ArrayList<>();
122             List<String> createdConnections = new ArrayList<>();
123             int crossConnectFlag = 0;
124             try {
125                 // if the node is currently mounted then proceed
126                 if (this.deviceTransactionManager.isDeviceMounted(nodeId)) {
127                     // TODO: In the case of flex-grid, the wave-number becomes bitmap index
128                     // TODO: need to update transportpce-common-types accordingly, to a more, generic-term
129                     Long waveNumber = input.getWaveNumber().toJava();
130                     BigDecimal centerFreq = null;
131                     BigDecimal slotWidth = null;
132                     if (input.getCenterFreq() != null) {
133                         centerFreq = input.getCenterFreq().getValue();
134                     }
135                     if (input.getSlotWidth() != null) {
136                         slotWidth = input.getSlotWidth().getValue();
137                     }
138                     String srcTp = node.getSrcTp();
139                     String destTp = node.getDestTp();
140                     if ((destTp != null) && destTp.contains(StringConstants.NETWORK_TOKEN)) {
141                         crossConnectFlag++;
142                         String supportingOchInterface;
143                         if ((centerFreq != null) && (slotWidth != null)) {
144                             supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
145                                 nodeId, destTp, waveNumber, ModulationFormat.DpQpsk, centerFreq, slotWidth);
146                         }
147                         else {
148                             supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
149                                 nodeId, destTp, waveNumber, ModulationFormat.DpQpsk);
150                         }
151                         createdOchInterfaces.add(supportingOchInterface);
152                         // Here we pass logical connection-point of z-end to set SAPI and DAPI
153                         Nodes tgtNode = null;
154                         if (nodeIndex + 1 == nodes.size()) {
155                             // For the end node, tgtNode becomes the first node in the list
156                             tgtNode = nodes.get(0);
157                         } else {
158                             tgtNode = nodes.get(nodeIndex + 1);
159                         }
160                         // tgtNode srcTp is null in this if cond
161                         String supportingOtuInterface = this.openRoadmInterfaceFactory
162                                 .createOpenRoadmOtu4Interface(nodeId, destTp, supportingOchInterface,
163                                     tgtNode.getNodeId(), tgtNode.getDestTp());
164                         createdOtuInterfaces.add(supportingOtuInterface);
165                         if (srcTp == null) {
166                             otnNodesProvisioned.add(node);
167                         } else {
168                             createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOdu4Interface(nodeId,
169                                     destTp, supportingOtuInterface));
170                         }
171                     }
172                     if ((srcTp != null) && srcTp.contains(StringConstants.CLIENT_TOKEN)) {
173                         crossConnectFlag++;
174                         // create OpenRoadm Xponder Client Interfaces
175                         createdEthInterfaces.add(
176                             this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(nodeId, srcTp));
177                     }
178                     if ((srcTp != null) && srcTp.contains(StringConstants.NETWORK_TOKEN)) {
179                         crossConnectFlag++;
180                         // create OpenRoadm Xponder Line Interfaces
181                         String supportingOchInterface;
182                         if ((centerFreq != null) && (slotWidth != null)) {
183                             supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
184                                 nodeId, srcTp, waveNumber, ModulationFormat.DpQpsk, centerFreq, slotWidth);
185                         }
186                         else {
187                             supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
188                                 nodeId, srcTp, waveNumber, ModulationFormat.DpQpsk);
189                         }
190                         createdOchInterfaces.add(supportingOchInterface);
191                         String supportingOtuInterface = this.openRoadmInterfaceFactory
192                                 .createOpenRoadmOtu4Interface(nodeId, srcTp, supportingOchInterface);
193                         createdOtuInterfaces.add(supportingOtuInterface);
194                         createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOdu4Interface(nodeId,
195                                 srcTp, supportingOtuInterface));
196                         Mapping mapping = this.portMapping.getMapping(nodeId,srcTp);
197                         if (mapping != null && mapping.getXponderType() != null
198                             && (mapping.getXponderType().getIntValue() == 3
199                             || mapping.getXponderType().getIntValue() == 2)) {
200                             createdOduInterfaces.add(this.openRoadmInterfaceFactory
201                                 .createOpenRoadmOtnOdu4Interface(nodeId, destTp, supportingOtuInterface));
202                         } else {
203                             createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOdu4Interface(nodeId,
204                                     destTp, supportingOtuInterface));
205                         }
206                     }
207                     if ((destTp != null) && destTp.contains(StringConstants.CLIENT_TOKEN)) {
208                         crossConnectFlag++;
209                         // create OpenRoadm Xponder Client Interfaces
210                         createdEthInterfaces.add(
211                             this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(nodeId, destTp));
212                     }
213                     if ((srcTp != null) && (srcTp.contains(StringConstants.TTP_TOKEN)
214                             || srcTp.contains(StringConstants.PP_TOKEN))) {
215                         if ((centerFreq != null) && (slotWidth != null)) {
216                             createdOchInterfaces.addAll(
217                                 this.openRoadmInterfaceFactory
218                                     .createOpenRoadmOchInterface(nodeId, srcTp, waveNumber, centerFreq, slotWidth));
219                         }
220                         else {
221                             createdOchInterfaces.addAll(
222                                 this.openRoadmInterfaceFactory
223                                     .createOpenRoadmOchInterface(nodeId, srcTp, waveNumber));
224                         }
225                     }
226                     if ((destTp != null) && (destTp.contains(StringConstants.TTP_TOKEN)
227                             || destTp.contains(StringConstants.PP_TOKEN))) {
228
229                         if ((centerFreq != null) && (slotWidth != null)) {
230                             createdOchInterfaces.addAll(
231                                 this.openRoadmInterfaceFactory
232                                     .createOpenRoadmOchInterface(nodeId, destTp, waveNumber, centerFreq, slotWidth));
233                         }
234                         else {
235                             createdOchInterfaces.addAll(
236                                 this.openRoadmInterfaceFactory
237                                     .createOpenRoadmOchInterface(nodeId, destTp, waveNumber));
238                         }
239
240                     }
241                     if (crossConnectFlag < 1) {
242                         LOG.info("Creating cross connect between source {} and destination {} for node {}", srcTp,
243                                 destTp, nodeId);
244                         Optional<String> connectionNameOpt =
245                                 this.crossConnect.postCrossConnect(nodeId, waveNumber, srcTp, destTp);
246                         if (connectionNameOpt.isPresent()) {
247                             nodesProvisioned.add(nodeId);
248                             createdConnections.add(connectionNameOpt.get());
249                         } else {
250                             processErrorMessage("Unable to post Roadm-connection for node " + nodeId, forkJoinPool,
251                                     results);
252                             success.set(false);
253                         }
254                     }
255                 } else {
256                     processErrorMessage(nodeId + " is not mounted on the controller", forkJoinPool, results);
257                     success.set(false);
258                 }
259             } catch (OpenRoadmInterfaceException ex) {
260                 processErrorMessage("Setup service path failed! Exception:" + ex.toString(), forkJoinPool, results);
261                 success.set(false);
262             }
263             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
264                 .withKey(new NodeInterfaceKey(nodeId))
265                 .setNodeId(nodeId)
266                 .setConnectionId(createdConnections)
267                 .setEthInterfaceId(createdEthInterfaces)
268                 .setOtuInterfaceId(createdOtuInterfaces)
269                 .setOduInterfaceId(createdOduInterfaces)
270                 .setOchInterfaceId(createdOchInterfaces);
271             nodeInterfaces.add(nodeInterfaceBuilder.build());
272         }));
273         try {
274             forkJoinTask.get();
275         } catch (InterruptedException | ExecutionException e) {
276             LOG.error("Error while setting up service paths!", e);
277         }
278         forkJoinPool.shutdown();
279
280         if (success.get()) {
281             results.add("Roadm-connection successfully created for nodes: " + String.join(", ", nodesProvisioned));
282         }
283         // setting topology in the service list data store
284         try {
285             setTopologyForService(input.getServiceName(), topology.getTopology());
286             updateOtnTopology(otnNodesProvisioned, false);
287         } catch (InterruptedException | TimeoutException | ExecutionException e) {
288             LOG.warn("Failed to write topologies for service {}.", input.getServiceName(), e);
289         }
290         if (!alarmSuppressionNodeRemoval(input.getServiceName())) {
291             LOG.error("Alarm suppresion node removal failed!!!!");
292         }
293         ServicePathOutputBuilder setServBldr = new ServicePathOutputBuilder()
294             .setNodeInterface(new ArrayList<>(nodeInterfaces))
295             .setSuccess(success.get())
296             .setResult(String.join("\n", results));
297         return setServBldr.build();
298     }
299
300     private ConcurrentLinkedQueue<String> processErrorMessage(String message, ForkJoinPool forkJoinPool,
301             ConcurrentLinkedQueue<String> messages) {
302         LOG.warn("Received error message {}", message);
303         messages.add(message);
304         forkJoinPool.shutdown();
305         return messages;
306     }
307
308     @Override
309     public ServicePathOutput deleteServicePath(ServicePathInput input) {
310         List<Nodes> nodes = input.getNodes();
311         AtomicBoolean success = new AtomicBoolean(true);
312         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
313         if (!alarmSuppressionNodeRegistration(input)) {
314             LOG.warn("Alarm suppresion node registraion failed!!!!");
315         }
316         CopyOnWriteArrayList<Nodes> otnNodesProvisioned = new CopyOnWriteArrayList<>();
317         ForkJoinPool forkJoinPool = new ForkJoinPool();
318         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
319             List<String> interfacesToDelete = new LinkedList<>();
320             String nodeId = node.getNodeId();
321             LOG.info("Deleting service setup on node {}", nodeId);
322             String srcTp;
323             String destTp;
324             Long waveNumber = input.getWaveNumber().toJava();
325             if (node.getDestTp() == null) {
326                 LOG.error("Destination termination point must not be null.");
327                 return;
328             } else {
329                 destTp = node.getDestTp();
330             }
331             if (node.getSrcTp() != null) {
332                 srcTp = node.getSrcTp();
333             } else {
334                 srcTp = "";
335                 otnNodesProvisioned.add(node);
336             }
337             // if the node is currently mounted then proceed.
338             if (this.deviceTransactionManager.isDeviceMounted(nodeId)) {
339                 interfacesToDelete.addAll(getInterfaces2delete(nodeId, srcTp, destTp, waveNumber));
340             } else {
341                 String result = nodeId + " is not mounted on the controller";
342                 results.add(result);
343                 success.set(false);
344                 LOG.warn(result);
345                 forkJoinPool.shutdown();
346                 return;
347                 //TODO should deletion end here?
348             }
349             for (String interfaceId : interfacesToDelete) {
350                 try {
351                     this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
352                 } catch (OpenRoadmInterfaceException e) {
353                     String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
354                     success.set(false);
355                     LOG.error(result, e);
356                     results.add(result);
357                 }
358             }
359         }));
360         try {
361             forkJoinTask.get();
362         } catch (InterruptedException | ExecutionException e) {
363             LOG.error("Error while deleting service paths!", e);
364         }
365         forkJoinPool.shutdown();
366         updateOtnTopology(otnNodesProvisioned, true);
367         if (!alarmSuppressionNodeRemoval(input.getServiceName())) {
368             LOG.error("Alarm suppresion node removal failed!!!!");
369         }
370         ServicePathOutputBuilder delServBldr = new ServicePathOutputBuilder();
371         delServBldr.setSuccess(success.get());
372         if (results.isEmpty()) {
373             return delServBldr.setResult("Request processed").build();
374         } else {
375             return delServBldr.setResult(String.join("\n", results)).build();
376         }
377     }
378
379     private List<String>  getInterfaces2delete(
380             String nodeId, String srcTp, String destTp, Long waveNumber) {
381         List<String> interfacesToDelete = new LinkedList<>();
382         if (destTp.contains(StringConstants.NETWORK_TOKEN)
383                 || srcTp.contains(StringConstants.CLIENT_TOKEN)
384                 || srcTp.contains(StringConstants.NETWORK_TOKEN)
385                 || destTp.contains(StringConstants.CLIENT_TOKEN)) {
386             if (destTp.contains(StringConstants.NETWORK_TOKEN)) {
387                 try {
388                     if (this.openRoadmInterfaces.getInterface(nodeId, destTp + "-ODU").isPresent()) {
389                         interfacesToDelete.add(destTp + "-ODU");
390                     }
391                     if (this.openRoadmInterfaces.getInterface(nodeId, destTp + ODU4).isPresent()) {
392                         interfacesToDelete.add(destTp + ODU4);
393                     }
394                 }
395                 catch (OpenRoadmInterfaceException e) {
396                     LOG.error("impossible to get interface {} or {}", destTp + "-ODU", destTp + ODU4, e);
397                 }
398                 interfacesToDelete.add(destTp + "-OTU");
399                 interfacesToDelete.add(
400                         this.openRoadmInterfaceFactory.createOpenRoadmOchInterfaceName(destTp, waveNumber));
401             }
402             if (srcTp.contains(StringConstants.NETWORK_TOKEN)) {
403                 interfacesToDelete.add(srcTp + "-ODU");
404                 interfacesToDelete.add(srcTp + "-OTU");
405                 interfacesToDelete
406                         .add(this.openRoadmInterfaceFactory.createOpenRoadmOchInterfaceName(srcTp, waveNumber));
407             }
408             if (srcTp.contains(StringConstants.CLIENT_TOKEN)) {
409                 interfacesToDelete.add(srcTp + "-ETHERNET");
410             }
411             if (destTp.contains(StringConstants.CLIENT_TOKEN)) {
412                 interfacesToDelete.add(destTp + "-ETHERNET");
413             }
414         } else {
415             String connectionNumber = srcTp + "-" + destTp + "-" + waveNumber;
416             List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, false);
417             connectionNumber = destTp + "-" + srcTp + "-" + waveNumber;
418             if (intToDelete != null) {
419                 for (String interf : intToDelete) {
420                     if (!this.openRoadmInterfaceFactory.isUsedByXc(nodeId, interf, connectionNumber,
421                         this.deviceTransactionManager)) {
422                         interfacesToDelete.add(interf);
423                     }
424                 }
425             }
426         }
427         return interfacesToDelete;
428     }
429
430     @Override
431     public RendererRollbackOutput rendererRollback(RendererRollbackInput input) {
432         boolean success = true;
433         List<FailedToRollback> failedToRollbackList = new ArrayList<>();
434         for (NodeInterface nodeInterfaces : input.getNodeInterface()) {
435             List<String> failedInterfaces = new ArrayList<>();
436             String nodeId = nodeInterfaces.getNodeId();
437             for (String connectionId : nodeInterfaces.getConnectionId()) {
438                 List<String> listInter = this.crossConnect.deleteCrossConnect(nodeId, connectionId, false);
439                 if (listInter != null) {
440                     LOG.info("Cross connect {} on node {} successfully deleted.", connectionId, nodeId);
441                 } else {
442                     LOG.error("Failed to delete cross connect {} on node {}!", connectionId, nodeId);
443                     success = false;
444                     failedInterfaces.add(connectionId);
445                 }
446             }
447             // Interfaces needs to be in specific order to delete. Order is:
448             // 1. ODU interfaces
449             // 2. OTU interfaces
450             // 3. OCH interfaces
451             // 4. ETH interfaces
452             LinkedList<String> interfacesToDelete = new LinkedList<>();
453             if (nodeInterfaces.getOduInterfaceId() != null) {
454                 interfacesToDelete.addAll(nodeInterfaces.getOduInterfaceId());
455             }
456             if (nodeInterfaces.getOtuInterfaceId() != null) {
457                 interfacesToDelete.addAll(nodeInterfaces.getOtuInterfaceId());
458             }
459             if (nodeInterfaces.getOchInterfaceId() != null) {
460                 interfacesToDelete.addAll(nodeInterfaces.getOchInterfaceId());
461             }
462             if (nodeInterfaces.getEthInterfaceId() != null) {
463                 interfacesToDelete.addAll(nodeInterfaces.getEthInterfaceId());
464             }
465             LOG.info("Going to execute rollback on node {}. Interfaces to rollback: {}", nodeId,
466                     String.join(", ", interfacesToDelete));
467             for (String interfaceId : interfacesToDelete) {
468                 try {
469                     this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
470                     LOG.info("Interface {} on node {} successfully deleted.", interfaceId, nodeId);
471                 } catch (OpenRoadmInterfaceException e) {
472                     LOG.error("Failed to delete interface {} on node {}!", interfaceId, nodeId);
473                     success = false;
474                     failedInterfaces.add(interfaceId);
475                 }
476             }
477             failedToRollbackList.add(new FailedToRollbackBuilder().withKey(new FailedToRollbackKey(nodeId))
478                     .setNodeId(nodeId).setInterface(failedInterfaces).build());
479         }
480         return new RendererRollbackOutputBuilder().setSuccess(success).setFailedToRollback(failedToRollbackList)
481                 .build();
482     }
483
484     private boolean alarmSuppressionNodeRegistration(ServicePathInput input) {
485         NodelistBuilder nodeListBuilder = new NodelistBuilder()
486             .withKey(new NodelistKey(input.getServiceName()))
487             .setServiceName(input.getServiceName());
488         List<org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service
489             .nodelist.nodelist.Nodes> nodeList =
490                 new ArrayList<>();
491         for (Nodes node : input.getNodes()) {
492             nodeList.add(
493                     new org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
494                     .service.nodelist.nodelist.NodesBuilder()
495                             .setNodeId(node.getNodeId()).build());
496         }
497         nodeListBuilder.setNodes(nodeList);
498         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
499             .service.nodelist.Nodelist> nodeListIID =
500                         InstanceIdentifier.create(ServiceNodelist.class).child(
501                                 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression
502                                     .rev171102.service.nodelist.Nodelist.class,
503                                 new NodelistKey(input.getServiceName()));
504         final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction();
505         writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodeListIID, nodeListBuilder.build());
506         FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
507         try {
508             commit.get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
509             LOG.info("Nodes are register for alarm suppression for service: {}", input.getServiceName());
510             return true;
511         } catch (ExecutionException | InterruptedException | TimeoutException e) {
512             LOG.warn("Failed to alarm suppresslist for service: {}", input.getServiceName(), e);
513             return false;
514         }
515     }
516
517     private boolean alarmSuppressionNodeRemoval(String serviceName) {
518         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
519             .service.nodelist.Nodelist> nodeListIID =
520                         InstanceIdentifier.create(ServiceNodelist.class).child(
521                                 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression
522                                     .rev171102.service.nodelist.Nodelist.class,
523                                 new NodelistKey(serviceName));
524         final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction();
525         writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, nodeListIID);
526         FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
527         try {
528             commit.get(Timeouts.DATASTORE_DELETE, TimeUnit.MILLISECONDS);
529             LOG.info("Nodes are unregister for alarm suppression for service: {}", serviceName);
530             return true;
531         } catch (InterruptedException | TimeoutException | ExecutionException e) {
532             LOG.warn("Failed to alarm suppresslist for service: {}", serviceName, e);
533             return false;
534         }
535     }
536
537     private void setTopologyForService(String name, Topology topo)
538             throws InterruptedException, ExecutionException, TimeoutException {
539         ServicesBuilder servicesBuilder;
540         // Get the service from the service list inventory
541         ServicesKey serviceKey = new ServicesKey(name);
542         InstanceIdentifier<Services> iid =
543                 InstanceIdentifier.create(ServiceList.class).child(Services.class, serviceKey);
544         Optional<Services> services;
545         try (ReadTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
546             Future<java.util.Optional<Services>> future =
547                     readTx.read(LogicalDatastoreType.OPERATIONAL, iid);
548             services = future.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
549         } catch (InterruptedException | ExecutionException | TimeoutException e) {
550             throw e;
551         }
552         if (services.isPresent()) {
553             LOG.info("service {} already exists", name);
554             servicesBuilder = new ServicesBuilder(services.get()).setTopology(topo);
555             WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction();
556             writeTx.merge(LogicalDatastoreType.OPERATIONAL, iid, servicesBuilder.build());
557             writeTx.commit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
558         } else {
559             LOG.warn("Service {} does not exist - topology can not be updated", name);
560         }
561     }
562
563     @Override
564     public CreateOtsOmsOutput createOtsOms(CreateOtsOmsInput input) throws OpenRoadmInterfaceException {
565         CreateOtsOmsOutputBuilder output = new CreateOtsOmsOutputBuilder();
566         String result = "";
567         Boolean success = false;
568         // if the node is currently mounted then proceed.
569         if (this.deviceTransactionManager.isDeviceMounted(input.getNodeId())) {
570             Mapping oldMapping = null;
571             Mapping newMapping = null;
572             oldMapping = this.portMapping.getMapping(input.getNodeId(), input.getLogicalConnectionPoint());
573             if (oldMapping != null) {
574                 String otsInterface =
575                         this.openRoadmInterfaceFactory.createOpenRoadmOtsInterface(input.getNodeId(), oldMapping);
576                 newMapping = this.portMapping.getMapping(input.getNodeId(), input.getLogicalConnectionPoint());
577                 int count = 0;
578                 Boolean isSupportingOtsPresent = isSupportingOtsPresent(newMapping);
579                 while (!isSupportingOtsPresent && (count < 6)) {
580                     LOG.info("waiting for post interface operation on node '{}'...", input.getNodeId());
581                     try {
582                         Thread.sleep(10000);
583                         this.portMapping.updateMapping(input.getNodeId(), oldMapping);
584                     } catch (InterruptedException e) {
585                         LOG.error("Failed to wait for post interface operation ");
586                     }
587                     newMapping = this.portMapping.getMapping(input.getNodeId(), input.getLogicalConnectionPoint());
588                     isSupportingOtsPresent = isSupportingOtsPresent(newMapping);
589                     count++;
590                 }
591                 if (count < 6) {
592                     String omsInterface =
593                             this.openRoadmInterfaceFactory.createOpenRoadmOmsInterface(input.getNodeId(), newMapping);
594                     if (omsInterface != null) {
595                         result = "Interfaces " + otsInterface + " - " + omsInterface + " successfully created on node "
596                                 + input.getNodeId();
597                         success = true;
598                     } else {
599                         LOG.error("Fail to create OpenRoadmOms Interface for node '{}'", input.getNodeId());
600                         result = "Fail to create OpenRoadmOms Interface for node : " + input.getNodeId();
601                     }
602                 } else {
603                     LOG.error("Unable to get ots interface from mapping {} for node {}",
604                             oldMapping.getLogicalConnectionPoint(), input.getNodeId());
605                     result = String.format("Unable to get ots interface from mapping %s - %s",
606                             oldMapping.getLogicalConnectionPoint(), input.getNodeId());
607                 }
608             } else {
609                 result = "Logical Connection point " + input.getLogicalConnectionPoint() + " does not exist for "
610                         + input.getNodeId();
611             }
612         } else {
613             result = input.getNodeId() + " is not mounted on the controller";
614             LOG.warn("{} is not mounted on the controller",input.getNodeId());
615         }
616         return output.setResult(result).setSuccess(success).build();
617     }
618
619     private Boolean isSupportingOtsPresent(Mapping mapping) {
620         Boolean result = false;
621         if (mapping != null) {
622             if (mapping.getSupportingOts() != null) {
623                 LOG.info("SupportingOts info is present in mapping {}", mapping);
624                 result = true;
625             } else {
626                 LOG.warn("SupportingOts info not present in mapping {}", mapping);
627             }
628         }
629         return result;
630     }
631
632     private void updateOtnTopology(CopyOnWriteArrayList<Nodes> nodes, boolean isDeletion) {
633         if (nodes.size() != 2) {
634             LOG.error("Error with OTU4 links to update in otn-topology");
635             return;
636         }
637         if (isDeletion) {
638             LOG.info("updating otn-topology removing OTU4 links");
639             this.networkModelService.deleteOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getDestTp(),
640                 nodes.get(1).getNodeId(), nodes.get(1).getDestTp(), OtnLinkType.OTU4);
641         } else {
642             LOG.info("updating otn-topology adding OTU4 links");
643             this.networkModelService.createOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getDestTp(),
644                 nodes.get(1).getNodeId(), nodes.get(1).getDestTp(), OtnLinkType.OTU4);
645         }
646     }
647 }