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