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