241ea4cb72708e9074343dbc7d1a854e5697b049
[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     public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) {
140         if (input.getNodes() == null) {
141             LOG.error("Unable to delete otn service path. input nodes = null");
142             return new OtnServicePathOutputBuilder()
143                 .setResult("Unable to delete otn service path. input nodes = null")
144                 .setSuccess(false)
145                 .build();
146         }
147         List<Nodes> nodes = input.getNodes();
148         AtomicBoolean success = new AtomicBoolean(true);
149         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
150         CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
151         ForkJoinPool forkJoinPool = new ForkJoinPool();
152         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
153             String nodeId = node.getNodeId();
154             LOG.info("Deleting service setup on node {}", nodeId);
155             String networkTp = node.getNetworkTp();
156             if (networkTp == null || input.getServiceRate() == null || input.getServiceFormat() == null) {
157                 LOG.error("destination ({}) or service-rate ({}) or service-format ({}) is null.",
158                     networkTp, input.getServiceRate(), input.getServiceFormat());
159                 return;
160             }
161             if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
162                 String result = nodeId + " is not mounted on the controller";
163                 results.add(result);
164                 success.set(false);
165                 LOG.warn(result);
166                 forkJoinPool.shutdown();
167                 return;
168                 // TODO should deletion end here?
169             }
170             // if the node is currently mounted then proceed.
171             List<String> interfacesToDelete = new LinkedList<>();
172             String connectionNumber = "";
173             switch (input.getServiceRate().intValue()) {
174                 case 100:
175                     if ("ODU".equals(input.getServiceFormat())) {
176                         interfacesToDelete.add(networkTp + "-ODU4");
177                         if (node.getNetwork2Tp() != null) {
178                             interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
179                         }
180                     } else if ("Ethernet".equals(input.getServiceFormat())) {
181                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU4");
182                     }
183                     break;
184                 case 400:
185                     if ("ODU".equals(input.getServiceFormat())) {
186                         interfacesToDelete.add(networkTp + "-ODUC4");
187                         if (node.getNetwork2Tp() != null) {
188                             interfacesToDelete.add(node.getNetwork2Tp() + "-ODUC4");
189                         }
190                     }
191                     break;
192                 case 10:
193                     connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
194                     break;
195                 case 1:
196                     connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
197                     break;
198                 default:
199                     LOG.error("service rate {} not managed yet", input.getServiceRate());
200                     String result = input.getServiceRate() + " is not supported";
201                     results.add(result);
202                     success.set(false);
203                     return;
204             }
205             List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
206             for (String interf : intToDelete == null ? new ArrayList<String>() : intToDelete) {
207                 if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
208                         this.deviceTransactionManager)) {
209                     interfacesToDelete.add(interf);
210                     String supportedInterface = this.openRoadmInterfaces.getSupportedInterface(nodeId, interf);
211                     if (input.getServiceRate().intValue() == 100) {
212                         if (!supportedInterface.contains("ODUC4")) {
213                             interfacesToDelete.add(supportedInterface);
214                         }
215                     } else {
216                         if (!supportedInterface.contains("ODU4")) {
217                             interfacesToDelete.add(supportedInterface);
218                         }
219                     }
220                 }
221             }
222
223             for (String interfaceId : interfacesToDelete) {
224                 try {
225                     this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
226                 } catch (OpenRoadmInterfaceException e) {
227                     String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
228                     success.set(false);
229                     LOG.error(result, e);
230                     results.add(result);
231                 }
232             }
233             List<String> interList =
234                     interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK")).collect(Collectors.toList());
235             if (!interList.isEmpty()) {
236                 for (String inter : interList) {
237                     otnLinkTps.add(new LinkTpBuilder()
238                             .setNodeId(nodeId)
239                             .setTpId(inter.split("-ODU")[0])
240                             .build());
241                 }
242             }
243         }));
244         try {
245             forkJoinTask.get();
246         } catch (InterruptedException | ExecutionException e) {
247             LOG.error("Error while deleting service paths!", e);
248             return new OtnServicePathOutputBuilder()
249                 .setResult("Error while deleting service paths!")
250                 .setSuccess(false)
251                 .build();
252         }
253         forkJoinPool.shutdown();
254         return new OtnServicePathOutputBuilder()
255                 .setSuccess(success.get())
256                 .setLinkTp(otnLinkTps)
257                 .setResult(
258                     results.isEmpty()
259                         ? "Request processed"
260                         : String.join("\n", results))
261                 .build();
262     }
263
264     private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
265         if (node.getClientTp() != null) {
266             return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName);
267         } else if (node.getNetwork2Tp() != null) {
268             return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName);
269         } else {
270             return "";
271         }
272     }
273
274     private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
275             throws OpenRoadmInterfaceException {
276         return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
277     }
278
279     private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
280             CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
281         for (Nodes node : input.getNodes()) {
282             // check if the node is mounted or not?
283             List<String> createdEthInterfaces = new ArrayList<>();
284             List<String> createdOduInterfaces = new ArrayList<>();
285             switch (input.getServiceRate().intValue()) {
286                 case 1:
287                     LOG.info("Input service is 1G");
288                     if (node.getClientTp() != null) {
289                         createdEthInterfaces.add(
290                             openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
291                                 node.getClientTp()));
292                         createdOduInterfaces.add(
293                             // suppporting interface?, payload ?
294                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
295                                 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
296                     }
297                     createdOduInterfaces.add(
298                         openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
299                             input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
300                     linkTpList.add(
301                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
302                     if (node.getNetwork2Tp() != null) {
303                         createdOduInterfaces.add(
304                             // supporting interface? payload ?
305                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
306                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
307                                 input.getTribSlot()));
308                         linkTpList.add(
309                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
310                     }
311                     break;
312                 case 10:
313                     LOG.info("Input service is 10G");
314                     if (node.getClientTp() != null) {
315                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
316                             node.getNodeId(), node.getClientTp()));
317                         createdOduInterfaces.add(
318                             // suppporting interface?, payload ?
319                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
320                                 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
321                                 input.getTribSlot()));
322                     }
323                     createdOduInterfaces.add(
324                         // supporting interface? payload ?
325                         openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
326                             input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
327                     linkTpList.add(
328                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
329                     if (node.getNetwork2Tp() != null) {
330                         createdOduInterfaces.add(
331                             // supporting interface? payload ?
332                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
333                                 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
334                                 input.getTribSlot()));
335                         linkTpList.add(
336                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
337                     }
338                     break;
339                 case 100:
340                     LOG.info("Input service is 100G");
341                     // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
342                     // min and max value only, size two)
343                     OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
344                         input.getOpucnTribSlots().get(0).getValue());
345                     OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
346                         input.getOpucnTribSlots().get(1).getValue());
347                     if (node.getClientTp() != null) {
348                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
349                             node.getNodeId(), node.getClientTp()));
350                         // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
351                         createdOduInterfaces.add(
352                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
353                             node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
354                                 maxOpucnTs));
355                     }
356                     // Here payload-type is optional and is not used for interface creation (especially for network)
357                     createdOduInterfaces.add(
358                         openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
359                             node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
360                             maxOpucnTs));
361                     linkTpList.add(
362                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
363                     // Here payload-type is optional and is not used for service creation
364                     // This is needed if there is an intermediate node
365                     if (node.getNetwork2Tp() != null) {
366                         createdOduInterfaces.add(
367                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
368                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
369                                 maxOpucnTs));
370                         linkTpList.add(
371                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
372                     }
373                     break;
374                 default:
375                     LOG.error("service rate {} not managed yet", input.getServiceRate());
376                     return;
377             }
378
379             // implement cross connect
380             List<String> createdConnections = new ArrayList<>();
381             if (!createdOduInterfaces.isEmpty()) {
382                 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
383                 createdConnections.add(connectionNameOpt.get());
384                 LOG.info("Created cross connects");
385             }
386             nodeInterfaces.add(new NodeInterfaceBuilder()
387                     .withKey(new NodeInterfaceKey(node.getNodeId()))
388                     .setNodeId(node.getNodeId())
389                     .setConnectionId(createdConnections)
390                     .setEthInterfaceId(createdEthInterfaces)
391                     .setOduInterfaceId(createdOduInterfaces)
392                     .build());
393         }
394     }
395
396     private void createOduc4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
397         CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
398         if (input.getNodes() == null) {
399             return;
400         }
401         LOG.info("Creation of ODUC4 TTP interface in OTN service path {}", input);
402         for (int i = 0; i < input.getNodes().size(); i++) {
403             Nodes node = input.getNodes().get(i);
404             String supportingOtuInterface = node.getNetworkTp() + "-OTUC4";
405
406             Nodes tgtNode =
407                 i + 1 == input.getNodes().size()
408                 // For the end node, tgtNode becomes the first node in the list
409                     ? input.getNodes().get(0)
410                     : input.getNodes().get(i + 1);
411
412             nodeInterfaces.add(new NodeInterfaceBuilder()
413                     .withKey(new NodeInterfaceKey(node.getNodeId()))
414                     .setNodeId(node.getNodeId())
415                     .setOduInterfaceId(List.of(
416                         // though this is odu, actually it has ODUC4 interfaces
417                         openRoadmInterfaceFactory.createOpenRoadmOtnOduc4Interface(node.getNodeId(),
418                             node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
419                     .build());
420             linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
421         }
422     }
423
424     private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
425         CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
426         if (input.getNodes() == null) {
427             return;
428         }
429         LOG.info("Creation of ODU4 tp interface {}", input);
430         for (int i = 0; i < input.getNodes().size(); i++) {
431             Nodes node = input.getNodes().get(i);
432             String supportingOtuInterface = node.getNetworkTp() + "-OTU";
433
434             Nodes tgtNode =
435                 i + 1 == input.getNodes().size()
436                 // For the end node, tgtNode becomes the first node in the list
437                     ? input.getNodes().get(0)
438                     : input.getNodes().get(i + 1);
439
440             nodeInterfaces.add(new NodeInterfaceBuilder()
441                     .withKey(new NodeInterfaceKey(node.getNodeId()))
442                     .setNodeId(node.getNodeId())
443                     .setOduInterfaceId(List.of(
444                         openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
445                             node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
446                     .build());
447             linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
448         }
449     }
450 }