69266d599ce43a40a40c2f6aa22ce685a410920a
[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.StringConstants;
24 import org.opendaylight.transportpce.common.crossconnect.CrossConnect;
25 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
26 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
27 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
28 import org.opendaylight.transportpce.common.service.ServiceTypes;
29 import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
30 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathInput;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathOutput;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathOutputBuilder;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OpucnTribSlotDef;
35 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
36 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTpBuilder;
37 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.node.interfaces.NodeInterface;
38 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.node.interfaces.NodeInterfaceBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.node.interfaces.NodeInterfaceKey;
40 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.otn.renderer.nodes.Nodes;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44
45 public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService {
46     private static final Logger LOG = LoggerFactory.getLogger(OtnDeviceRendererServiceImpl.class);
47     private static final String PT_03 = "03";
48     private static final String PT_07 = "07";
49     private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
50     private final CrossConnect crossConnect;
51     private final OpenRoadmInterfaces openRoadmInterfaces;
52     private final DeviceTransactionManager deviceTransactionManager;
53     private final NetworkModelService networkModelService;
54
55     public OtnDeviceRendererServiceImpl(OpenRoadmInterfaceFactory openRoadmInterfaceFactory, CrossConnect crossConnect,
56                                         OpenRoadmInterfaces openRoadmInterfaces,
57                                         DeviceTransactionManager deviceTransactionManager,
58                                         NetworkModelService networkModelService) {
59         this.openRoadmInterfaceFactory = openRoadmInterfaceFactory;
60         this.crossConnect = crossConnect;
61         this.openRoadmInterfaces = openRoadmInterfaces;
62         this.deviceTransactionManager = deviceTransactionManager;
63         this.networkModelService = networkModelService;
64     }
65
66 //TODO Align log messages and returned results messages
67     @Override
68     public OtnServicePathOutput setupOtnServicePath(OtnServicePathInput input) {
69         LOG.info("Calling setup otn-service path");
70         if (input.getServiceFormat() == null || input.getServiceRate() == null) {
71             return new OtnServicePathOutputBuilder()
72                 .setSuccess(false)
73                 .setResult("Error - service-type and service-rate must be present")
74                 .build();
75         }
76         List<NodeInterface> nodeInterfaces = new ArrayList<>();
77         CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
78         String serviceType = ServiceTypes.getOtnServiceType(input.getServiceFormat(), input.getServiceRate());
79         try {
80             switch (serviceType) {
81                 case StringConstants.SERVICE_TYPE_1GE:
82                 case StringConstants.SERVICE_TYPE_10GE:
83                 case StringConstants.SERVICE_TYPE_100GE_M:
84                     LOG.info("Calling Node interfaces {} {} {} {} {} {} {}",
85                         input.getServiceRate(), input.getEthernetEncoding(),
86                         input.getServiceFormat(), input.getOperation(), input.getTribPortNumber(),
87                         input.getTribSlot(), input.getNodes());
88                     if (input.getNodes() != null) {
89                         createLowOrderInterfaces(input, nodeInterfaces, otnLinkTps);
90                         LOG.info("Node interfaces created just fine ");
91                     }
92                     break;
93                 case StringConstants.SERVICE_TYPE_ODU4:
94                     createODU4TtpInterface(input, nodeInterfaces, otnLinkTps);
95                     break;
96                 case StringConstants.SERVICE_TYPE_ODUC4:
97                     createOduc4TtpInterface(input, nodeInterfaces, otnLinkTps);
98                     break;
99                 default:
100                     LOG.error("Service-type {} not managed yet", serviceType);
101                     return new OtnServicePathOutputBuilder()
102                         .setSuccess(false)
103                         .setResult("Service-type not managed")
104                         .build();
105             }
106         } catch (OpenRoadmInterfaceException e) {
107             LOG.warn("Service path set-up failed", e);
108             Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
109             for (NodeInterface nodeInterface : nodeInterfaces) {
110                 if (nodeInterface != null) {
111                     nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
112                 }
113             }
114             //TODO check if we need to set a NodeInterface Map in the result in that case
115             return new OtnServicePathOutputBuilder()
116                     .setSuccess(false)
117                     .setNodeInterface(nodeInterfacesMap)
118                     .setResult("Service path set-up failed")
119                     .setLinkTp(otnLinkTps)
120                     .build();
121         }
122         LOG.info("Service path set-up succeed");
123         List<String> results = new ArrayList<>();
124         Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
125         for (NodeInterface nodeInterface : nodeInterfaces) {
126             if (nodeInterface != null) {
127                 results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId());
128                 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
129             }
130         }
131         return new OtnServicePathOutputBuilder()
132                 .setSuccess(true)
133                 .setNodeInterface(nodeInterfacesMap)
134                 .setResult(String.join("\n", results))
135                 .setLinkTp(otnLinkTps)
136                 .build();
137     }
138
139     @SuppressWarnings("rawtypes")
140     // FIXME check if the ForkJoinTask raw type can be avoided
141     // Raw types use are discouraged since they lack type safety.
142     // Resulting Problems are observed at run time and not at compile time
143     public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) {
144         if (input.getNodes() == null) {
145             LOG.error("Unable to delete otn service path. input nodes = null");
146             return new OtnServicePathOutputBuilder()
147                 .setResult("Unable to delete otn service path. input nodes = null")
148                 .setSuccess(false)
149                 .build();
150         }
151         List<Nodes> nodes = input.getNodes();
152         AtomicBoolean success = new AtomicBoolean(true);
153         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
154         CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
155         ForkJoinPool forkJoinPool = new ForkJoinPool();
156         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
157             String nodeId = node.getNodeId();
158             LOG.info("Deleting service setup on node {}", nodeId);
159             String networkTp = node.getNetworkTp();
160             if (networkTp == null || input.getServiceRate() == null || input.getServiceFormat() == null) {
161                 LOG.error("destination ({}) or service-rate ({}) or service-format ({}) is null.",
162                     networkTp, input.getServiceRate(), input.getServiceFormat());
163                 return;
164             }
165             if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
166                 String result = nodeId + " is not mounted on the controller";
167                 results.add(result);
168                 success.set(false);
169                 LOG.warn(result);
170                 forkJoinPool.shutdown();
171                 return;
172                 // TODO should deletion end here?
173             }
174             // if the node is currently mounted then proceed.
175             List<String> interfacesToDelete = new LinkedList<>();
176             String connectionNumber = "";
177             switch (input.getServiceRate().intValue()) {
178                 case 100:
179                     if ("ODU".equals(input.getServiceFormat())) {
180                         interfacesToDelete.add(networkTp + "-ODU4");
181                         if (node.getNetwork2Tp() != null) {
182                             interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
183                         }
184                     } else if ("Ethernet".equals(input.getServiceFormat())) {
185                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU4");
186                     }
187                     break;
188                 case 400:
189                     if ("ODU".equals(input.getServiceFormat())) {
190                         interfacesToDelete.add(networkTp + "-ODUC4");
191                         if (node.getNetwork2Tp() != null) {
192                             interfacesToDelete.add(node.getNetwork2Tp() + "-ODUC4");
193                         }
194                     }
195                     break;
196                 case 10:
197                     connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
198                     break;
199                 case 1:
200                     connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
201                     break;
202                 default:
203                     LOG.error("service rate {} not managed yet", input.getServiceRate());
204                     String result = input.getServiceRate() + " is not supported";
205                     results.add(result);
206                     success.set(false);
207                     return;
208             }
209             List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
210             for (String interf : intToDelete == null ? new ArrayList<String>() : intToDelete) {
211                 if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
212                         this.deviceTransactionManager)) {
213                     interfacesToDelete.add(interf);
214                     String supportedInterface = this.openRoadmInterfaces.getSupportedInterface(nodeId, interf);
215                     if (input.getServiceRate().intValue() == 100) {
216                         if (!supportedInterface.contains("ODUC4")) {
217                             interfacesToDelete.add(supportedInterface);
218                         }
219                     } else {
220                         if (!supportedInterface.contains("ODU4")) {
221                             interfacesToDelete.add(supportedInterface);
222                         }
223                     }
224                 }
225             }
226
227             for (String interfaceId : interfacesToDelete) {
228                 try {
229                     this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
230                 } catch (OpenRoadmInterfaceException e) {
231                     String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
232                     success.set(false);
233                     LOG.error(result, e);
234                     results.add(result);
235                 }
236             }
237             List<String> interList =
238                     interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK")).collect(Collectors.toList());
239             if (!interList.isEmpty()) {
240                 for (String inter : interList) {
241                     otnLinkTps.add(new LinkTpBuilder()
242                             .setNodeId(nodeId)
243                             .setTpId(inter.split("-ODU")[0])
244                             .build());
245                 }
246             }
247         }));
248         try {
249             forkJoinTask.get();
250         } catch (InterruptedException | ExecutionException e) {
251             LOG.error("Error while deleting service paths!", e);
252             return new OtnServicePathOutputBuilder()
253                 .setResult("Error while deleting service paths!")
254                 .setSuccess(false)
255                 .build();
256         }
257         forkJoinPool.shutdown();
258         return new OtnServicePathOutputBuilder()
259                 .setSuccess(success.get())
260                 .setLinkTp(otnLinkTps)
261                 .setResult(
262                     results.isEmpty()
263                         ? "Request processed"
264                         : String.join("\n", results))
265                 .build();
266     }
267
268     private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
269         if (node.getClientTp() != null) {
270             return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName);
271         } else if (node.getNetwork2Tp() != null) {
272             return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName);
273         } else {
274             return "";
275         }
276     }
277
278     private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
279             throws OpenRoadmInterfaceException {
280         return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
281     }
282
283     private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
284             CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
285         for (Nodes node : input.getNodes()) {
286             // check if the node is mounted or not?
287             List<String> createdEthInterfaces = new ArrayList<>();
288             List<String> createdOduInterfaces = new ArrayList<>();
289             switch (input.getServiceRate().intValue()) {
290                 case 1:
291                     LOG.info("Input service is 1G");
292                     if (node.getClientTp() != null) {
293                         createdEthInterfaces.add(
294                             openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
295                                 node.getClientTp()));
296                         createdOduInterfaces.add(
297                             // suppporting interface?, payload ?
298                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
299                                 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
300                     }
301                     createdOduInterfaces.add(
302                         openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
303                             input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
304                     linkTpList.add(
305                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
306                     if (node.getNetwork2Tp() != null) {
307                         createdOduInterfaces.add(
308                             // supporting interface? payload ?
309                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
310                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
311                                 input.getTribSlot()));
312                         linkTpList.add(
313                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
314                     }
315                     break;
316                 case 10:
317                     LOG.info("Input service is 10G");
318                     if (node.getClientTp() != null) {
319                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
320                             node.getNodeId(), node.getClientTp()));
321                         createdOduInterfaces.add(
322                             // suppporting interface?, payload ?
323                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
324                                 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
325                                 input.getTribSlot()));
326                     }
327                     createdOduInterfaces.add(
328                         // supporting interface? payload ?
329                         openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
330                             input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
331                     linkTpList.add(
332                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
333                     if (node.getNetwork2Tp() != null) {
334                         createdOduInterfaces.add(
335                             // supporting interface? payload ?
336                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
337                                 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
338                                 input.getTribSlot()));
339                         linkTpList.add(
340                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
341                     }
342                     break;
343                 case 100:
344                     LOG.info("Input service is 100G");
345                     // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
346                     // min and max value only, size two)
347                     OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
348                         input.getOpucnTribSlots().get(0).getValue());
349                     OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
350                         input.getOpucnTribSlots().get(1).getValue());
351                     if (node.getClientTp() != null) {
352                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
353                             node.getNodeId(), node.getClientTp()));
354                         // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
355                         createdOduInterfaces.add(
356                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
357                             node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
358                                 maxOpucnTs));
359                     }
360                     // Here payload-type is optional and is not used for interface creation (especially for network)
361                     createdOduInterfaces.add(
362                         openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
363                             node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
364                             maxOpucnTs));
365                     linkTpList.add(
366                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
367                     // Here payload-type is optional and is not used for service creation
368                     // This is needed if there is an intermediate node
369                     if (node.getNetwork2Tp() != null) {
370                         createdOduInterfaces.add(
371                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
372                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
373                                 maxOpucnTs));
374                         linkTpList.add(
375                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
376                     }
377                     break;
378                 default:
379                     LOG.error("service rate {} not managed yet", input.getServiceRate());
380                     return;
381             }
382
383             // implement cross connect
384             List<String> createdConnections = new ArrayList<>();
385             if (!createdOduInterfaces.isEmpty()) {
386                 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
387                 createdConnections.add(connectionNameOpt.get());
388                 LOG.info("Created cross connects");
389             }
390             nodeInterfaces.add(new NodeInterfaceBuilder()
391                     .withKey(new NodeInterfaceKey(node.getNodeId()))
392                     .setNodeId(node.getNodeId())
393                     .setConnectionId(createdConnections)
394                     .setEthInterfaceId(createdEthInterfaces)
395                     .setOduInterfaceId(createdOduInterfaces)
396                     .build());
397         }
398     }
399
400     private void createOduc4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
401         CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
402         if (input.getNodes() == null) {
403             return;
404         }
405         LOG.info("Creation of ODUC4 TTP interface in OTN service path {}", input);
406         for (int i = 0; i < input.getNodes().size(); i++) {
407             Nodes node = input.getNodes().get(i);
408             String supportingOtuInterface = node.getNetworkTp() + "-OTUC4";
409
410             Nodes tgtNode =
411                 i + 1 == input.getNodes().size()
412                 // For the end node, tgtNode becomes the first node in the list
413                     ? input.getNodes().get(0)
414                     : input.getNodes().get(i + 1);
415
416             nodeInterfaces.add(new NodeInterfaceBuilder()
417                     .withKey(new NodeInterfaceKey(node.getNodeId()))
418                     .setNodeId(node.getNodeId())
419                     .setOduInterfaceId(List.of(
420                         // though this is odu, actually it has ODUC4 interfaces
421                         openRoadmInterfaceFactory.createOpenRoadmOtnOduc4Interface(node.getNodeId(),
422                             node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
423                     .build());
424             linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
425         }
426     }
427
428     private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
429         CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
430         if (input.getNodes() == null) {
431             return;
432         }
433         LOG.info("Creation of ODU4 tp interface {}", input);
434         for (int i = 0; i < input.getNodes().size(); i++) {
435             Nodes node = input.getNodes().get(i);
436             String supportingOtuInterface = node.getNetworkTp() + "-OTU";
437
438             Nodes tgtNode =
439                 i + 1 == input.getNodes().size()
440                 // For the end node, tgtNode becomes the first node in the list
441                     ? input.getNodes().get(0)
442                     : input.getNodes().get(i + 1);
443
444             nodeInterfaces.add(new NodeInterfaceBuilder()
445                     .withKey(new NodeInterfaceKey(node.getNodeId()))
446                     .setNodeId(node.getNodeId())
447                     .setOduInterfaceId(List.of(
448                         openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
449                             node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
450                     .build());
451             linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
452         }
453     }
454 }