Merge "Fix output response for 400GE device renderer"
[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.Arrays;
12 import java.util.HashMap;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Optional;
17 import java.util.concurrent.ConcurrentLinkedQueue;
18 import java.util.concurrent.CopyOnWriteArrayList;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.ForkJoinPool;
21 import java.util.concurrent.ForkJoinTask;
22 import java.util.concurrent.atomic.AtomicBoolean;
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.networkmodel.service.NetworkModelService;
29 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathOutput;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathOutputBuilder;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.AEndApiInfo;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.ZEndApiInfo;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OpucnTribSlotDef;
36 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.link.tp.LinkTp;
37 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.link.tp.LinkTpBuilder;
38 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.node.interfaces.NodeInterface;
39 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.node.interfaces.NodeInterfaceBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.node.interfaces.NodeInterfaceKey;
41 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.otn.renderer.nodes.Nodes;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45
46 public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService {
47     private static final Logger LOG = LoggerFactory.getLogger(OtnDeviceRendererServiceImpl.class);
48     private static final String PT_03 = "03";
49     private static final String PT_07 = "07";
50     private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
51     private final CrossConnect crossConnect;
52     private final OpenRoadmInterfaces openRoadmInterfaces;
53     private final DeviceTransactionManager deviceTransactionManager;
54     private final NetworkModelService networkModelService;
55
56     public OtnDeviceRendererServiceImpl(OpenRoadmInterfaceFactory openRoadmInterfaceFactory, CrossConnect crossConnect,
57                                         OpenRoadmInterfaces openRoadmInterfaces,
58                                         DeviceTransactionManager deviceTransactionManager,
59                                         NetworkModelService networkModelService) {
60         this.openRoadmInterfaceFactory = openRoadmInterfaceFactory;
61         this.crossConnect = crossConnect;
62         this.openRoadmInterfaces = openRoadmInterfaces;
63         this.deviceTransactionManager = deviceTransactionManager;
64         this.networkModelService = networkModelService;
65     }
66
67 //TODO Align log messages and returned results messages
68     @Override
69     public OtnServicePathOutput setupOtnServicePath(OtnServicePathInput input, String serviceType) {
70         LOG.info("Calling setup otn-service path");
71         if (input.getServiceFormat() == null || input.getServiceRate() == null) {
72             return new OtnServicePathOutputBuilder()
73                 .setSuccess(false)
74                 .setResult("Error - service-type and service-rate must be present")
75                 .build();
76         }
77         List<NodeInterface> nodeInterfaces = new ArrayList<>();
78         CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
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                     createHighOrderInterfaces(input, nodeInterfaces, otnLinkTps);
95                     break;
96                 // For all the intermediate rates, device renderer is generalized as
97                 // ODUCnTTPinterface method
98                 case StringConstants.SERVICE_TYPE_ODUC2:
99                 case StringConstants.SERVICE_TYPE_ODUC3:
100                 case StringConstants.SERVICE_TYPE_ODUC4:
101                     createOducnTtpInterface(input, nodeInterfaces, otnLinkTps);
102                     break;
103                 case StringConstants.SERVICE_TYPE_100GE_S:
104                     LOG.info("Calling Node interface for service-type {}", serviceType);
105                     if (input.getNodes() != null) {
106                         createHighOrderInterfaces(input, nodeInterfaces, otnLinkTps);
107                         LOG.info("Node interfaces created");
108                     }
109                     break;
110                 default:
111                     LOG.error("Service-type {} not managed yet", serviceType);
112                     return new OtnServicePathOutputBuilder()
113                         .setSuccess(false)
114                         .setResult("Service-type not managed")
115                         .build();
116             }
117         } catch (OpenRoadmInterfaceException e) {
118             LOG.warn("Service path set-up failed", e);
119             Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
120             for (NodeInterface nodeInterface : nodeInterfaces) {
121                 if (nodeInterface != null) {
122                     nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
123                 }
124             }
125             //TODO check if we need to set a NodeInterface Map in the result in that case
126             return new OtnServicePathOutputBuilder()
127                     .setSuccess(false)
128                     .setNodeInterface(nodeInterfacesMap)
129                     .setResult("Service path set-up failed")
130                     .setLinkTp(otnLinkTps)
131                     .build();
132         }
133         LOG.info("Service path set-up succeed");
134         List<String> results = new ArrayList<>();
135         Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
136         for (NodeInterface nodeInterface : nodeInterfaces) {
137             if (nodeInterface != null) {
138                 results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId());
139                 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
140             }
141         }
142         return new OtnServicePathOutputBuilder()
143                 .setSuccess(true)
144                 .setNodeInterface(nodeInterfacesMap)
145                 .setResult(String.join("\n", results))
146                 .setLinkTp(otnLinkTps)
147                 .build();
148     }
149
150     @SuppressWarnings("rawtypes")
151     // FIXME check if the ForkJoinTask raw type can be avoided
152     // Raw types use are discouraged since they lack type safety.
153     // Resulting Problems are observed at run time and not at compile time
154     public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input, String serviceType) {
155         if (input.getNodes() == null) {
156             LOG.error("Unable to delete otn service path. input nodes = null");
157             return new OtnServicePathOutputBuilder()
158                 .setResult("Unable to delete otn service path. input nodes = null")
159                 .setSuccess(false)
160                 .build();
161         }
162         List<Nodes> nodes = input.getNodes();
163         AtomicBoolean success = new AtomicBoolean(true);
164         ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
165         CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
166         ForkJoinPool forkJoinPool = new ForkJoinPool();
167         ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
168             String nodeId = node.getNodeId();
169             LOG.info("Deleting service setup on node {}", nodeId);
170             String networkTp = node.getNetworkTp();
171             if (networkTp == null || input.getServiceRate() == null || input.getServiceFormat() == null) {
172                 LOG.error("destination ({}) or service-rate ({}) or service-format ({}) is null.",
173                     networkTp, input.getServiceRate(), input.getServiceFormat());
174                 return;
175             }
176             if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
177                 String result = nodeId + " is not mounted on the controller";
178                 results.add(result);
179                 success.set(false);
180                 LOG.warn(result);
181                 forkJoinPool.shutdown();
182                 return;
183                 // TODO should deletion end here?
184             }
185             // if the node is currently mounted then proceed.
186             List<String> interfacesToDelete = new LinkedList<>();
187             String connectionNumber = "";
188             switch (serviceType) {
189                 case StringConstants.SERVICE_TYPE_100GE_S:
190                     connectionNumber = getConnectionNumber(null, node, networkTp, "ODU4");
191                     break;
192                 case StringConstants.SERVICE_TYPE_100GE_M:
193                     connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU4");
194                     otnLinkTps.add(new LinkTpBuilder()
195                         .setNodeId(nodeId)
196                         .setTpId(networkTp)
197                         .build());
198                     break;
199                 case StringConstants.SERVICE_TYPE_ODU4:
200                     if (node.getClientTp() == null && node.getNetwork2Tp() == null) {
201                         interfacesToDelete.add(networkTp + "-ODU4");
202                         otnLinkTps.add(new LinkTpBuilder()
203                             .setNodeId(nodeId)
204                             .setTpId(networkTp)
205                             .build());
206                     }
207                     if (node.getClientTp() == null && node.getNetwork2Tp() != null) {
208                         interfacesToDelete.add(networkTp + "-ODU4");
209                         interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
210                         connectionNumber = getConnectionNumber(null, node, networkTp, "ODU4");
211                     }
212                     break;
213                 case StringConstants.SERVICE_TYPE_ODUC2:
214                 case StringConstants.SERVICE_TYPE_ODUC3:
215                 case StringConstants.SERVICE_TYPE_ODUC4:
216                     if (node.getClientTp() == null && node.getNetwork2Tp() == null) {
217                         // Service-type can be ODUC2, ODUC3, ODUC4
218                         interfacesToDelete.add(networkTp + "-" + serviceType);
219                         otnLinkTps.add(new LinkTpBuilder()
220                             .setNodeId(nodeId)
221                             .setTpId(networkTp)
222                             .build());
223                     }
224                     if (node.getClientTp() == null && node.getNetwork2Tp() != null) {
225                         interfacesToDelete.add(networkTp + "-" + serviceType);
226                         interfacesToDelete.add(node.getNetwork2Tp() + "-" + serviceType);
227                         connectionNumber = getConnectionNumber(null, node, networkTp, serviceType);
228                     }
229                     break;
230                 case StringConstants.SERVICE_TYPE_10GE:
231                     connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
232                     otnLinkTps.add(new LinkTpBuilder()
233                         .setNodeId(nodeId)
234                         .setTpId(networkTp)
235                         .build());
236                     break;
237                 case StringConstants.SERVICE_TYPE_1GE:
238                     connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
239                     otnLinkTps.add(new LinkTpBuilder()
240                         .setNodeId(nodeId)
241                         .setTpId(networkTp)
242                         .build());
243                     break;
244                 default:
245                     LOG.error("service-type {} not managed yet", serviceType);
246                     String result = serviceType + " is not supported";
247                     results.add(result);
248                     success.set(false);
249                     return;
250             }
251             List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
252             for (String interf : intToDelete == null ? new ArrayList<String>() : intToDelete) {
253                 if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
254                         this.deviceTransactionManager)) {
255                     interfacesToDelete.add(interf);
256                     String supportedInterface = this.openRoadmInterfaces.getSupportedInterface(nodeId, interf);
257                     if (supportedInterface == null) {
258                         continue;
259                     }
260                     // Here ODUC can be ODUC2, ODUC3, ODUC4
261                     if ((input.getServiceRate().intValue() == 100 && !supportedInterface.contains("ODUC"))
262                         || (input.getServiceRate().intValue() != 100 && !supportedInterface.contains("ODU4"))) {
263                         interfacesToDelete.add(supportedInterface);
264                     }
265                 }
266             }
267
268             for (String interfaceId : interfacesToDelete) {
269                 try {
270                     this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
271                 } catch (OpenRoadmInterfaceException e) {
272                     String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
273                     success.set(false);
274                     LOG.error(result, e);
275                     results.add(result);
276                 }
277             }
278         }));
279         try {
280             forkJoinTask.get();
281         } catch (InterruptedException | ExecutionException e) {
282             LOG.error("Error while deleting service paths!", e);
283             return new OtnServicePathOutputBuilder()
284                 .setResult("Error while deleting service paths!")
285                 .setSuccess(false)
286                 .build();
287         }
288         forkJoinPool.shutdown();
289         return new OtnServicePathOutputBuilder()
290                 .setSuccess(success.get())
291                 .setLinkTp(otnLinkTps)
292                 .setResult(
293                     results.isEmpty()
294                         ? "Request processed"
295                         : String.join("\n", results))
296                 .build();
297     }
298
299     private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
300         List<String> list1 = new ArrayList<>();
301         List<String> list2 = new ArrayList<>(Arrays.asList("x"));
302         if (node.getClientTp() != null) {
303             list1.addAll(Arrays.asList(node.getClientTp(), oduType));
304             list2.addAll(Arrays.asList(networkTp, oduType));
305         } else if (node.getNetwork2Tp() != null) {
306             list1.addAll(Arrays.asList(networkTp, oduType));
307             list2.addAll(Arrays.asList(node.getNetwork2Tp(), oduType));
308         } else {
309             return "";
310         }
311         if (serviceName != null) {
312             list1.add(serviceName);
313             list2.add(serviceName);
314         }
315         list1.addAll(list2);
316         return String.join("-", list1);
317     }
318
319     private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
320             throws OpenRoadmInterfaceException {
321         return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
322     }
323
324     private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
325             CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
326         for (Nodes node : input.getNodes()) {
327             AEndApiInfo apiInfoA = null;
328             ZEndApiInfo apiInfoZ = null;
329             if (input.getAEndApiInfo() != null && input.getAEndApiInfo().getNodeId().contains(node.getNodeId())) {
330                 apiInfoA = input.getAEndApiInfo();
331             }
332             if (input.getZEndApiInfo() != null && input.getZEndApiInfo().getNodeId().contains(node.getNodeId())) {
333                 apiInfoZ = input.getZEndApiInfo();
334             }
335             // check if the node is mounted or not?
336             List<String> createdEthInterfaces = new ArrayList<>();
337             List<String> createdOduInterfaces = new ArrayList<>();
338             switch (input.getServiceRate().intValue()) {
339                 case 1:
340                     LOG.info("Input service is 1G");
341                     if (node.getClientTp() != null) {
342                         createdEthInterfaces.add(
343                             openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
344                                 node.getClientTp()));
345                         createdOduInterfaces.add(
346                             // suppporting interface?, payload ?
347                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
348                                 input.getServiceName(), false, input.getTribPortNumber(), input.getTribSlot(), apiInfoA,
349                                 apiInfoZ, PT_07));
350                     }
351                     createdOduInterfaces.add(
352                         openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
353                             input.getServiceName(), true, input.getTribPortNumber(), input.getTribSlot(), null, null,
354                             null));
355                     linkTpList.add(
356                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
357                     if (node.getNetwork2Tp() != null) {
358                         createdOduInterfaces.add(
359                             // supporting interface? payload ?
360                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
361                                 node.getNetwork2Tp(), input.getServiceName(), true, input.getTribPortNumber(),
362                                 input.getTribSlot(), null, null, null));
363                         linkTpList.add(
364                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
365                     }
366                     break;
367                 case 10:
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(), false, input.getTribPortNumber(),
376                                 input.getTribSlot(), apiInfoA, apiInfoZ, PT_03));
377                     }
378                     createdOduInterfaces.add(
379                         // supporting interface? payload ?
380                         openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
381                             input.getServiceName(), true, input.getTribPortNumber(), input.getTribSlot(), null,
382                             null, null));
383                     linkTpList.add(
384                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
385                     if (node.getNetwork2Tp() != null) {
386                         createdOduInterfaces.add(
387                             // supporting interface? payload ?
388                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
389                                 node.getNetwork2Tp(), input.getServiceName(), true, input.getTribPortNumber(),
390                                 input.getTribSlot(), null, null, null));
391                         linkTpList.add(
392                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
393                     }
394                     break;
395                 case 100:
396                     LOG.info("Input service is 100G");
397                     // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
398                     // min and max value only, size two)
399                     OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
400                         input.getOpucnTribSlots().get(0).getValue());
401                     OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
402                         input.getOpucnTribSlots().get(1).getValue());
403                     if (node.getClientTp() != null) {
404                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
405                             node.getNodeId(), node.getClientTp()));
406                         // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
407                         createdOduInterfaces.add(
408                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
409                             node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
410                                 maxOpucnTs));
411                     }
412                     // Here payload-type is optional and is not used for interface creation (especially for network)
413                     createdOduInterfaces.add(
414                         openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
415                             node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
416                             maxOpucnTs));
417                     linkTpList.add(
418                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
419                     // Here payload-type is optional and is not used for service creation
420                     // This is needed if there is an intermediate node
421                     if (node.getNetwork2Tp() != null) {
422                         createdOduInterfaces.add(
423                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
424                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
425                                 maxOpucnTs));
426                         linkTpList.add(
427                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
428                     }
429                     break;
430                 default:
431                     LOG.error("service rate {} not managed yet", input.getServiceRate());
432                     return;
433             }
434
435             // implement cross connect
436             List<String> createdConnections = new ArrayList<>();
437             if (!createdOduInterfaces.isEmpty()) {
438                 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
439                 createdConnections.add(connectionNameOpt.get());
440                 LOG.info("Created cross connects");
441             }
442             nodeInterfaces.add(new NodeInterfaceBuilder()
443                     .withKey(new NodeInterfaceKey(node.getNodeId()))
444                     .setNodeId(node.getNodeId())
445                     .setConnectionId(createdConnections)
446                     .setEthInterfaceId(createdEthInterfaces)
447                     .setOduInterfaceId(createdOduInterfaces)
448                     .build());
449         }
450     }
451
452     private void createHighOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
453             CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
454         for (Nodes node : input.nonnullNodes()) {
455             AEndApiInfo apiInfoA = null;
456             ZEndApiInfo apiInfoZ = null;
457             if (input.getAEndApiInfo() != null && input.getAEndApiInfo().getNodeId().contains(node.getNodeId())) {
458                 apiInfoA = input.getAEndApiInfo();
459             }
460             if (input.getZEndApiInfo() != null && input.getZEndApiInfo().getNodeId().contains(node.getNodeId())) {
461                 apiInfoZ = input.getZEndApiInfo();
462             }
463             // check if the node is mounted or not?
464             List<String> createdEthInterfaces = new ArrayList<>();
465             List<String> createdOduInterfaces = new ArrayList<>();
466             switch (input.getServiceRate().intValue()) {
467                 case 100:
468                     LOG.info("Input service is 100G");
469                     if (node.getClientTp() != null && node.getNetwork2Tp() == null) {
470                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
471                             node.getNodeId(), node.getClientTp()));
472                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
473                                 node.getNodeId(), node.getClientTp(), false, apiInfoA, apiInfoZ, "21"));
474                         // supporting interface? payload ?
475                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
476                                 node.getNodeId(), node.getNetworkTp(), true, null, null, null));
477                         linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getClientTp())
478                                 .build());
479                     }
480                     if (node.getClientTp() == null && node.getNetwork2Tp() == null) {
481                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
482                             node.getNodeId(), node.getNetworkTp(), false, apiInfoA, apiInfoZ, "21"));
483                         linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp())
484                             .build());
485                     }
486                     if (node.getClientTp() == null && node.getNetwork2Tp() != null) {
487                         // supporting interface? payload ?
488                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
489                             node.getNodeId(), node.getNetworkTp(), true, null, null, null));
490                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
491                                 node.getNodeId(), node.getNetwork2Tp(), true, null, null, null));
492                     }
493                     break;
494                 default:
495                     LOG.error("service rate {} not managed yet", input.getServiceRate());
496                     return;
497             }
498
499             // implement cross connect
500             List<String> createdConnections = new ArrayList<>();
501             if (createdOduInterfaces.size() == 2) {
502                 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
503                 createdConnections.add(connectionNameOpt.get());
504                 LOG.info("Created cross connects");
505             }
506             nodeInterfaces.add(new NodeInterfaceBuilder()
507                     .withKey(new NodeInterfaceKey(node.getNodeId()))
508                     .setNodeId(node.getNodeId())
509                     .setConnectionId(createdConnections)
510                     .setEthInterfaceId(createdEthInterfaces)
511                     .setOduInterfaceId(createdOduInterfaces)
512                     .build());
513         }
514     }
515
516     private void createOducnTtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
517         CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
518         if (input.getNodes() == null) {
519             return;
520         }
521         if (input.getServiceRate() == null) {
522             LOG.error("Missing service rate for ODUCn interface");
523             return;
524         }
525         LOG.info("Creation of ODUCn TTP interface in OTN service path {}", input);
526         for (int i = 0; i < input.getNodes().size(); i++) {
527             Nodes node = input.getNodes().get(i);
528             // Based on the service rate, we will know if it is a OTUC4, OTUC3 or OTUC2
529             String supportingOtuInterface = node.getNetworkTp();
530             boolean serviceRateNotSupp = false;
531
532             switch (input.getServiceRate().intValue()) {
533                 case 200:
534                     supportingOtuInterface += "-OTUC2";
535                     break;
536                 case 300:
537                     supportingOtuInterface += "-OTUC3";
538                     break;
539                 case 400:
540                     supportingOtuInterface += "-OTUC4";
541                     break;
542                 default:
543                     serviceRateNotSupp = true;
544                     break;
545             }
546             if (serviceRateNotSupp) {
547                 LOG.error("Service rate {} is not supported", input.getServiceRate());
548             }
549
550             Nodes tgtNode =
551                 i + 1 == input.getNodes().size()
552                 // For the end node, tgtNode becomes the first node in the list
553                     ? input.getNodes().get(0)
554                     : input.getNodes().get(i + 1);
555
556             nodeInterfaces.add(new NodeInterfaceBuilder()
557                     .withKey(new NodeInterfaceKey(node.getNodeId()))
558                     .setNodeId(node.getNodeId())
559                     .setOduInterfaceId(List.of(
560                         // though this is odu, actually it has ODUCn interfaces
561                         openRoadmInterfaceFactory.createOpenRoadmOtnOducnInterface(node.getNodeId(),
562                             node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
563                     .build());
564             linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
565         }
566     }
567 }