ee964c53d1c28e1575cf8a60d82ffbf3bc10e937
[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.rev200128.node.interfaces.NodeInterface;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.node.interfaces.NodeInterfaceBuilder;
33 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.node.interfaces.NodeInterfaceKey;
34 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.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 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 serivce-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 serivce-rate for service-type ODU");
122                 }
123                 break;
124             default:
125                 LOG.error("service-type {} not managet 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         List<Nodes> nodes = input.getNodes();
143         AtomicBoolean success = new AtomicBoolean(true);
144         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
145         List<String> nodesTpToUpdate = new ArrayList<>();
146         CopyOnWriteArrayList<Nodes> otnNodesProvisioned = new CopyOnWriteArrayList<>();
147         ForkJoinPool forkJoinPool = new ForkJoinPool();
148         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
149             List<String> interfacesToDelete = new LinkedList<>();
150             String nodeId = node.getNodeId();
151             LOG.info("Deleting service setup on node {}", nodeId);
152             String networkTp = node.getNetworkTp();
153             if (networkTp == null || input.getServiceRate() == null || input.getServiceType() == null) {
154                 LOG.error("destination ({}) or service rate ({}) or service type ({}) is null.", networkTp,
155                     input.getServiceRate(), input.getServiceType());
156                 return;
157             }
158             // if the node is currently mounted then proceed.
159             if (this.deviceTransactionManager.isDeviceMounted(nodeId)) {
160                 String connectionNumber = "";
161                 switch (input.getServiceRate()) {
162                     case ("100G"):
163                         if ("ODU".equals(input.getServiceType())) {
164                             interfacesToDelete.add(networkTp + "-ODU4");
165                             otnNodesProvisioned.add(node);
166                             if (node.getNetwork2Tp() != null) {
167                                 interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
168                             }
169                         }
170                         break;
171                     case ("10G"):
172                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
173                         break;
174                     case ("1G"):
175                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
176                         break;
177                     default:
178                         LOG.error("service rate {} not managed yet", input.getServiceRate());
179                         String result = input.getServiceRate() + " is not supported";
180                         results.add(result);
181                         success.set(false);
182                         return;
183                 }
184                 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
185                 if (intToDelete != null) {
186                     for (String interf : intToDelete) {
187                         if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
188                             this.deviceTransactionManager)) {
189                             interfacesToDelete.add(interf);
190                             if (!getSupportedInterface(nodeId, interf).contains("ODU4")) {
191                                 interfacesToDelete.add(getSupportedInterface(nodeId, interf));
192                             }
193                         }
194                     }
195                 }
196             } else {
197                 String result = nodeId + " is not mounted on the controller";
198                 results.add(result);
199                 success.set(false);
200                 LOG.warn(result);
201                 forkJoinPool.shutdown();
202                 return;
203                 // TODO should deletion end here?
204             }
205             for (String interfaceId : interfacesToDelete) {
206                 try {
207                     this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
208                 } catch (OpenRoadmInterfaceException e) {
209                     String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
210                     success.set(false);
211                     LOG.error(result, e);
212                     results.add(result);
213                 }
214             }
215             List<String> interList = interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK"))
216                 .collect(Collectors.toList());
217             if (!interList.isEmpty()) {
218                 for (String inter : interList) {
219                     String tp = inter.split("-ODU")[0];
220                     String nodeTopo = nodeId + "-" + tp.split("-")[0];
221                     nodesTpToUpdate.add(nodeTopo + "--" + tp);
222                 }
223             }
224         }));
225         try {
226             forkJoinTask.get();
227         } catch (InterruptedException | ExecutionException e) {
228             LOG.error("Error while deleting service paths!", e);
229         }
230         forkJoinPool.shutdown();
231         LOG.info("requesting otn-topology update...");
232         if (!nodesTpToUpdate.isEmpty() && !"ODU".equals(input.getServiceType())) {
233             updateOtnTopology(null, nodesTpToUpdate, input.getServiceRate(), input.getTribPortNumber(),
234                 input.getTribSlot(), true);
235         } else if (!otnNodesProvisioned.isEmpty()) {
236             updateOtnTopology(otnNodesProvisioned, null, null, null, null, true);
237         }
238
239         OtnServicePathOutputBuilder delServBldr = new OtnServicePathOutputBuilder();
240         delServBldr.setSuccess(success.get());
241         if (results.isEmpty()) {
242             return delServBldr.setResult("Request processed").build();
243         } else {
244             return delServBldr.setResult(String.join("\n", results)).build();
245         }
246     }
247
248     private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
249         if (node.getClientTp() != null) {
250             return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName);
251         } else if (node.getNetwork2Tp() != null) {
252             return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName);
253         } else {
254             return "";
255         }
256     }
257
258     private String getSupportedInterface(String nodeId, String interf) {
259         Optional<Interface> supInterfOpt;
260         try {
261             supInterfOpt = this.openRoadmInterfaces.getInterface(nodeId, interf);
262             if (supInterfOpt.isPresent()) {
263                 return supInterfOpt.get().getSupportingInterface();
264             } else {
265                 return null;
266             }
267         } catch (OpenRoadmInterfaceException e) {
268             LOG.error("error getting Supported Interface of {} - {}", interf, nodeId, e);
269             return null;
270         }
271     }
272
273     private List<NodeInterface> createInterface(OtnServicePathInput input) throws OpenRoadmInterfaceException {
274         List<NodeInterface> nodeInterfaces = new ArrayList<>();
275         LOG.info("Calling Create Interface entry for OTN service path");
276         if (input.getServiceRate() == null
277             || !("1G".equals(input.getServiceRate()) || "10G".equals(input.getServiceRate()))) {
278             LOG.error("Service rate {} not managed yet", input.getServiceRate());
279         } else {
280             createLowOrderInterfaces(input, nodeInterfaces);
281         }
282         return nodeInterfaces;
283     }
284
285     private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
286             throws OpenRoadmInterfaceException {
287         return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
288     }
289
290     private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces)
291         throws OpenRoadmInterfaceException {
292         for (Nodes node : input.getNodes()) {
293             // check if the node is mounted or not?
294             List<String> createdEthInterfaces = new ArrayList<>();
295             List<String> createdOduInterfaces = new ArrayList<>();
296             switch (input.getServiceRate()) {
297                 case ("1G"):
298                     LOG.info("Input service is 1G");
299                     if (node.getClientTp() != null) {
300                         createdEthInterfaces.add(
301                             openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
302                                 node.getClientTp()));
303                         createdOduInterfaces.add(
304                             // suppporting interface?, payload ?
305                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
306                                 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
307                     }
308                     createdOduInterfaces.add(
309                         openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
310                             input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
311                     if (node.getNetwork2Tp() != null) {
312                         createdOduInterfaces.add(
313                             // supporting interface? payload ?
314                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
315                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
316                                 input.getTribSlot()));
317                     }
318                     break;
319                 case ("10G"):
320                     LOG.info("Input service is 10G");
321                     if (node.getClientTp() != null) {
322                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
323                             node.getNodeId(), node.getClientTp()));
324                         createdOduInterfaces.add(
325                             // suppporting interface?, payload ?
326                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
327                                 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
328                                 input.getTribSlot()));
329                     }
330                     createdOduInterfaces.add(
331                         // supporting interface? payload ?
332                         openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
333                             input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
334                     if (node.getNetwork2Tp() != null) {
335                         createdOduInterfaces.add(
336                             // supporting interface? payload ?
337                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
338                                 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
339                                 input.getTribSlot()));
340                     }
341                     break;
342                 default:
343                     LOG.error("service rate {} not managed yet", input.getServiceRate());
344                     return;
345             }
346
347             // implement cross connect
348             List<String> createdConnections = new ArrayList<>();
349             if (!createdOduInterfaces.isEmpty()) {
350                 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
351                 createdConnections.add(connectionNameOpt.get());
352                 LOG.info("Created cross connects");
353             }
354             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
355                 .withKey(new NodeInterfaceKey(node.getNodeId()))
356                 .setNodeId(node.getNodeId())
357                 .setConnectionId(createdConnections)
358                 .setEthInterfaceId(createdEthInterfaces)
359                 .setOduInterfaceId(createdOduInterfaces);
360             nodeInterfaces.add(nodeInterfaceBuilder.build());
361         }
362     }
363
364     private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
365         CopyOnWriteArrayList<Nodes> otnNodesProvisioned) throws OpenRoadmInterfaceException {
366         for (Nodes node : input.getNodes()) {
367             String supportingOtuInterface = node.getNetworkTp() + "-OTU";
368             List<String> createdOdu4Interfaces = new ArrayList<>();
369             createdOdu4Interfaces.add(openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
370                 node.getNetworkTp(), supportingOtuInterface));
371             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
372                 .withKey(new NodeInterfaceKey(node.getNodeId()))
373                 .setNodeId(node.getNodeId())
374                 .setOduInterfaceId(createdOdu4Interfaces);
375             nodeInterfaces.add(nodeInterfaceBuilder.build());
376             otnNodesProvisioned.add(node);
377         }
378     }
379
380     private void updateOtnTopology(CopyOnWriteArrayList<Nodes> nodes, List<String> nodesTps, String serviceRate,
381         Short tribPortNb, Short tribSlotNb, boolean isDeletion) {
382         if (nodes != null && nodes.size() == 2) {
383             if (isDeletion) {
384                 LOG.info("updating otn-topology removing ODU4 links");
385                 this.networkModelService.deleteOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(),
386                     nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4);
387             } else {
388                 LOG.info("updating otn-topology adding ODU4 links");
389                 this.networkModelService.createOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(),
390                     nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4);
391             }
392         } else if (nodesTps != null && (nodesTps.size() % 2 == 0) && serviceRate != null && tribPortNb != null
393             && tribSlotNb != null) {
394             LOG.info("updating otn-topology node tps -tps and tpn pools");
395             this.networkModelService.updateOtnLinks(nodesTps, serviceRate, tribPortNb, tribSlotNb, isDeletion);
396         }
397     }
398
399 }