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