2 * Copyright © 2017 AT&T and others. All rights reserved.
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
8 package org.opendaylight.transportpce.renderer.provisiondevice;
10 import com.google.common.collect.Sets;
11 import com.google.common.util.concurrent.FluentFuture;
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.LinkedList;
18 import java.util.List;
20 import java.util.Optional;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentLinkedQueue;
24 import java.util.concurrent.CopyOnWriteArrayList;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.ForkJoinPool;
27 import java.util.concurrent.ForkJoinTask;
28 import java.util.concurrent.Future;
29 import java.util.concurrent.TimeUnit;
30 import java.util.concurrent.TimeoutException;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 import org.eclipse.jdt.annotation.NonNull;
33 import org.opendaylight.mdsal.binding.api.DataBroker;
34 import org.opendaylight.mdsal.binding.api.ReadTransaction;
35 import org.opendaylight.mdsal.binding.api.WriteTransaction;
36 import org.opendaylight.mdsal.common.api.CommitInfo;
37 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
38 import org.opendaylight.transportpce.common.StringConstants;
39 import org.opendaylight.transportpce.common.Timeouts;
40 import org.opendaylight.transportpce.common.crossconnect.CrossConnect;
41 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
42 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
43 import org.opendaylight.transportpce.common.fixedflex.GridUtils;
44 import org.opendaylight.transportpce.common.fixedflex.SpectrumInformation;
45 import org.opendaylight.transportpce.common.mapping.MappingUtils;
46 import org.opendaylight.transportpce.common.mapping.PortMapping;
47 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
48 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
49 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
50 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServiceListTopology;
51 import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection;
52 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.Connection;
53 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.DeviceInterface;
54 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.DeleteService;
55 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.DeleteSubscriber;
56 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.FailedRollbackResult;
57 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.Result;
58 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.delete.Subscriber;
59 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.History;
60 import org.opendaylight.transportpce.renderer.provisiondevice.transaction.history.NonStickHistoryMemory;
61 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.ServiceNodelist;
62 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service.nodelist.NodelistBuilder;
63 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service.nodelist.NodelistKey;
64 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.CreateOtsOmsInput;
65 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.CreateOtsOmsOutput;
66 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.CreateOtsOmsOutputBuilder;
67 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.RendererRollbackInput;
68 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.RendererRollbackOutput;
69 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.RendererRollbackOutputBuilder;
70 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.ServicePathInput;
71 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.ServicePathOutput;
72 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.ServicePathOutputBuilder;
73 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.AEndApiInfo;
74 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.ZEndApiInfo;
75 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.renderer.rollback.output.FailedToRollback;
76 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.renderer.rollback.output.FailedToRollbackBuilder;
77 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.renderer.rollback.output.FailedToRollbackKey;
78 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.OpenroadmNodeVersion;
79 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.mapping.Mapping;
80 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.Topology;
81 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceList;
82 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
83 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.ServicesBuilder;
84 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.ServicesKey;
85 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.link.tp.LinkTp;
86 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.link.tp.LinkTpBuilder;
87 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.node.interfaces.NodeInterface;
88 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.node.interfaces.NodeInterfaceBuilder;
89 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.node.interfaces.NodeInterfaceKey;
90 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev220926.optical.renderer.nodes.Nodes;
91 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
92 import org.osgi.service.component.annotations.Activate;
93 import org.osgi.service.component.annotations.Component;
94 import org.osgi.service.component.annotations.Reference;
95 import org.slf4j.Logger;
96 import org.slf4j.LoggerFactory;
99 public class DeviceRendererServiceImpl implements DeviceRendererService {
100 private static final String IS_NOT_MOUNTED_ON_THE_CONTROLLER = " is not mounted on the controller";
101 private static final Logger LOG = LoggerFactory.getLogger(DeviceRendererServiceImpl.class);
102 private static final String PT_07 = "07";
103 private final DataBroker dataBroker;
104 private final DeviceTransactionManager deviceTransactionManager;
105 private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
106 private final OpenRoadmInterfaces openRoadmInterfaces;
107 private final CrossConnect crossConnect;
108 private final PortMapping portMapping;
111 public DeviceRendererServiceImpl(@Reference DataBroker dataBroker,
112 @Reference DeviceTransactionManager deviceTransactionManager,
113 @Reference OpenRoadmInterfaces openRoadmInterfaces,
114 @Reference CrossConnect crossConnect,
115 @Reference MappingUtils mappingUtils,
116 @Reference PortMapping portMapping) {
117 this.dataBroker = dataBroker;
118 this.deviceTransactionManager = deviceTransactionManager;
119 this.openRoadmInterfaces = openRoadmInterfaces;
120 this.crossConnect = crossConnect;
121 this.portMapping = portMapping;
122 this.openRoadmInterfaceFactory = new OpenRoadmInterfaceFactory(mappingUtils, portMapping, openRoadmInterfaces);
126 public ServicePathOutput setupServicePath(ServicePathInput input, ServicePathDirection direction) {
127 return setupServicePath(input, direction, new NonStickHistoryMemory());
130 @SuppressWarnings("rawtypes")
131 // FIXME check if the ForkJoinTask raw type can be avoided
132 // Raw types use are discouraged since they lack type safety.
133 // Resulting Problems are observed at run time and not at compile time
135 public ServicePathOutput setupServicePath(
136 ServicePathInput input,
137 ServicePathDirection direction,
138 History transactionHistory
140 LOG.info("setup service path for input {} and direction {}", input, direction);
141 List<Nodes> nodes = new ArrayList<>();
142 if (input.getNodes() != null) {
143 nodes.addAll(input.getNodes());
145 SpectrumInformation spectrumInformation = GridUtils.initSpectrumInformationFromServicePathInput(input);
146 // Register node for suppressing alarms
147 if (!alarmSuppressionNodeRegistration(input)) {
148 LOG.warn("Alarm suppresion node registration failed!!!!");
150 ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
151 Map<NodeInterfaceKey,NodeInterface> nodeInterfaces = new ConcurrentHashMap<>();
152 Set<String> nodesProvisioned = Sets.newConcurrentHashSet();
153 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
154 ServiceListTopology topology = new ServiceListTopology();
155 AtomicBoolean success = new AtomicBoolean(true);
156 ForkJoinPool forkJoinPool = new ForkJoinPool();
157 ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
158 String nodeId = node.getNodeId();
159 LOG.info("Starting provisioning for node : {}", nodeId);
160 AEndApiInfo apiInfoA = null;
161 ZEndApiInfo apiInfoZ = null;
162 if (input.getAEndApiInfo() != null && input.getAEndApiInfo().getNodeId().contains(nodeId)) {
163 apiInfoA = input.getAEndApiInfo();
165 if (input.getZEndApiInfo() != null && input.getZEndApiInfo().getNodeId().contains(nodeId)) {
166 apiInfoZ = input.getZEndApiInfo();
168 Set<String> createdEthInterfaces = new HashSet<>();
169 Set<String> createdOtuInterfaces = new HashSet<>();
170 Set<String> createdOduInterfaces = new HashSet<>();
171 Set<String> createdOchInterfaces = new HashSet<>();
172 Set<String> createdConnections = new HashSet<>();
173 int crossConnectFlag = 0;
175 // if the node is currently mounted then proceed
176 if (this.deviceTransactionManager.isDeviceMounted(nodeId)) {
177 String srcTp = node.getSrcTp();
178 String destTp = node.getDestTp();
179 if ((destTp != null) && destTp.contains(StringConstants.NETWORK_TOKEN)) {
180 LOG.info("Adding supporting OCH interface for node {}, dest tp {}, spectrumInformation {}",
181 nodeId, destTp, spectrumInformation);
183 String supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
184 nodeId, destTp, spectrumInformation);
185 transactionHistory.add(new DeviceInterface(nodeId, supportingOchInterface));
187 // Split the string based on # pass the last element as the supported Interface
188 // This is needed for 7.1 device models with B100G, we have OTSI, OTSI-group combined as OCH
189 String[] listOfSuppOchInf = supportingOchInterface.split("#");
190 List<String> createdOchInf = Arrays.asList(listOfSuppOchInf);
191 transactionHistory.addInterfaces(nodeId, listOfSuppOchInf);
193 createdOchInterfaces.addAll(createdOchInf);
194 LOG.info("DEST all otsi interfaces {}", createdOchInterfaces);
195 // Taking the last element
196 supportingOchInterface = listOfSuppOchInf[createdOchInf.size() - 1];
197 String supportingOtuInterface = this.openRoadmInterfaceFactory
198 .createOpenRoadmOtu4Interface(nodeId, destTp, supportingOchInterface, apiInfoA,
200 createdOtuInterfaces.add(supportingOtuInterface);
201 transactionHistory.add(new DeviceInterface(nodeId, supportingOtuInterface));
203 LOG.info("all dest otu interfaces {}", createdOtuInterfaces);
205 otnLinkTps.add(new LinkTpBuilder().setNodeId(nodeId).setTpId(destTp).build());
206 } else if (srcTp.contains(StringConstants.NETWORK_TOKEN)) {
207 // If src and dest tp contains the network token, then it is regenerator
208 LOG.info("Create the ODUCn for regen on the dest-tp");
209 // Here we first create ODUCn interface for the Regen
210 String openRoadmOducn = this.openRoadmInterfaceFactory
211 .createOpenRoadmOducn(nodeId, destTp);
212 createdOduInterfaces.add(openRoadmOducn);
213 transactionHistory.addInterfaces(nodeId, openRoadmOducn);
215 LOG.info("all dest odu interfaces {}", createdOduInterfaces);
217 // This is needed for 7.1 device models for 400GE, since we have ODUC4 and ODUflex
219 String[] oduInterfaces = this.openRoadmInterfaceFactory
220 .createOpenRoadmOdu4HOInterface(
221 nodeId, destTp, false, apiInfoA, apiInfoZ, PT_07).split("#");
222 createdOduInterfaces.addAll(Arrays.asList(oduInterfaces));
223 transactionHistory.addInterfaces(nodeId, oduInterfaces);
227 if ((srcTp != null) && srcTp.contains(StringConstants.CLIENT_TOKEN)) {
228 LOG.info("Adding supporting EThernet interface for node {}, src tp {}", nodeId, srcTp);
230 // create OpenRoadm Xponder Client Interfaces
231 String openRoadmEthInterface = this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(
233 createdEthInterfaces.add(openRoadmEthInterface);
234 transactionHistory.add(new DeviceInterface(nodeId, openRoadmEthInterface));
237 if ((srcTp != null) && srcTp.contains(StringConstants.NETWORK_TOKEN)) {
238 LOG.info("Adding supporting OCH interface for node {}, src tp {}, spectrumInformation {}",
239 nodeId, srcTp, spectrumInformation);
241 // create OpenRoadm Xponder Line Interfaces
242 String supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(
243 nodeId, srcTp, spectrumInformation);
244 transactionHistory.add(new DeviceInterface(nodeId, supportingOchInterface));
246 // createdOchInterfaces.add(supportingOchInterface);
247 // Split the string based on # pass the last element as the supported Interface
248 // This is needed for 7.1 device models with B100G, we have OTSI, OTSI-group combined as OCH
249 String[] listOfSuppOchInf = supportingOchInterface.split("#");
250 transactionHistory.addInterfaces(nodeId, listOfSuppOchInf);
252 List<String> tmpCreatedOchInterfaces = Arrays.asList(listOfSuppOchInf);
253 createdOchInterfaces.addAll(tmpCreatedOchInterfaces);
254 // Taking the last element
255 supportingOchInterface = tmpCreatedOchInterfaces.get(tmpCreatedOchInterfaces.size() - 1);
256 String supportingOtuInterface = this.openRoadmInterfaceFactory.createOpenRoadmOtu4Interface(
257 nodeId, srcTp, supportingOchInterface, apiInfoA, apiInfoZ);
258 createdOtuInterfaces.add(supportingOtuInterface);
259 transactionHistory.add(new DeviceInterface(nodeId, supportingOtuInterface));
261 if (destTp == null) {
262 otnLinkTps.add(new LinkTpBuilder().setNodeId(nodeId).setTpId(srcTp).build());
263 } else if (destTp.contains(StringConstants.NETWORK_TOKEN)) {
264 // If the src and dest tp have network-token, then it is a regen
265 LOG.info("Create the regen-interfaces on the src-tp");
266 // Here we first create ODUCn interface for the Regen
267 String openRoadmOducn = this.openRoadmInterfaceFactory.createOpenRoadmOducn(nodeId,
269 createdOduInterfaces.add(openRoadmOducn);
270 transactionHistory.add(new DeviceInterface(nodeId, openRoadmOducn));
272 LOG.info("all src odu interfaces {}", createdOduInterfaces);
274 String openRoadmOdu4HOInterface = this.openRoadmInterfaceFactory
275 .createOpenRoadmOdu4HOInterface(nodeId, srcTp, false, apiInfoA, apiInfoZ, PT_07);
276 createdOduInterfaces.add(openRoadmOdu4HOInterface);
277 transactionHistory.add(new DeviceInterface(nodeId, openRoadmOdu4HOInterface));
280 if ((destTp != null) && destTp.contains(StringConstants.CLIENT_TOKEN)) {
281 LOG.info("Adding supporting EThernet interface for node {}, dest tp {}", nodeId, destTp);
283 // create OpenRoadm Xponder Client Interfaces
284 String openRoadmEthInterface = this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(
286 createdEthInterfaces.add(openRoadmEthInterface);
287 transactionHistory.add(new DeviceInterface(nodeId, openRoadmEthInterface));
289 if ((srcTp != null) && (srcTp.contains(StringConstants.TTP_TOKEN)
290 || srcTp.contains(StringConstants.PP_TOKEN))) {
291 LOG.info("Adding supporting OCH interface for node {}, src tp {}, spectrumInformation {}",
292 nodeId, srcTp, spectrumInformation);
293 List<String> openRoadmOchInterfaces = this.openRoadmInterfaceFactory
294 .createOpenRoadmOchInterfaces(nodeId, srcTp, spectrumInformation);
295 createdOchInterfaces.addAll(openRoadmOchInterfaces);
296 transactionHistory.addInterfaces(nodeId, openRoadmOchInterfaces);
298 if ((destTp != null) && (destTp.contains(StringConstants.TTP_TOKEN)
299 || destTp.contains(StringConstants.PP_TOKEN))) {
300 LOG.info("Adding supporting OCH interface for node {}, dest tp {}, spectrumInformation {}",
301 nodeId, destTp, spectrumInformation);
302 List<String> openRoadmOchInterfaces = this.openRoadmInterfaceFactory
303 .createOpenRoadmOchInterfaces(nodeId, destTp, spectrumInformation);
304 createdOchInterfaces.addAll(openRoadmOchInterfaces);
305 transactionHistory.addInterfaces(nodeId, openRoadmOchInterfaces);
307 if (crossConnectFlag < 1) {
308 LOG.info("Creating cross connect between source {} and destination {} for node {}", srcTp,
310 Optional<String> connectionNameOpt =
311 this.crossConnect.postCrossConnect(nodeId, srcTp, destTp, spectrumInformation);
312 if (connectionNameOpt.isPresent()) {
313 nodesProvisioned.add(nodeId);
314 String connectionName = connectionNameOpt.orElseThrow();
315 createdConnections.add(connectionName);
316 transactionHistory.add(new Connection(nodeId, connectionName, false));
318 processErrorMessage("Unable to post Roadm-connection for node " + nodeId, forkJoinPool,
324 processErrorMessage(nodeId + IS_NOT_MOUNTED_ON_THE_CONTROLLER, forkJoinPool, results);
327 } catch (OpenRoadmInterfaceException ex) {
328 processErrorMessage("Setup service path failed! Exception:" + ex.toString(), forkJoinPool, results);
331 NodeInterface nodeInterface = new NodeInterfaceBuilder()
332 .withKey(new NodeInterfaceKey(nodeId))
334 .setConnectionId(createdConnections)
335 .setEthInterfaceId(createdEthInterfaces)
336 .setOtuInterfaceId(createdOtuInterfaces)
337 .setOduInterfaceId(createdOduInterfaces)
338 .setOchInterfaceId(createdOchInterfaces)
340 nodeInterfaces.put(nodeInterface.key(),nodeInterface);
344 } catch (InterruptedException | ExecutionException e) {
345 LOG.error("Error while setting up service paths!", e);
347 forkJoinPool.shutdown();
350 results.add("Interfaces created successfully for nodes: " + String.join(", ", nodesProvisioned));
352 // setting topology in the service list data store
354 setTopologyForService(input.getServiceName(), topology.getTopology());
355 } catch (InterruptedException | TimeoutException | ExecutionException e) {
356 LOG.warn("Failed to write topologies for service {}.", input.getServiceName(), e);
358 if (!alarmSuppressionNodeRemoval(input.getServiceName())) {
359 LOG.error("Alarm suppression node removal failed!!!!");
361 return new ServicePathOutputBuilder()
362 .setNodeInterface(nodeInterfaces)
363 .setSuccess(success.get())
364 .setResult(String.join("\n", results))
365 .setLinkTp(otnLinkTps)
369 private ConcurrentLinkedQueue<String> processErrorMessage(String message, ForkJoinPool forkJoinPool,
370 ConcurrentLinkedQueue<String> messages) {
371 LOG.warn("Received error message {}", message);
372 messages.add(message);
373 forkJoinPool.shutdown();
377 @SuppressWarnings("rawtypes")
378 // FIXME check if the ForkJoinTask raw type can be avoided
379 // Raw types use are discouraged since they lack type safety.
380 // Resulting Problems are observed at run time and not at compile time
382 public ServicePathOutput deleteServicePath(ServicePathInput input) {
383 if (!alarmSuppressionNodeRegistration(input)) {
384 LOG.warn("Alarm suppression node registration failed!!!!");
386 List<Nodes> nodes = input.getNodes();
387 AtomicBoolean success = new AtomicBoolean(true);
388 ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
389 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
390 ForkJoinPool forkJoinPool = new ForkJoinPool();
391 ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
392 String nodeId = node.getNodeId();
393 LOG.info("Deleting service setup on node {}", nodeId);
394 if (node.getDestTp() == null) {
395 LOG.error("Destination termination point must not be null.");
398 if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
399 String result = nodeId + IS_NOT_MOUNTED_ON_THE_CONTROLLER;
403 forkJoinPool.shutdown();
405 //TODO should deletion end here?
407 // if the node is currently mounted then proceed.
409 String destTp = node.getDestTp();
411 if (node.getSrcTp() == null) {
412 otnLinkTps.add(new LinkTpBuilder()
417 srcTp = node.getSrcTp();
419 List<String> interfacesToDelete = new LinkedList<>();
420 interfacesToDelete.addAll(getInterfaces2delete(nodeId, srcTp, destTp,
421 input.getLowerSpectralSlotNumber().intValue(),
422 input.getHigherSpectralSlotNumber().intValue()));
423 for (String interfaceId : interfacesToDelete) {
425 this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
426 } catch (OpenRoadmInterfaceException e) {
427 String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
429 LOG.error(result, e);
436 } catch (InterruptedException | ExecutionException e) {
437 LOG.error("Error while deleting service paths!", e);
439 forkJoinPool.shutdown();
440 if (!alarmSuppressionNodeRemoval(input.getServiceName())) {
441 LOG.error("Alarm suppresion node removal failed!!!!");
443 return new ServicePathOutputBuilder()
444 .setSuccess(success.get())
445 .setLinkTp(otnLinkTps)
448 ? "Request processed"
449 : String.join("\n", results))
453 private List<String> getInterfaces2delete(
454 String nodeId, String srcTp, String destTp, int lowerSpectralSlotNumber, int higherSpectralSlotNumber) {
455 String spectralSlotName = String.join(GridConstant.SPECTRAL_SLOT_SEPARATOR,
456 String.valueOf(lowerSpectralSlotNumber),
457 String.valueOf(higherSpectralSlotNumber));
459 if (destTp.contains(StringConstants.NETWORK_TOKEN)
460 || srcTp.contains(StringConstants.CLIENT_TOKEN)
461 || srcTp.contains(StringConstants.NETWORK_TOKEN)
462 || destTp.contains(StringConstants.CLIENT_TOKEN)) {
463 return getInterfacesTodelete(nodeId, srcTp, destTp, spectralSlotName);
466 List<String> interfacesToDelete = new LinkedList<>();
467 String connectionNumber = String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, srcTp, destTp, spectralSlotName);
468 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, false);
469 for (String interf : intToDelete == null ? new ArrayList<String>() : intToDelete) {
470 if (!this.openRoadmInterfaceFactory.isUsedByXc(
471 nodeId, interf, connectionNumber, this.deviceTransactionManager)) {
472 interfacesToDelete.add(interf);
475 return interfacesToDelete;
478 private List<String> getInterfacesTodelete(String nodeId, String srcTp, String destTp, String spectralSlotName) {
480 OpenroadmNodeVersion nodeOpenRoadmVersion =
481 this.portMapping.getNode(nodeId).getNodeInfo().getOpenroadmVersion();
483 List<String> interfacesToDelete = new LinkedList<>();
484 Map<String, List<String>> suffixListMap =
485 nodeOpenRoadmVersion.equals(OpenroadmNodeVersion._71)
487 // We don't need ODUC2, ODUC3 here, since they are handled in OTN service-path
488 // This has to be in an order of deletion
489 "ODU", List.of("ODU4", "ODUFLEX", "ODUC4", "ODUC1"),
490 // Add intermediate OTUCn rates (OTUC2, OTUC3)
491 // OTU4 is used in 100G service on 7.1 model
492 "other", List.of("OTU4", "OTUC1", "OTUC2", "OTUC3", "OTUC4",
493 "OTSIGROUP-400G", "OTSIGROUP-300G", "OTSIGROUP-200G", "OTSIGROUP-100G",
496 "ODU", List.of("ODU", "ODU4"),
497 "other", List.of("OTU", spectralSlotName));
498 // this last suffix used to be retrieved from openRoadmInterfaceFactory.createOpenRoadmOchInterfaceName
499 // i.e. String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, destTp, spectralSlotName) with
500 // common GridConstant that states NAME_PARAMETERS_SEPARATOR = "-"
502 if (destTp.contains(StringConstants.NETWORK_TOKEN)) {
503 interfacesToDelete.addAll(inf2Del(destTp, suffixListMap, nodeId));
505 if (srcTp.contains(StringConstants.NETWORK_TOKEN)) {
506 // For a regen case, the srcTp can also contain the network-token
507 interfacesToDelete.addAll(inf2Del(srcTp, suffixListMap, nodeId));
509 if (srcTp.contains(StringConstants.CLIENT_TOKEN)) {
510 interfacesToDelete.add(String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, srcTp, "ETHERNET"));
512 if (destTp.contains(StringConstants.CLIENT_TOKEN)) {
513 interfacesToDelete.add(String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, destTp, "ETHERNET"));
515 return interfacesToDelete;
518 private List<String> inf2Del(String termPoint, Map<String, List<String>> suffixListMap, String nodeId) {
519 List<String> inf2Del = new LinkedList<>();
521 for (String suffix : suffixListMap.get("ODU")) {
522 if (this.openRoadmInterfaces.getInterface(
523 nodeId, String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, termPoint, suffix)).isPresent()) {
524 inf2Del.add(String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, termPoint, suffix));
528 catch (OpenRoadmInterfaceException e) {
529 LOG.error("impossible to get one of the interfaces {}",
530 termPoint + GridConstant.NAME_PARAMETERS_SEPARATOR + String.join(
531 " or " + termPoint + GridConstant.NAME_PARAMETERS_SEPARATOR,
532 suffixListMap.get("ODU")),
536 for (String suffix : suffixListMap.get("other")) {
537 if (this.openRoadmInterfaces.getInterface(
538 nodeId, String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, termPoint, suffix)).isPresent()) {
539 LOG.info("Deleting the interface {}",
540 String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, termPoint, suffix));
541 inf2Del.add(String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, termPoint, suffix));
545 catch (OpenRoadmInterfaceException e) {
546 LOG.error("impossible to get one of the interfaces {}",
547 termPoint + GridConstant.NAME_PARAMETERS_SEPARATOR + String.join(
548 " or " + termPoint + GridConstant.NAME_PARAMETERS_SEPARATOR,
549 suffixListMap.get("ODU")),
557 public RendererRollbackOutput rendererRollback(RendererRollbackInput input) {
558 boolean success = true;
559 Map<FailedToRollbackKey,FailedToRollback> failedToRollbackList = new HashMap<>();
560 for (NodeInterface nodeInterfaces : input.nonnullNodeInterface().values()) {
561 Set<String> failedInterfaces = new HashSet<>();
562 String nodeId = nodeInterfaces.getNodeId();
563 for (String connectionId : nodeInterfaces.getConnectionId()) {
564 List<String> listInter = this.crossConnect.deleteCrossConnect(nodeId, connectionId, false);
565 if (listInter != null) {
566 LOG.info("Cross connect {} on node {} successfully deleted.", connectionId, nodeId);
568 LOG.error("Failed to delete cross connect {} on node {}!", connectionId, nodeId);
570 failedInterfaces.add(connectionId);
573 // Interfaces needs to be in specific order to delete. Order is:
578 LinkedList<String> interfacesToDelete = new LinkedList<>();
579 if (nodeInterfaces.getOduInterfaceId() != null) {
580 interfacesToDelete.addAll(nodeInterfaces.getOduInterfaceId());
582 if (nodeInterfaces.getOtuInterfaceId() != null) {
583 interfacesToDelete.addAll(nodeInterfaces.getOtuInterfaceId());
585 if (nodeInterfaces.getOchInterfaceId() != null) {
586 interfacesToDelete.addAll(nodeInterfaces.getOchInterfaceId());
588 if (nodeInterfaces.getEthInterfaceId() != null) {
589 interfacesToDelete.addAll(nodeInterfaces.getEthInterfaceId());
591 LOG.info("Going to execute rollback on node {}. Interfaces to rollback: {}", nodeId,
592 String.join(", ", interfacesToDelete));
593 for (String interfaceId : interfacesToDelete) {
595 this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
596 LOG.info("Interface {} on node {} successfully deleted.", interfaceId, nodeId);
597 } catch (OpenRoadmInterfaceException e) {
598 LOG.error("Failed to delete interface {} on node {}!", interfaceId, nodeId);
600 failedInterfaces.add(interfaceId);
603 FailedToRollback failedToRollack = new FailedToRollbackBuilder().withKey(new FailedToRollbackKey(nodeId))
604 .setNodeId(nodeId).setInterface(failedInterfaces).build();
605 failedToRollbackList.put(failedToRollack.key(),failedToRollack);
607 return new RendererRollbackOutputBuilder()
609 .setFailedToRollback(failedToRollbackList)
614 public RendererRollbackOutput rendererRollback(History transactionHistory) {
615 LOG.info("Rolling back...");
617 Result rollbackResult = new FailedRollbackResult();
618 Subscriber deleteSubscriber = new DeleteSubscriber(rollbackResult);
620 transactionHistory.rollback(
628 LOG.info("Rollback done!");
630 return rollbackResult.renderRollbackOutput();
633 private boolean alarmSuppressionNodeRegistration(ServicePathInput input) {
634 Map<org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service
635 .nodelist.nodelist.NodesKey,
636 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102.service
637 .nodelist.nodelist.Nodes> nodeList = new HashMap<>();
638 if (input.getNodes() != null) {
639 for (Nodes node : input.getNodes()) {
640 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
641 .service.nodelist.nodelist.Nodes nodes =
642 new org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
643 .service.nodelist.nodelist.NodesBuilder().setNodeId(node.getNodeId()).build();
644 nodeList.put(nodes.key(),nodes);
647 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
648 .service.nodelist.Nodelist> nodeListIID =
649 InstanceIdentifier.create(ServiceNodelist.class)
650 .child(org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
651 .service.nodelist.Nodelist.class, new NodelistKey(input.getServiceName()));
652 final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction();
653 writeTransaction.merge(LogicalDatastoreType.CONFIGURATION,
655 new NodelistBuilder()
656 .withKey(new NodelistKey(input.getServiceName()))
657 .setServiceName(input.getServiceName())
660 FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
662 commit.get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
663 LOG.info("Nodes are register for alarm suppression for service: {}", input.getServiceName());
665 } catch (ExecutionException | InterruptedException | TimeoutException e) {
666 LOG.warn("Failed to alarm suppresslist for service: {}", input.getServiceName(), e);
671 private boolean alarmSuppressionNodeRemoval(String serviceName) {
672 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
673 .service.nodelist.Nodelist> nodeListIID =
674 InstanceIdentifier.create(ServiceNodelist.class)
675 .child(org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.alarmsuppression.rev171102
676 .service.nodelist.Nodelist.class, new NodelistKey(serviceName));
677 final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction();
678 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, nodeListIID);
679 FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
681 commit.get(Timeouts.DATASTORE_DELETE, TimeUnit.MILLISECONDS);
682 LOG.info("Nodes are unregister for alarm suppression for service: {}", serviceName);
684 } catch (InterruptedException | TimeoutException | ExecutionException e) {
685 LOG.warn("Failed to alarm suppresslist for service: {}", serviceName, e);
690 private void setTopologyForService(String name, Topology topo)
691 throws InterruptedException, ExecutionException, TimeoutException {
692 ServicesBuilder servicesBuilder;
693 // Get the service from the service list inventory
694 ServicesKey serviceKey = new ServicesKey(name);
695 InstanceIdentifier<Services> iid =
696 InstanceIdentifier.create(ServiceList.class).child(Services.class, serviceKey);
697 Optional<Services> services;
698 try (ReadTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
699 Future<java.util.Optional<Services>> future =
700 readTx.read(LogicalDatastoreType.OPERATIONAL, iid);
701 services = future.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
702 } catch (InterruptedException | ExecutionException | TimeoutException e) {
705 if (services.isPresent()) {
706 LOG.info("service {} already exists", name);
707 servicesBuilder = new ServicesBuilder(services.orElseThrow()).setTopology(topo);
708 WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction();
709 writeTx.merge(LogicalDatastoreType.OPERATIONAL, iid, servicesBuilder.build());
710 writeTx.commit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
712 LOG.warn("Service {} does not exist - topology can not be updated", name);
717 value = "SLF4J_FORMAT_SHOULD_BE_CONST",
718 justification = "Log messages content needs to be formatted before"
719 + "since they are used in the returned object")
721 public CreateOtsOmsOutput createOtsOms(CreateOtsOmsInput input) throws OpenRoadmInterfaceException {
722 if (!this.deviceTransactionManager.isDeviceMounted(input.getNodeId())) {
723 String result = input.getNodeId() + IS_NOT_MOUNTED_ON_THE_CONTROLLER;
725 return new CreateOtsOmsOutputBuilder().setResult(result).setSuccess(false).build();
727 // if the node is currently mounted then proceed.
728 Mapping oldMapping = this.portMapping.getMapping(input.getNodeId(), input.getLogicalConnectionPoint());
729 if (oldMapping == null) {
730 return new CreateOtsOmsOutputBuilder()
731 .setResult(String.format("Logical Connection point %s does not exist for %s",
732 input.getLogicalConnectionPoint(), input.getNodeId()))
737 String otsInterface = this.openRoadmInterfaceFactory.createOpenRoadmOtsInterface(input.getNodeId(), oldMapping);
739 Mapping newMapping = this.portMapping.getMapping(input.getNodeId(), input.getLogicalConnectionPoint());
740 while (!isSupportingOtsPresent(newMapping)) {
741 LOG.info("waiting for post interface operation on node '{}'...", input.getNodeId());
744 this.portMapping.updateMapping(input.getNodeId(), oldMapping);
745 } catch (InterruptedException e) {
746 LOG.error("Failed to wait for post interface operation");
750 String result = String.format("Unable to get ots interface from mapping %s - %s",
751 oldMapping.getLogicalConnectionPoint(), input.getNodeId());
753 return new CreateOtsOmsOutputBuilder().setResult(result).setSuccess(false).build();
755 newMapping = this.portMapping.getMapping(input.getNodeId(), input.getLogicalConnectionPoint());
758 String omsInterface = this.openRoadmInterfaceFactory.createOpenRoadmOmsInterface(input.getNodeId(), newMapping);
759 if (omsInterface == null) {
760 String result = String.format("Fail to create OpenRoadmOms Interface for node : %s", input.getNodeId());
762 return new CreateOtsOmsOutputBuilder().setResult(result).setSuccess(false).build();
764 return new CreateOtsOmsOutputBuilder()
765 .setResult(String.format("Interfaces %s - %s successfully created on node %s",
766 otsInterface, omsInterface, input.getNodeId()))
771 private Boolean isSupportingOtsPresent(Mapping mapping) {
772 if (mapping == null) {
775 if (mapping.getSupportingOts() == null) {
776 LOG.warn("SupportingOts info is not present in mapping {}", mapping);
779 LOG.info("SupportingOts info is present in mapping {}", mapping);