Update project version for Chlorine release train
[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.HashSet;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.Set;
19 import java.util.concurrent.ConcurrentLinkedQueue;
20 import java.util.concurrent.CopyOnWriteArrayList;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.ForkJoinPool;
23 import java.util.concurrent.ForkJoinTask;
24 import java.util.concurrent.atomic.AtomicBoolean;
25 import org.opendaylight.transportpce.common.StringConstants;
26 import org.opendaylight.transportpce.common.crossconnect.CrossConnect;
27 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
28 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
29 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
30 import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
31 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathInput;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathOutput;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.OtnServicePathOutputBuilder;
35 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.AEndApiInfo;
36 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.ZEndApiInfo;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev210924.OpucnTribSlotDef;
38 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.link.tp.LinkTp;
39 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.link.tp.LinkTpBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.node.interfaces.NodeInterface;
41 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.node.interfaces.NodeInterfaceBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.node.interfaces.NodeInterfaceKey;
43 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210930.otn.renderer.nodes.Nodes;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47
48 public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService {
49     private static final Logger LOG = LoggerFactory.getLogger(OtnDeviceRendererServiceImpl.class);
50     private static final String PT_03 = "03";
51     private static final String PT_07 = "07";
52     private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
53     private final CrossConnect crossConnect;
54     private final OpenRoadmInterfaces openRoadmInterfaces;
55     private final DeviceTransactionManager deviceTransactionManager;
56
57     public OtnDeviceRendererServiceImpl(OpenRoadmInterfaceFactory openRoadmInterfaceFactory, CrossConnect crossConnect,
58                                         OpenRoadmInterfaces openRoadmInterfaces,
59                                         DeviceTransactionManager deviceTransactionManager,
60                                         NetworkModelService networkModelService) {
61         this.openRoadmInterfaceFactory = openRoadmInterfaceFactory;
62         this.crossConnect = crossConnect;
63         this.openRoadmInterfaces = openRoadmInterfaces;
64         this.deviceTransactionManager = deviceTransactionManager;
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(node, networkTp, "ODU4");
191                     break;
192                 case StringConstants.SERVICE_TYPE_100GE_M:
193                     connectionNumber = getConnectionNumber(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(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(node, networkTp, serviceType);
228                     }
229                     break;
230                 case StringConstants.SERVICE_TYPE_10GE:
231                     connectionNumber = getConnectionNumber(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(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(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         list1.addAll(list2);
312         return String.join("-", list1);
313     }
314
315     private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
316             throws OpenRoadmInterfaceException {
317         return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
318     }
319
320     private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
321             CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
322         for (Nodes node : input.getNodes()) {
323             AEndApiInfo apiInfoA = null;
324             ZEndApiInfo apiInfoZ = null;
325             if (input.getAEndApiInfo() != null && input.getAEndApiInfo().getNodeId().contains(node.getNodeId())) {
326                 apiInfoA = input.getAEndApiInfo();
327             }
328             if (input.getZEndApiInfo() != null && input.getZEndApiInfo().getNodeId().contains(node.getNodeId())) {
329                 apiInfoZ = input.getZEndApiInfo();
330             }
331             // check if the node is mounted or not?
332             Set<String> createdEthInterfaces = new HashSet<>();
333             Set<String> createdOduInterfaces = new HashSet<>();
334             switch (input.getServiceRate().intValue()) {
335                 case 1:
336                     LOG.info("Input service is 1G");
337                     if (node.getClientTp() != null) {
338                         createdEthInterfaces.add(
339                             openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
340                                 node.getClientTp()));
341                         createdOduInterfaces.add(
342                             // suppporting interface?, payload ?
343                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
344                                 input.getServiceName(), false, input.getTribPortNumber(), input.getTribSlot(), apiInfoA,
345                                 apiInfoZ, PT_07));
346                     }
347                     createdOduInterfaces.add(
348                         openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
349                             input.getServiceName(), true, input.getTribPortNumber(), input.getTribSlot(), null, null,
350                             null));
351                     linkTpList.add(
352                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
353                     if (node.getNetwork2Tp() != null) {
354                         createdOduInterfaces.add(
355                             // supporting interface? payload ?
356                             openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
357                                 node.getNetwork2Tp(), input.getServiceName(), true, input.getTribPortNumber(),
358                                 input.getTribSlot(), null, null, null));
359                         linkTpList.add(
360                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
361                     }
362                     break;
363                 case 10:
364                     LOG.info("Input service is 10G");
365                     if (node.getClientTp() != null) {
366                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
367                             node.getNodeId(), node.getClientTp()));
368                         createdOduInterfaces.add(
369                             // suppporting interface?, payload ?
370                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
371                                 node.getClientTp(),  false, input.getTribPortNumber(),
372                                 input.getTribSlot(), apiInfoA, apiInfoZ, PT_03));
373                     }
374                     createdOduInterfaces.add(
375                         // supporting interface? payload ?
376                         openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
377                              true, input.getTribPortNumber(), input.getTribSlot(), null,
378                             null, null));
379                     linkTpList.add(
380                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
381                     if (node.getNetwork2Tp() != null) {
382                         createdOduInterfaces.add(
383                             // supporting interface? payload ?
384                             openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
385                                 node.getNetwork2Tp(), true, input.getTribPortNumber(),
386                                 input.getTribSlot(), null, null, null));
387                         linkTpList.add(
388                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
389                     }
390                     break;
391                 case 100:
392                     LOG.info("Input service is 100G");
393                     // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
394                     // min and max value only, size two)
395                     OpucnTribSlotDef minOpucnTs = input.getOpucnTribSlots().stream()
396                         .min((ts1, ts2) -> ts1.getValue().compareTo(ts2.getValue())).get();
397                     OpucnTribSlotDef maxOpucnTs = input.getOpucnTribSlots().stream()
398                         .max((ts1, ts2) -> ts1.getValue().compareTo(ts2.getValue())).get();
399                     if (node.getClientTp() != null) {
400                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
401                             node.getNodeId(), node.getClientTp()));
402                         // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
403                         createdOduInterfaces.add(
404                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
405                             node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
406                                 maxOpucnTs));
407                     }
408                     // Here payload-type is optional and is not used for interface creation (especially for network)
409                     createdOduInterfaces.add(
410                         openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
411                             node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
412                             maxOpucnTs));
413                     linkTpList.add(
414                         new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
415                     // Here payload-type is optional and is not used for service creation
416                     // This is needed if there is an intermediate node
417                     if (node.getNetwork2Tp() != null) {
418                         createdOduInterfaces.add(
419                             openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
420                                 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
421                                 maxOpucnTs));
422                         linkTpList.add(
423                             new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
424                     }
425                     break;
426                 default:
427                     LOG.error("service rate {} not managed yet", input.getServiceRate());
428                     return;
429             }
430
431             // implement cross connect
432             Set<String> createdConnections = new HashSet<>();
433             if (!createdOduInterfaces.isEmpty()) {
434                 Optional<String> connectionNameOpt = postCrossConnect(new ArrayList<>(createdOduInterfaces), node);
435                 createdConnections.add(connectionNameOpt.get());
436                 LOG.info("Created cross connects");
437             }
438             nodeInterfaces.add(new NodeInterfaceBuilder()
439                     .withKey(new NodeInterfaceKey(node.getNodeId()))
440                     .setNodeId(node.getNodeId())
441                     .setConnectionId(createdConnections)
442                     .setEthInterfaceId(createdEthInterfaces)
443                     .setOduInterfaceId(createdOduInterfaces)
444                     .build());
445         }
446     }
447
448     private void createHighOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
449             CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
450         for (Nodes node : input.nonnullNodes()) {
451             AEndApiInfo apiInfoA = null;
452             ZEndApiInfo apiInfoZ = null;
453             if (input.getAEndApiInfo() != null && input.getAEndApiInfo().getNodeId().contains(node.getNodeId())) {
454                 apiInfoA = input.getAEndApiInfo();
455             }
456             if (input.getZEndApiInfo() != null && input.getZEndApiInfo().getNodeId().contains(node.getNodeId())) {
457                 apiInfoZ = input.getZEndApiInfo();
458             }
459             // check if the node is mounted or not?
460             Set<String> createdEthInterfaces = new HashSet<>();
461             Set<String> createdOduInterfaces = new HashSet<>();
462             switch (input.getServiceRate().intValue()) {
463                 case 100:
464                     LOG.info("Input service is 100G");
465                     if (node.getClientTp() != null && node.getNetwork2Tp() == null) {
466                         createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
467                             node.getNodeId(), node.getClientTp()));
468                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
469                                 node.getNodeId(), node.getClientTp(), false, apiInfoA, apiInfoZ, "21"));
470                         // supporting interface? payload ?
471                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
472                                 node.getNodeId(), node.getNetworkTp(), true, null, null, null));
473                         linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getClientTp())
474                                 .build());
475                     }
476                     if (node.getClientTp() == null && node.getNetwork2Tp() == null) {
477                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
478                             node.getNodeId(), node.getNetworkTp(), false, apiInfoA, apiInfoZ, "21"));
479                         linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp())
480                             .build());
481                     }
482                     if (node.getClientTp() == null && node.getNetwork2Tp() != null) {
483                         // supporting interface? payload ?
484                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
485                             node.getNodeId(), node.getNetworkTp(), true, null, null, null));
486                         createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
487                                 node.getNodeId(), node.getNetwork2Tp(), true, null, null, null));
488                     }
489                     break;
490                 default:
491                     LOG.error("service rate {} not managed yet", input.getServiceRate());
492                     return;
493             }
494
495             // implement cross connect
496             Set<String> createdConnections = new HashSet<>();
497             if (createdOduInterfaces.size() == 2) {
498                 Optional<String> connectionNameOpt = postCrossConnect(new ArrayList<>(createdOduInterfaces), node);
499                 createdConnections.add(connectionNameOpt.get());
500                 LOG.info("Created cross connects");
501             }
502             nodeInterfaces.add(new NodeInterfaceBuilder()
503                     .withKey(new NodeInterfaceKey(node.getNodeId()))
504                     .setNodeId(node.getNodeId())
505                     .setConnectionId(createdConnections)
506                     .setEthInterfaceId(createdEthInterfaces)
507                     .setOduInterfaceId(createdOduInterfaces)
508                     .build());
509         }
510     }
511
512     private void createOducnTtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
513         CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
514         if (input.getNodes() == null) {
515             return;
516         }
517         if (input.getServiceRate() == null) {
518             LOG.error("Missing service rate for ODUCn interface");
519             return;
520         }
521         LOG.info("Creation of ODUCn TTP interface in OTN service path {}", input);
522         for (int i = 0; i < input.getNodes().size(); i++) {
523             Nodes node = input.getNodes().get(i);
524             // Based on the service rate, we will know if it is a OTUC4, OTUC3 or OTUC2
525             String supportingOtuInterface = node.getNetworkTp();
526             boolean serviceRateNotSupp = false;
527
528             switch (input.getServiceRate().intValue()) {
529                 case 200:
530                     supportingOtuInterface += "-OTUC2";
531                     break;
532                 case 300:
533                     supportingOtuInterface += "-OTUC3";
534                     break;
535                 case 400:
536                     supportingOtuInterface += "-OTUC4";
537                     break;
538                 default:
539                     serviceRateNotSupp = true;
540                     break;
541             }
542             if (serviceRateNotSupp) {
543                 LOG.error("Service rate {} is not supported", input.getServiceRate());
544             }
545
546             Nodes tgtNode =
547                 i + 1 == input.getNodes().size()
548                 // For the end node, tgtNode becomes the first node in the list
549                     ? input.getNodes().get(0)
550                     : input.getNodes().get(i + 1);
551
552             nodeInterfaces.add(new NodeInterfaceBuilder()
553                     .withKey(new NodeInterfaceKey(node.getNodeId()))
554                     .setNodeId(node.getNodeId())
555                     .setOduInterfaceId(Set.of(
556                         // though this is odu, actually it has ODUCn interfaces
557                         openRoadmInterfaceFactory.createOpenRoadmOtnOducnInterface(node.getNodeId(),
558                             node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
559                     .build());
560             linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
561         }
562     }
563 }