Device renderer for muxponder
[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.device.renderer.rev200128.OtnServicePathInput;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev200128.OtnServicePathOutput;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.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.openroadm.otn.common.types.rev200327.OpucnTribSlotDef;
34 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.node.interfaces.NodeInterface;
35 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.node.interfaces.NodeInterfaceBuilder;
36 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.node.interfaces.NodeInterfaceKey;
37 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev201211.otn.renderer.input.Nodes;
38 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev201019.OtnLinkType;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42
43 public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService {
44     private static final Logger LOG = LoggerFactory.getLogger(OtnDeviceRendererServiceImpl.class);
45     private static final String PT_03 = "03";
46     private static final String PT_07 = "07";
47     private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
48     private final CrossConnect crossConnect;
49     private final OpenRoadmInterfaces openRoadmInterfaces;
50     private final DeviceTransactionManager deviceTransactionManager;
51     private final NetworkModelService networkModelService;
52
53     public OtnDeviceRendererServiceImpl(OpenRoadmInterfaceFactory openRoadmInterfaceFactory, CrossConnect crossConnect,
54                                         OpenRoadmInterfaces openRoadmInterfaces,
55                                         DeviceTransactionManager deviceTransactionManager,
56                                         NetworkModelService networkModelService) {
57         this.openRoadmInterfaceFactory = openRoadmInterfaceFactory;
58         this.crossConnect = crossConnect;
59         this.openRoadmInterfaces = openRoadmInterfaces;
60         this.deviceTransactionManager = deviceTransactionManager;
61         this.networkModelService = networkModelService;
62     }
63
64     @Override
65     public OtnServicePathOutput setupOtnServicePath(OtnServicePathInput input) {
66         LOG.info("Calling setup otn-service path");
67         boolean success = true;
68         List<NodeInterface> nodeInterfaces = new ArrayList<>();
69         List<String> results = new ArrayList<>();
70         if (input.getServiceType() == null || input.getServiceRate() == null) {
71             OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder()
72                 .setSuccess(false)
73                 .setResult("Error - service-type and service-rate must be presents");
74             return otnServicePathOutputBuilder.build();
75         }
76         CopyOnWriteArrayList<Nodes> otnNodesProvisioned = new CopyOnWriteArrayList<>();
77         switch (input.getServiceType()) {
78             case "Ethernet":
79                 if ("10G".equals(input.getServiceRate()) || "1G".equals(input.getServiceRate())) {
80                     try {
81                         LOG.info("Calling Node interfaces {} {} {} {} {} {} {}",
82                             input.getServiceRate(), input.getEthernetEncoding(),
83                             input.getServiceType(), input.getOperation(), input.getTribPortNumber(),
84                             input.getTribSlot(), input.getNodes());
85                         nodeInterfaces = createInterface(input);
86                         LOG.info("Node interfaces created just fine ");
87
88                         List<String> nodesToUpdate = updateOduNodes(nodeInterfaces, "ODU");
89                         updateOtnTopology(null, nodesToUpdate, input.getServiceRate(), input.getTribPortNumber(),
90                             input.getTribSlot(), false);
91                     } catch (OpenRoadmInterfaceException e) {
92                         LOG.warn("Set up service path failed", e);
93                         success = false;
94                     }
95                 } else if ("100G".equals(input.getServiceRate())) {
96                     try {
97                         LOG.info("Calling Node interfaces {} {} {} {} {} {}",
98                             input.getServiceRate(), input.getEthernetEncoding(),
99                             input.getServiceType(), input.getOperation(), input.getOpucnTribSlots(), input.getNodes());
100                         nodeInterfaces = createInterface(input);
101                         LOG.info("Node interfaces created just fine for 100G OTN ");
102                         // TODO: Update the OTN topology accordingly with Opucn-Trib-slots
103                         // List<String> nodesToUpdate = updateOduNodes(nodeInterfaces, "ODUC4");
104                         // updateOtnTopology(null, nodesToUpdate, input.getServiceRate(), input.getTribPortNumber(),
105                         //    input.getTribSlot(), false);
106                     } catch (OpenRoadmInterfaceException e) {
107                         LOG.warn("Set up service path failed", e);
108                         success = false;
109                     }
110                 } else {
111                     LOG.warn("Unsupported service-rate for service-type Ethernet");
112                 }
113                 break;
114             case "ODU":
115                 if ("100G".equals(input.getServiceRate())) {
116                     try {
117                         createODU4TtpInterface(input, nodeInterfaces, otnNodesProvisioned);
118                         updateOtnTopology(otnNodesProvisioned, null, null, null, null, false);
119                     } catch (OpenRoadmInterfaceException e) {
120                         LOG.warn("Set up service path failed", e);
121                         success = false;
122                     }
123                 } else if ("400G".equals(input.getServiceRate())) {
124                     try {
125                         createOduc4TtpInterface(input, nodeInterfaces, otnNodesProvisioned);
126                         updateOtnTopology(otnNodesProvisioned, null, null, null, null, false);
127                     } catch (OpenRoadmInterfaceException e) {
128                         LOG.warn("Set up service path failed", e);
129                         success = false;
130                     }
131                 } else {
132                     LOG.warn("Unsupported service-rate for service-type ODU");
133                 }
134                 break;
135             default:
136                 LOG.error("service-type {} not managed yet", input.getServiceType());
137                 break;
138         }
139         if (success) {
140             LOG.info("Result is success");
141             for (NodeInterface nodeInterface : nodeInterfaces) {
142                 results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId());
143             }
144         }
145         Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
146         for (NodeInterface nodeInterface : nodeInterfaces) {
147             if (nodeInterface != null) {
148                 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
149             }
150         }
151         OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder()
152                 .setSuccess(success)
153                 .setNodeInterface(nodeInterfacesMap)
154                 .setResult(String.join("\n", results));
155         return otnServicePathOutputBuilder.build();
156     }
157
158     public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) {
159         if (input == null) {
160             LOG.error("Unable to delete otn service path. input = null");
161             return new OtnServicePathOutputBuilder().setResult("Unable to delete otn service path. input = null")
162                 .setSuccess(false).build();
163         }
164         List<Nodes> nodes = input.getNodes();
165         AtomicBoolean success = new AtomicBoolean(true);
166         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
167         List<String> nodesTpToUpdate = new ArrayList<>();
168         CopyOnWriteArrayList<Nodes> otnNodesProvisioned = new CopyOnWriteArrayList<>();
169         ForkJoinPool forkJoinPool = new ForkJoinPool();
170         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
171             List<String> interfacesToDelete = new LinkedList<>();
172             String nodeId = node.getNodeId();
173             LOG.info("Deleting service setup on node {}", nodeId);
174             String networkTp = node.getNetworkTp();
175             if (networkTp == null || input.getServiceRate() == null || input.getServiceType() == null) {
176                 LOG.error("destination ({}) or service rate ({}) or service type ({}) is null.", networkTp,
177                     input.getServiceRate(), input.getServiceType());
178                 return;
179             }
180             // if the node is currently mounted then proceed.
181             if (this.deviceTransactionManager.isDeviceMounted(nodeId)) {
182                 String connectionNumber = "";
183                 switch (input.getServiceRate()) {
184                     case ("100G"):
185                         if ("ODU".equals(input.getServiceType())) {
186                             interfacesToDelete.add(networkTp + "-ODU4");
187                             otnNodesProvisioned.add(node);
188                             if (node.getNetwork2Tp() != null) {
189                                 interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
190                             }
191                         }
192                         break;
193                     case ("10G"):
194                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
195                         break;
196                     case ("1G"):
197                         connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
198                         break;
199                     default:
200                         LOG.error("service rate {} not managed yet", input.getServiceRate());
201                         String result = input.getServiceRate() + " is not supported";
202                         results.add(result);
203                         success.set(false);
204                         return;
205                 }
206                 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
207                 if (intToDelete != null) {
208                     for (String interf : intToDelete) {
209                         if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
210                             this.deviceTransactionManager)) {
211                             interfacesToDelete.add(interf);
212                             if (!getSupportedInterface(nodeId, interf).contains("ODU4")) {
213                                 interfacesToDelete.add(getSupportedInterface(nodeId, interf));
214                             }
215                         }
216                     }
217                 }
218             } else {
219                 String result = nodeId + " is not mounted on the controller";
220                 results.add(result);
221                 success.set(false);
222                 LOG.warn(result);
223                 forkJoinPool.shutdown();
224                 return;
225                 // TODO should deletion end here?
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 = interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK"))
238                 .collect(Collectors.toList());
239             if (!interList.isEmpty()) {
240                 for (String inter : interList) {
241                     String tp = inter.split("-ODU")[0];
242                     String nodeTopo = nodeId + "-" + tp.split("-")[0];
243                     nodesTpToUpdate.add(nodeTopo + "--" + tp);
244                 }
245             }
246         }));
247         try {
248             forkJoinTask.get();
249         } catch (InterruptedException | ExecutionException e) {
250             LOG.error("Error while deleting service paths!", e);
251         }
252         forkJoinPool.shutdown();
253         LOG.info("requesting otn-topology update...");
254         if (!nodesTpToUpdate.isEmpty() && !"ODU".equals(input.getServiceType())) {
255             updateOtnTopology(null, nodesTpToUpdate, input.getServiceRate(), input.getTribPortNumber(),
256                 input.getTribSlot(), true);
257         } else if (!otnNodesProvisioned.isEmpty()) {
258             updateOtnTopology(otnNodesProvisioned, null, null, null, null, true);
259         }
260
261         OtnServicePathOutputBuilder delServBldr = new OtnServicePathOutputBuilder();
262         delServBldr.setSuccess(success.get());
263         if (results.isEmpty()) {
264             return delServBldr.setResult("Request processed").build();
265         } else {
266             return delServBldr.setResult(String.join("\n", results)).build();
267         }
268     }
269
270     private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
271         if (node.getClientTp() != null) {
272             return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName);
273         } else if (node.getNetwork2Tp() != null) {
274             return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName);
275         } else {
276             return "";
277         }
278     }
279
280     private String getSupportedInterface(String nodeId, String interf) {
281         Optional<Interface> supInterfOpt;
282         try {
283             supInterfOpt = this.openRoadmInterfaces.getInterface(nodeId, interf);
284             if (supInterfOpt.isPresent()) {
285                 return supInterfOpt.get().getSupportingInterface();
286             } else {
287                 return null;
288             }
289         } catch (OpenRoadmInterfaceException e) {
290             LOG.error("error getting Supported Interface of {} - {}", interf, nodeId, e);
291             return null;
292         }
293     }
294
295     private List<String> updateOduNodes(List<NodeInterface> nodeInterfaceList, String deLimiter) {
296         List<String> nodesToUpdate = new ArrayList<>();
297         if (!(deLimiter.equals("ODU")) || !(deLimiter.equals("ODUC4"))) {
298             LOG.error("ODU node list update will be incorrect");
299         }
300
301         if (!nodeInterfaceList.isEmpty()) {
302             for (NodeInterface nodeInterf : nodeInterfaceList) {
303                 if (nodeInterf.getOduInterfaceId() != null) {
304                     List<String> interList = nodeInterf.getOduInterfaceId().stream()
305                         .filter(id -> id.contains("NETWORK")).collect(Collectors.toList());
306                     if (!interList.isEmpty()) {
307                         for (String inter : interList) {
308                             String tp = inter.split("-" + deLimiter)[0];
309                             String nodeTopo = nodeInterf.getNodeId() + "-" + tp.split("-")[0];
310                             nodesToUpdate.add(nodeTopo + "--" + tp);
311                         }
312                     }
313                 }
314             }
315         }
316
317         return nodesToUpdate;
318     }
319
320     private List<NodeInterface> createInterface(OtnServicePathInput input) throws OpenRoadmInterfaceException {
321         List<NodeInterface> nodeInterfaces = new ArrayList<>();
322         LOG.info("Calling Create Interface entry for OTN service path");
323         if (input.getServiceRate() == null
324             || !("1G".equals(input.getServiceRate()) || "10G".equals(input.getServiceRate())
325                 || "100G".equals(input.getServiceRate()))) {
326             LOG.error("Service rate {} not managed yet", input.getServiceRate());
327         } else {
328             createLowOrderInterfaces(input, nodeInterfaces);
329         }
330         return nodeInterfaces;
331     }
332
333     private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
334             throws OpenRoadmInterfaceException {
335         return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
336     }
337
338     private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces)
339         throws OpenRoadmInterfaceException {
340         for (Nodes node : input.getNodes()) {
341             // check if the node is mounted or not?
342             List<String> createdEthInterfaces = new ArrayList<>();
343             List<String> createdOduInterfaces = new ArrayList<>();
344             switch (input.getServiceRate()) {
345                 case ("1G"):
346                     LOG.info("Input service is 1G");
347                     if (node.getClientTp() != null) {
348                         createdEthInterfaces.add(
349                             openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
350                                 node.getClientTp()));
351                         createdOduInterfaces.add(
352                             // suppporting interface?, payload ?
353                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
354                                 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
355                     }
356                     createdOduInterfaces.add(
357                         openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
358                             input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
359                     if (node.getNetwork2Tp() != null) {
360                         createdOduInterfaces.add(
361                             // supporting interface? payload ?
362                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
363                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
364                                 input.getTribSlot()));
365                     }
366                     break;
367                 case ("10G"):
368                     LOG.info("Input service is 10G");
369                     if (node.getClientTp() != null) {
370                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
371                             node.getNodeId(), node.getClientTp()));
372                         createdOduInterfaces.add(
373                             // suppporting interface?, payload ?
374                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
375                                 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
376                                 input.getTribSlot()));
377                     }
378                     createdOduInterfaces.add(
379                         // supporting interface? payload ?
380                         openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
381                             input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
382                     if (node.getNetwork2Tp() != null) {
383                         createdOduInterfaces.add(
384                             // supporting interface? payload ?
385                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
386                                 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
387                                 input.getTribSlot()));
388                     }
389                     break;
390                 case ("100G"):
391                     LOG.info("Input service is 100G");
392                     // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
393                     // min and max value only, size two)
394                     OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
395                         input.getOpucnTribSlots().get(0).getValue());
396                     OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
397                         input.getOpucnTribSlots().get(1).getValue());
398                     if (node.getClientTp() != null) {
399                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
400                             node.getNodeId(), node.getClientTp()));
401                         // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
402                         createdOduInterfaces.add(
403                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
404                             node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
405                                 maxOpucnTs));
406                     }
407                     // Here payload-type is optional and is not used for interface creation (especially for network)
408                     createdOduInterfaces.add(
409                         openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
410                             node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
411                             maxOpucnTs));
412                     // Here payload-type is optional and is not used for service creation
413                     // This is needed if there is an intermediate node
414                     if (node.getNetwork2Tp() != null) {
415                         createdOduInterfaces.add(
416                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
417                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
418                                 maxOpucnTs));
419                     }
420                     break;
421                 default:
422                     LOG.error("service rate {} not managed yet", input.getServiceRate());
423                     return;
424             }
425
426             // implement cross connect
427             List<String> createdConnections = new ArrayList<>();
428             if (!createdOduInterfaces.isEmpty()) {
429                 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
430                 createdConnections.add(connectionNameOpt.get());
431                 LOG.info("Created cross connects");
432             }
433             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
434                 .withKey(new NodeInterfaceKey(node.getNodeId()))
435                 .setNodeId(node.getNodeId())
436                 .setConnectionId(createdConnections)
437                 .setEthInterfaceId(createdEthInterfaces)
438                 .setOduInterfaceId(createdOduInterfaces);
439             nodeInterfaces.add(nodeInterfaceBuilder.build());
440         }
441     }
442
443     private void createOduc4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
444         CopyOnWriteArrayList<Nodes> otnNodesProvisioned) throws OpenRoadmInterfaceException {
445         if (input.getNodes() == null) {
446             return;
447         }
448         LOG.info("Creation of ODUC4 TTP interface in OTN service path {}", input);
449         for (int i = 0; i < input.getNodes().size(); i++) {
450             Nodes node = input.getNodes().get(i);
451             String supportingOtuInterface = node.getNetworkTp() + "-OTUC4";
452             List<String> createdOduc4Interfaces = new ArrayList<>();
453             // Adding SAPI/DAPI information to the
454             Nodes tgtNode = null;
455             if (i + 1 == input.getNodes().size()) {
456                 // For the end node, tgtNode becomes the first node in the list
457                 tgtNode = input.getNodes().get(0);
458             } else {
459                 tgtNode = input.getNodes().get(i + 1);
460             }
461             createdOduc4Interfaces.add(openRoadmInterfaceFactory.createOpenRoadmOtnOduc4Interface(node.getNodeId(),
462                 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp()));
463
464             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
465                 .withKey(new NodeInterfaceKey(node.getNodeId()))
466                 .setNodeId(node.getNodeId())
467                 .setOduInterfaceId(createdOduc4Interfaces); // though this is odu, actually it has ODUC4 interfaces
468             nodeInterfaces.add(nodeInterfaceBuilder.build());
469             otnNodesProvisioned.add(node);
470         }
471     }
472
473     private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
474         CopyOnWriteArrayList<Nodes> otnNodesProvisioned) throws OpenRoadmInterfaceException {
475         if (input.getNodes() == null) {
476             return;
477         }
478         LOG.info("Creation of ODU4 tp interface {}", input);
479         for (int i = 0; i < input.getNodes().size(); i++) {
480             Nodes node = input.getNodes().get(i);
481             String supportingOtuInterface = node.getNetworkTp() + "-OTU";
482             List<String> createdOdu4Interfaces = new ArrayList<>();
483             // Adding SAPI/DAPI information to the
484             Nodes tgtNode = null;
485             if (i + 1 == input.getNodes().size()) {
486                 // For the end node, tgtNode becomes the first node in the list
487                 tgtNode = input.getNodes().get(0);
488             } else {
489                 tgtNode = input.getNodes().get(i + 1);
490             }
491             createdOdu4Interfaces.add(openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
492                 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp()));
493             NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
494                 .withKey(new NodeInterfaceKey(node.getNodeId()))
495                 .setNodeId(node.getNodeId())
496                 .setOduInterfaceId(createdOdu4Interfaces);
497             nodeInterfaces.add(nodeInterfaceBuilder.build());
498             otnNodesProvisioned.add(node);
499         }
500     }
501
502     private void updateOtnTopology(CopyOnWriteArrayList<Nodes> nodes, List<String> nodesTps, String serviceRate,
503         Short tribPortNb, Short tribSlotNb, boolean isDeletion) {
504         if (nodes != null && nodes.size() == 2) {
505             if (isDeletion) {
506                 LOG.info("updating otn-topology removing ODU4 links");
507                 this.networkModelService.deleteOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(),
508                     nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4);
509             } else {
510                 LOG.info("updating otn-topology adding ODU4 links");
511                 this.networkModelService.createOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(),
512                     nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4);
513             }
514         } else if (nodesTps != null && (nodesTps.size() % 2 == 0) && serviceRate != null && tribPortNb != null
515             && tribSlotNb != null) {
516             LOG.info("updating otn-topology node tps -tps and tpn pools");
517             this.networkModelService.updateOtnLinks(nodesTps, serviceRate, tribPortNb, tribSlotNb, isDeletion);
518         }
519     }
520
521 }