2 * Copyright © 2019 AT&T and others. All rights reserved.
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
8 package org.opendaylight.transportpce.renderer.provisiondevice;
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;
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 java.util.stream.Collectors;
24 import org.opendaylight.transportpce.common.StringConstants;
25 import org.opendaylight.transportpce.common.crossconnect.CrossConnect;
26 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
27 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
28 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
29 import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
30 import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathInput;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathOutput;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev210618.OtnServicePathOutputBuilder;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OpucnTribSlotDef;
35 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
36 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTpBuilder;
37 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.node.interfaces.NodeInterface;
38 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.node.interfaces.NodeInterfaceBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.node.interfaces.NodeInterfaceKey;
40 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.otn.renderer.nodes.Nodes;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService {
46 private static final Logger LOG = LoggerFactory.getLogger(OtnDeviceRendererServiceImpl.class);
47 private static final String PT_03 = "03";
48 private static final String PT_07 = "07";
49 private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory;
50 private final CrossConnect crossConnect;
51 private final OpenRoadmInterfaces openRoadmInterfaces;
52 private final DeviceTransactionManager deviceTransactionManager;
53 private final NetworkModelService networkModelService;
55 public OtnDeviceRendererServiceImpl(OpenRoadmInterfaceFactory openRoadmInterfaceFactory, CrossConnect crossConnect,
56 OpenRoadmInterfaces openRoadmInterfaces,
57 DeviceTransactionManager deviceTransactionManager,
58 NetworkModelService networkModelService) {
59 this.openRoadmInterfaceFactory = openRoadmInterfaceFactory;
60 this.crossConnect = crossConnect;
61 this.openRoadmInterfaces = openRoadmInterfaces;
62 this.deviceTransactionManager = deviceTransactionManager;
63 this.networkModelService = networkModelService;
66 //TODO Align log messages and returned results messages
68 public OtnServicePathOutput setupOtnServicePath(OtnServicePathInput input, String serviceType) {
69 LOG.info("Calling setup otn-service path");
70 if (input.getServiceFormat() == null || input.getServiceRate() == null) {
71 return new OtnServicePathOutputBuilder()
73 .setResult("Error - service-type and service-rate must be present")
76 List<NodeInterface> nodeInterfaces = new ArrayList<>();
77 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
79 switch (serviceType) {
80 case StringConstants.SERVICE_TYPE_1GE:
81 case StringConstants.SERVICE_TYPE_10GE:
82 case StringConstants.SERVICE_TYPE_100GE_M:
83 LOG.info("Calling Node interfaces {} {} {} {} {} {} {}",
84 input.getServiceRate(), input.getEthernetEncoding(),
85 input.getServiceFormat(), input.getOperation(), input.getTribPortNumber(),
86 input.getTribSlot(), input.getNodes());
87 if (input.getNodes() != null) {
88 createLowOrderInterfaces(input, nodeInterfaces, otnLinkTps);
89 LOG.info("Node interfaces created just fine ");
92 case StringConstants.SERVICE_TYPE_ODU4:
93 createODU4TtpInterface(input, nodeInterfaces, otnLinkTps);
95 case StringConstants.SERVICE_TYPE_ODUC4:
96 createOduc4TtpInterface(input, nodeInterfaces, otnLinkTps);
98 case StringConstants.SERVICE_TYPE_100GE_S:
99 LOG.info("Calling Node interface for service-type {}", serviceType);
100 if (input.getNodes() != null) {
101 createHighOrderInterfaces(input, nodeInterfaces, otnLinkTps);
102 LOG.info("Node interfaces created");
106 LOG.error("Service-type {} not managed yet", serviceType);
107 return new OtnServicePathOutputBuilder()
109 .setResult("Service-type not managed")
112 } catch (OpenRoadmInterfaceException e) {
113 LOG.warn("Service path set-up failed", e);
114 Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
115 for (NodeInterface nodeInterface : nodeInterfaces) {
116 if (nodeInterface != null) {
117 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
120 //TODO check if we need to set a NodeInterface Map in the result in that case
121 return new OtnServicePathOutputBuilder()
123 .setNodeInterface(nodeInterfacesMap)
124 .setResult("Service path set-up failed")
125 .setLinkTp(otnLinkTps)
128 LOG.info("Service path set-up succeed");
129 List<String> results = new ArrayList<>();
130 Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
131 for (NodeInterface nodeInterface : nodeInterfaces) {
132 if (nodeInterface != null) {
133 results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId());
134 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
137 return new OtnServicePathOutputBuilder()
139 .setNodeInterface(nodeInterfacesMap)
140 .setResult(String.join("\n", results))
141 .setLinkTp(otnLinkTps)
145 @SuppressWarnings("rawtypes")
146 // FIXME check if the ForkJoinTask raw type can be avoided
147 // Raw types use are discouraged since they lack type safety.
148 // Resulting Problems are observed at run time and not at compile time
149 public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input, String serviceType) {
150 if (input.getNodes() == null) {
151 LOG.error("Unable to delete otn service path. input nodes = null");
152 return new OtnServicePathOutputBuilder()
153 .setResult("Unable to delete otn service path. input nodes = null")
157 List<Nodes> nodes = input.getNodes();
158 AtomicBoolean success = new AtomicBoolean(true);
159 ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
160 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
161 ForkJoinPool forkJoinPool = new ForkJoinPool();
162 ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
163 String nodeId = node.getNodeId();
164 LOG.info("Deleting service setup on node {}", nodeId);
165 String networkTp = node.getNetworkTp();
166 if (networkTp == null || input.getServiceRate() == null || input.getServiceFormat() == null) {
167 LOG.error("destination ({}) or service-rate ({}) or service-format ({}) is null.",
168 networkTp, input.getServiceRate(), input.getServiceFormat());
171 if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
172 String result = nodeId + " is not mounted on the controller";
176 forkJoinPool.shutdown();
178 // TODO should deletion end here?
180 // if the node is currently mounted then proceed.
181 List<String> interfacesToDelete = new LinkedList<>();
182 String connectionNumber = "";
183 switch (serviceType) {
184 case StringConstants.SERVICE_TYPE_100GE_S:
185 connectionNumber = getConnectionNumber(null, node, networkTp, "ODU4");
187 case StringConstants.SERVICE_TYPE_100GE_M:
188 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU4");
190 case StringConstants.SERVICE_TYPE_ODU4:
191 interfacesToDelete.add(networkTp + "-ODU4");
192 if (node.getNetwork2Tp() != null) {
193 interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
196 case StringConstants.SERVICE_TYPE_ODUC4:
197 interfacesToDelete.add(networkTp + "-ODUC4");
198 if (node.getNetwork2Tp() != null) {
199 interfacesToDelete.add(node.getNetwork2Tp() + "-ODUC4");
202 case StringConstants.SERVICE_TYPE_10GE:
203 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
205 case StringConstants.SERVICE_TYPE_1GE:
206 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
209 LOG.error("service-type {} not managed yet", serviceType);
210 String result = serviceType + " is not supported";
215 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
216 for (String interf : intToDelete == null ? new ArrayList<String>() : intToDelete) {
217 if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
218 this.deviceTransactionManager)) {
219 interfacesToDelete.add(interf);
220 String supportedInterface = this.openRoadmInterfaces.getSupportedInterface(nodeId, interf);
221 if (supportedInterface == null) {
224 if ((input.getServiceRate().intValue() == 100 && !supportedInterface.contains("ODUC4"))
225 || (input.getServiceRate().intValue() != 100 && !supportedInterface.contains("ODU4"))) {
226 interfacesToDelete.add(supportedInterface);
231 for (String interfaceId : interfacesToDelete) {
233 this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
234 } catch (OpenRoadmInterfaceException e) {
235 String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
237 LOG.error(result, e);
241 List<String> interList =
242 interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK")).collect(Collectors.toList());
243 if (!interList.isEmpty()) {
244 for (String inter : interList) {
245 otnLinkTps.add(new LinkTpBuilder()
247 .setTpId(inter.split("-ODU")[0])
254 } catch (InterruptedException | ExecutionException e) {
255 LOG.error("Error while deleting service paths!", e);
256 return new OtnServicePathOutputBuilder()
257 .setResult("Error while deleting service paths!")
261 forkJoinPool.shutdown();
262 return new OtnServicePathOutputBuilder()
263 .setSuccess(success.get())
264 .setLinkTp(otnLinkTps)
267 ? "Request processed"
268 : String.join("\n", results))
272 private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
273 List<String> list1 = new ArrayList<>();
274 List<String> list2 = new ArrayList<>(Arrays.asList("x"));
275 if (node.getClientTp() != null) {
276 list1.addAll(Arrays.asList(node.getClientTp(), oduType));
277 list2.addAll(Arrays.asList(networkTp, oduType));
278 } else if (node.getNetwork2Tp() != null) {
279 list1.addAll(Arrays.asList(networkTp, oduType));
280 list2.addAll(Arrays.asList(node.getNetwork2Tp(), oduType));
284 if (serviceName != null) {
285 list1.add(serviceName);
286 list2.add(serviceName);
289 return String.join("-", list1);
292 private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
293 throws OpenRoadmInterfaceException {
294 return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
297 private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
298 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
299 for (Nodes node : input.getNodes()) {
300 // check if the node is mounted or not?
301 List<String> createdEthInterfaces = new ArrayList<>();
302 List<String> createdOduInterfaces = new ArrayList<>();
303 switch (input.getServiceRate().intValue()) {
305 LOG.info("Input service is 1G");
306 if (node.getClientTp() != null) {
307 createdEthInterfaces.add(
308 openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
309 node.getClientTp()));
310 createdOduInterfaces.add(
311 // suppporting interface?, payload ?
312 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
313 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
315 createdOduInterfaces.add(
316 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
317 input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
319 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
320 if (node.getNetwork2Tp() != null) {
321 createdOduInterfaces.add(
322 // supporting interface? payload ?
323 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
324 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
325 input.getTribSlot()));
327 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
331 LOG.info("Input service is 10G");
332 if (node.getClientTp() != null) {
333 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
334 node.getNodeId(), node.getClientTp()));
335 createdOduInterfaces.add(
336 // suppporting interface?, payload ?
337 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
338 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
339 input.getTribSlot()));
341 createdOduInterfaces.add(
342 // supporting interface? payload ?
343 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
344 input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
346 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
347 if (node.getNetwork2Tp() != null) {
348 createdOduInterfaces.add(
349 // supporting interface? payload ?
350 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
351 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
352 input.getTribSlot()));
354 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
358 LOG.info("Input service is 100G");
359 // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
360 // min and max value only, size two)
361 OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
362 input.getOpucnTribSlots().get(0).getValue());
363 OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
364 input.getOpucnTribSlots().get(1).getValue());
365 if (node.getClientTp() != null) {
366 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
367 node.getNodeId(), node.getClientTp()));
368 // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
369 createdOduInterfaces.add(
370 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
371 node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
374 // Here payload-type is optional and is not used for interface creation (especially for network)
375 createdOduInterfaces.add(
376 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
377 node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
380 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
381 // Here payload-type is optional and is not used for service creation
382 // This is needed if there is an intermediate node
383 if (node.getNetwork2Tp() != null) {
384 createdOduInterfaces.add(
385 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
386 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
389 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
393 LOG.error("service rate {} not managed yet", input.getServiceRate());
397 // implement cross connect
398 List<String> createdConnections = new ArrayList<>();
399 if (!createdOduInterfaces.isEmpty()) {
400 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
401 createdConnections.add(connectionNameOpt.get());
402 LOG.info("Created cross connects");
404 nodeInterfaces.add(new NodeInterfaceBuilder()
405 .withKey(new NodeInterfaceKey(node.getNodeId()))
406 .setNodeId(node.getNodeId())
407 .setConnectionId(createdConnections)
408 .setEthInterfaceId(createdEthInterfaces)
409 .setOduInterfaceId(createdOduInterfaces)
414 private void createHighOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
415 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
416 for (Nodes node : input.getNodes()) {
417 // check if the node is mounted or not?
418 List<String> createdEthInterfaces = new ArrayList<>();
419 List<String> createdOduInterfaces = new ArrayList<>();
420 switch (input.getServiceRate().intValue()) {
422 LOG.info("Input service is 100G");
423 if (node.getClientTp() != null) {
424 String supEthInter = openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
425 node.getNodeId(), node.getClientTp());
426 createdEthInterfaces.add(supEthInter);
427 createdOduInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(
428 node.getNodeId(), node.getClientTp(), false, supEthInter));
430 createdOduInterfaces.add(
431 // supporting interface? payload ?
432 openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(node.getNodeId(), node.getNetworkTp(),
435 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
436 if (node.getNetwork2Tp() != null) {
437 createdOduInterfaces.add(
438 // supporting interface? payload ?
439 openRoadmInterfaceFactory.createOpenRoadmOdu4HOInterface(node.getNodeId(),
440 node.getNetwork2Tp(), true, null));
442 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
446 LOG.error("service rate {} not managed yet", input.getServiceRate());
450 // implement cross connect
451 List<String> createdConnections = new ArrayList<>();
452 if (!createdOduInterfaces.isEmpty()) {
453 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
454 createdConnections.add(connectionNameOpt.get());
455 LOG.info("Created cross connects");
457 nodeInterfaces.add(new NodeInterfaceBuilder()
458 .withKey(new NodeInterfaceKey(node.getNodeId()))
459 .setNodeId(node.getNodeId())
460 .setConnectionId(createdConnections)
461 .setEthInterfaceId(createdEthInterfaces)
462 .setOduInterfaceId(createdOduInterfaces)
467 private void createOduc4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
468 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
469 if (input.getNodes() == null) {
472 LOG.info("Creation of ODUC4 TTP interface in OTN service path {}", input);
473 for (int i = 0; i < input.getNodes().size(); i++) {
474 Nodes node = input.getNodes().get(i);
475 String supportingOtuInterface = node.getNetworkTp() + "-OTUC4";
478 i + 1 == input.getNodes().size()
479 // For the end node, tgtNode becomes the first node in the list
480 ? input.getNodes().get(0)
481 : input.getNodes().get(i + 1);
483 nodeInterfaces.add(new NodeInterfaceBuilder()
484 .withKey(new NodeInterfaceKey(node.getNodeId()))
485 .setNodeId(node.getNodeId())
486 .setOduInterfaceId(List.of(
487 // though this is odu, actually it has ODUC4 interfaces
488 openRoadmInterfaceFactory.createOpenRoadmOtnOduc4Interface(node.getNodeId(),
489 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
491 linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
495 private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
496 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
497 if (input.getNodes() == null) {
500 LOG.info("Creation of ODU4 tp interface {}", input);
501 for (int i = 0; i < input.getNodes().size(); i++) {
502 Nodes node = input.getNodes().get(i);
503 String supportingOtuInterface = node.getNetworkTp() + "-OTU";
506 i + 1 == input.getNodes().size()
507 // For the end node, tgtNode becomes the first node in the list
508 ? input.getNodes().get(0)
509 : input.getNodes().get(i + 1);
511 nodeInterfaces.add(new NodeInterfaceBuilder()
512 .withKey(new NodeInterfaceKey(node.getNodeId()))
513 .setNodeId(node.getNodeId())
514 .setOduInterfaceId(List.of(
515 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
516 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
518 linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());