a5e21db96da64b626a41b62e892df25121e0c964
[transportpce.git] / renderer / src / main / java / org / opendaylight / transportpce / renderer / provisiondevice / OtnDeviceRendererServiceImpl.java
1 /*
2  * Copyright © 2019 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 java.util.ArrayList;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.Optional;
14 import java.util.concurrent.ConcurrentLinkedQueue;
15 import java.util.concurrent.CopyOnWriteArrayList;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.ForkJoinPool;
18 import java.util.concurrent.ForkJoinTask;
19 import java.util.concurrent.atomic.AtomicBoolean;
20 import java.util.stream.Collectors;
21 import org.opendaylight.transportpce.common.crossconnect.CrossConnect;
22 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
23 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
24 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
25 import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
26 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.OtnServicePathInput;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.OtnServicePathOutput;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.OtnServicePathOutputBuilder;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.interfaces.grp.Interface;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.node.interfaces.NodeInterface;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.node.interfaces.NodeInterfaceBuilder;
33 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.node.interfaces.NodeInterfaceKey;
34 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200615.otn.renderer.input.Nodes;
35 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev200129.OtnLinkType;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39
40 public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService {
41     private static final Logger LOG = LoggerFactory.getLogger(OtnDeviceRendererServiceImpl.class);
42     private static final String PT_03 = "03";
43     private static final String PT_07 = "07";
44     private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
45     private final CrossConnect crossConnect;
46     private final OpenRoadmInterfaces openRoadmInterfaces;
47     private final DeviceTransactionManager deviceTransactionManager;
48     private final NetworkModelService networkModelService;
49
50     public OtnDeviceRendererServiceImpl(OpenRoadmInterfaceFactory openRoadmInterfaceFactory, CrossConnect crossConnect,
51                                         OpenRoadmInterfaces openRoadmInterfaces,
52                                         DeviceTransactionManager deviceTransactionManager,
53                                         NetworkModelService networkModelService) {
54         this.openRoadmInterfaceFactory = openRoadmInterfaceFactory;
55         this.crossConnect = crossConnect;
56         this.openRoadmInterfaces = openRoadmInterfaces;
57         this.deviceTransactionManager = deviceTransactionManager;
58         this.networkModelService = networkModelService;
59     }
60
61     @Override
62     public OtnServicePathOutput setupOtnServicePath(OtnServicePathInput input) {
63         LOG.info("Calling setup otn-service path");
64         boolean success = true;
65         List<NodeInterface> nodeInterfaces = new ArrayList<>();
66         List<String> results = new ArrayList<>();
67         if (input.getServiceType() == null || input.getServiceRate() == null) {
68             OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder()
69                 .setSuccess(false)
70                 .setResult("Error - service-type and service-rate must be presents");
71             return otnServicePathOutputBuilder.build();
72         }
73         CopyOnWriteArrayList<Nodes> otnNodesProvisioned = new CopyOnWriteArrayList<>();
74         switch (input.getServiceType()) {
75             case "Ethernet":
76                 if ("10G".equals(input.getServiceRate()) || "1G".equals(input.getServiceRate())) {
77                     try {
78                         LOG.info("Calling Node interfaces {} {} {} {} {} {} {}",
79                             input.getServiceRate(), input.getEthernetEncoding(),
80                             input.getServiceType(), input.getOperation(), input.getTribPortNumber(),
81                             input.getTribSlot(), input.getNodes());
82                         nodeInterfaces = createInterface(input);
83                         LOG.info("Node interfaces created just fine ");
84
85                         List<String> nodesToUpdate = new ArrayList<>();
86                         if (!nodeInterfaces.isEmpty()) {
87                             for (NodeInterface nodeInterf : nodeInterfaces) {
88                                 if (nodeInterf.getOduInterfaceId() != null) {
89                                     List<String> interList = nodeInterf.getOduInterfaceId().stream()
90                                         .filter(id -> id.contains("NETWORK")).collect(Collectors.toList());
91                                     if (!interList.isEmpty()) {
92                                         for (String inter : interList) {
93                                             String tp = inter.split("-ODU")[0];
94                                             String nodeTopo = nodeInterf.getNodeId() + "-" + tp.split("-")[0];
95                                             nodesToUpdate.add(nodeTopo + "--" + tp);
96                                         }
97                                     }
98                                 }
99                             }
100                         }
101                         updateOtnTopology(null, nodesToUpdate, input.getServiceRate(), input.getTribPortNumber(),
102                             input.getTribSlot(), false);
103                     } catch (OpenRoadmInterfaceException e) {
104                         LOG.warn("Set up service path failed", e);
105                         success = false;
106                     }
107                 } else {
108                     LOG.warn("Unsupported service-rate for service-type Ethernet");
109                 }
110                 break;
111             case "ODU":
112                 if ("100G".equals(input.getServiceRate())) {
113                     try {
114                         createODU4TtpInterface(input, nodeInterfaces, otnNodesProvisioned);
115                         updateOtnTopology(otnNodesProvisioned, null, null, null, null, false);
116                     } catch (OpenRoadmInterfaceException e) {
117                         LOG.warn("Set up service path failed", e);
118                         success = false;
119                     }
120                 } else {
121                     LOG.warn("Unsupported service-rate for service-type ODU");
122                 }
123                 break;
124             default:
125                 LOG.error("service-type {} not managed yet", input.getServiceType());
126                 break;
127         }
128         if (success) {
129             LOG.info("Result is success");
130             for (NodeInterface nodeInterface : nodeInterfaces) {
131                 results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId());
132             }
133         }
134         OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder()
135                 .setSuccess(success)
136                 .setNodeInterface(nodeInterfaces)
137                 .setResult(String.join("\n", results));
138         return otnServicePathOutputBuilder.build();
139     }
140
141     public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) {
142         if (input == null) {
143             LOG.error("Unable to delete otn service path. input = null");
144             return new OtnServicePathOutputBuilder().setResult("Unable to delete otn service path. input = null")
145                 .setSuccess(false).build();
146         }
147         List<Nodes> nodes = input.getNodes();
148         AtomicBoolean success = new AtomicBoolean(true);
149         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
150         List<String> nodesTpToUpdate = new ArrayList<>();
151         CopyOnWriteArrayList<Nodes> otnNodesProvisioned = new CopyOnWriteArrayList<>();
152         ForkJoinPool forkJoinPool = new ForkJoinPool();
153         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
154             List<String> interfacesToDelete = new LinkedList<>();
155             String nodeId = node.getNodeId();
156             LOG.info("Deleting service setup on node {}", nodeId);
157             String networkTp = node.getNetworkTp();
158             if (networkTp == null || input.getServiceRate() == null || input.getServiceType() == null) {
159                 LOG.error("destination ({}) or service rate ({}) or service type ({}) is null.", networkTp,
160                     input.getServiceRate(), input.getServiceType());
161                 return;
162             }
163             // if the node is currently mounted then proceed.
164             if (this.deviceTransactionManager.isDeviceMounted(nodeId)) {
165                 String connectionNumber = "";
166                 switch (input.getServiceRate()) {
167                     case ("100G"):
168                         if ("ODU".equals(input.getServiceType())) {
169                             interfacesToDelete.add(networkTp + "-ODU4");
170                             otnNodesProvisioned.add(node);
171                             if (node.getNetwork2Tp() != null) {
172                                 interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
173                             }
174                         }
175                         break;
176                     case ("10G"):
177                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
178                         break;
179                     case ("1G"):
180                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
181                         break;
182                     default:
183                         LOG.error("service rate {} not managed yet", input.getServiceRate());
184                         String result = input.getServiceRate() + " is not supported";
185                         results.add(result);
186                         success.set(false);
187                         return;
188                 }
189                 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
190                 if (intToDelete != null) {
191                     for (String interf : intToDelete) {
192                         if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
193                             this.deviceTransactionManager)) {
194                             interfacesToDelete.add(interf);
195                             if (!getSupportedInterface(nodeId, interf).contains("ODU4")) {
196                                 interfacesToDelete.add(getSupportedInterface(nodeId, interf));
197                             }
198                         }
199                     }
200                 }
201             } else {
202                 String result = nodeId + " is not mounted on the controller";
203                 results.add(result);
204                 success.set(false);
205                 LOG.warn(result);
206                 forkJoinPool.shutdown();
207                 return;
208                 // TODO should deletion end here?
209             }
210             for (String interfaceId : interfacesToDelete) {
211                 try {
212                     this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
213                 } catch (OpenRoadmInterfaceException e) {
214                     String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
215                     success.set(false);
216                     LOG.error(result, e);
217                     results.add(result);
218                 }
219             }
220             List<String> interList = interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK"))
221                 .collect(Collectors.toList());
222             if (!interList.isEmpty()) {
223                 for (String inter : interList) {
224                     String tp = inter.split("-ODU")[0];
225                     String nodeTopo = nodeId + "-" + tp.split("-")[0];
226                     nodesTpToUpdate.add(nodeTopo + "--" + tp);
227                 }
228             }
229         }));
230         try {
231             forkJoinTask.get();
232         } catch (InterruptedException | ExecutionException e) {
233             LOG.error("Error while deleting service paths!", e);
234         }
235         forkJoinPool.shutdown();
236         LOG.info("requesting otn-topology update...");
237         if (!nodesTpToUpdate.isEmpty() && !"ODU".equals(input.getServiceType())) {
238             updateOtnTopology(null, nodesTpToUpdate, input.getServiceRate(), input.getTribPortNumber(),
239                 input.getTribSlot(), true);
240         } else if (!otnNodesProvisioned.isEmpty()) {
241             updateOtnTopology(otnNodesProvisioned, null, null, null, null, true);
242         }
243
244         OtnServicePathOutputBuilder delServBldr = new OtnServicePathOutputBuilder();
245         delServBldr.setSuccess(success.get());
246         if (results.isEmpty()) {
247             return delServBldr.setResult("Request processed").build();
248         } else {
249             return delServBldr.setResult(String.join("\n", results)).build();
250         }
251     }
252
253     private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
254         if (node.getClientTp() != null) {
255             return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName);
256         } else if (node.getNetwork2Tp() != null) {
257             return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName);
258         } else {
259             return "";
260         }
261     }
262
263     private String getSupportedInterface(String nodeId, String interf) {
264         Optional<Interface> supInterfOpt;
265         try {
266             supInterfOpt = this.openRoadmInterfaces.getInterface(nodeId, interf);
267             if (supInterfOpt.isPresent()) {
268                 return supInterfOpt.get().getSupportingInterface();
269             } else {
270                 return null;
271             }
272         } catch (OpenRoadmInterfaceException e) {
273             LOG.error("error getting Supported Interface of {} - {}", interf, nodeId, e);
274             return null;
275         }
276     }
277
278     private List<NodeInterface> createInterface(OtnServicePathInput input) throws OpenRoadmInterfaceException {
279         List<NodeInterface> nodeInterfaces = new ArrayList<>();
280         LOG.info("Calling Create Interface entry for OTN service path");
281         if (input.getServiceRate() == null
282             || !("1G".equals(input.getServiceRate()) || "10G".equals(input.getServiceRate()))) {
283             LOG.error("Service rate {} not managed yet", input.getServiceRate());
284         } else {
285             createLowOrderInterfaces(input, nodeInterfaces);
286         }
287         return nodeInterfaces;
288     }
289
290     private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
291             throws OpenRoadmInterfaceException {
292         return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
293     }
294
295     private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces)
296         throws OpenRoadmInterfaceException {
297         for (Nodes node : input.getNodes()) {
298             // check if the node is mounted or not?
299             List<String> createdEthInterfaces = new ArrayList<>();
300             List<String> createdOduInterfaces = new ArrayList<>();
301             switch (input.getServiceRate()) {
302                 case ("1G"):
303                     LOG.info("Input service is 1G");
304                     if (node.getClientTp() != null) {
305                         createdEthInterfaces.add(
306                             openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
307                                 node.getClientTp()));
308                         createdOduInterfaces.add(
309                             // suppporting interface?, payload ?
310                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
311                                 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
312                     }
313                     createdOduInterfaces.add(
314                         openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
315                             input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
316                     if (node.getNetwork2Tp() != null) {
317                         createdOduInterfaces.add(
318                             // supporting interface? payload ?
319                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
320                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
321                                 input.getTribSlot()));
322                     }
323                     break;
324                 case ("10G"):
325                     LOG.info("Input service is 10G");
326                     if (node.getClientTp() != null) {
327                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
328                             node.getNodeId(), node.getClientTp()));
329                         createdOduInterfaces.add(
330                             // suppporting interface?, payload ?
331                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
332                                 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
333                                 input.getTribSlot()));
334                     }
335                     createdOduInterfaces.add(
336                         // supporting interface? payload ?
337                         openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
338                             input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
339                     if (node.getNetwork2Tp() != null) {
340                         createdOduInterfaces.add(
341                             // supporting interface? payload ?
342                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
343                                 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
344                                 input.getTribSlot()));
345                     }
346                     break;
347                 default:
348                     LOG.error("service rate {} not managed yet", input.getServiceRate());
349                     return;
350             }
351
352             // implement cross connect
353             List<String> createdConnections = new ArrayList<>();
354             if (!createdOduInterfaces.isEmpty()) {
355                 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
356                 createdConnections.add(connectionNameOpt.get());
357                 LOG.info("Created cross connects");
358             }
359             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
360                 .withKey(new NodeInterfaceKey(node.getNodeId()))
361                 .setNodeId(node.getNodeId())
362                 .setConnectionId(createdConnections)
363                 .setEthInterfaceId(createdEthInterfaces)
364                 .setOduInterfaceId(createdOduInterfaces);
365             nodeInterfaces.add(nodeInterfaceBuilder.build());
366         }
367     }
368
369     private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
370         CopyOnWriteArrayList<Nodes> otnNodesProvisioned) throws OpenRoadmInterfaceException {
371
372         for (int i = 0; i < input.getNodes().size(); i++) {
373             Nodes node = input.getNodes().get(i);
374             String supportingOtuInterface = node.getNetworkTp() + "-OTU";
375             List<String> createdOdu4Interfaces = new ArrayList<>();
376             // Adding SAPI/DAPI information to the
377             Nodes tgtNode = null;
378             if (i + 1 == input.getNodes().size()) {
379                 // For the end node, tgtNode becomes the first node in the list
380                 tgtNode = input.getNodes().get(0);
381             } else {
382                 tgtNode = input.getNodes().get(i + 1);
383             }
384             createdOdu4Interfaces.add(openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
385                 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp()));
386             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
387                 .withKey(new NodeInterfaceKey(node.getNodeId()))
388                 .setNodeId(node.getNodeId())
389                 .setOduInterfaceId(createdOdu4Interfaces);
390             nodeInterfaces.add(nodeInterfaceBuilder.build());
391             otnNodesProvisioned.add(node);
392         }
393     }
394
395     private void updateOtnTopology(CopyOnWriteArrayList<Nodes> nodes, List<String> nodesTps, String serviceRate,
396         Short tribPortNb, Short tribSlotNb, boolean isDeletion) {
397         if (nodes != null && nodes.size() == 2) {
398             if (isDeletion) {
399                 LOG.info("updating otn-topology removing ODU4 links");
400                 this.networkModelService.deleteOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(),
401                     nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4);
402             } else {
403                 LOG.info("updating otn-topology adding ODU4 links");
404                 this.networkModelService.createOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(),
405                     nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4);
406             }
407         } else if (nodesTps != null && (nodesTps.size() % 2 == 0) && serviceRate != null && tribPortNb != null
408             && tribSlotNb != null) {
409             LOG.info("updating otn-topology node tps -tps and tpn pools");
410             this.networkModelService.updateOtnLinks(nodesTps, serviceRate, tribPortNb, tribSlotNb, isDeletion);
411         }
412     }
413
414 }