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.HashMap;
12 import java.util.LinkedList;
13 import java.util.List;
15 import java.util.Optional;
16 import java.util.concurrent.ConcurrentLinkedQueue;
17 import java.util.concurrent.CopyOnWriteArrayList;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.ForkJoinPool;
20 import java.util.concurrent.ForkJoinTask;
21 import java.util.concurrent.atomic.AtomicBoolean;
22 import java.util.stream.Collectors;
23 import org.opendaylight.transportpce.common.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.common.service.ServiceTypes;
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;
67 public OtnServicePathOutput setupOtnServicePath(OtnServicePathInput input) {
68 LOG.info("Calling setup otn-service path");
69 boolean success = true;
70 List<NodeInterface> nodeInterfaces = new ArrayList<>();
71 List<String> results = new ArrayList<>();
72 if (input.getServiceFormat() == null || input.getServiceRate() == null) {
73 OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder()
75 .setResult("Error - service-type and service-rate must be presents");
76 return otnServicePathOutputBuilder.build();
78 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
79 String serviceType = ServiceTypes.getOtnServiceType(input.getServiceFormat(), input.getServiceRate());
80 switch (serviceType) {
81 case StringConstants.SERVICE_TYPE_1GE:
82 case StringConstants.SERVICE_TYPE_10GE:
83 case StringConstants.SERVICE_TYPE_100GE_M:
85 LOG.info("Calling Node interfaces {} {} {} {} {} {} {}",
86 input.getServiceRate(), input.getEthernetEncoding(),
87 input.getServiceFormat(), input.getOperation(), input.getTribPortNumber(),
88 input.getTribSlot(), input.getNodes());
89 if (input.getNodes() != null) {
90 createLowOrderInterfaces(input, nodeInterfaces, otnLinkTps);
91 LOG.info("Node interfaces created just fine ");
93 } catch (OpenRoadmInterfaceException e) {
94 LOG.warn("Set up service path failed", e);
98 case StringConstants.SERVICE_TYPE_ODU4:
100 createODU4TtpInterface(input, nodeInterfaces, otnLinkTps);
101 } catch (OpenRoadmInterfaceException e) {
102 LOG.warn("Set up service path failed", e);
106 case StringConstants.SERVICE_TYPE_ODUC4:
108 createOduc4TtpInterface(input, nodeInterfaces, otnLinkTps);
109 } catch (OpenRoadmInterfaceException e) {
110 LOG.warn("Set up service path failed", e);
115 LOG.error("service-type {} not managed yet", serviceType);
119 LOG.info("Result is success");
120 for (NodeInterface nodeInterface : nodeInterfaces) {
121 results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId());
124 Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
125 for (NodeInterface nodeInterface : nodeInterfaces) {
126 if (nodeInterface != null) {
127 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
130 OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder()
132 .setNodeInterface(nodeInterfacesMap)
133 .setResult(String.join("\n", results))
134 .setLinkTp(otnLinkTps);
135 return otnServicePathOutputBuilder.build();
138 public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) {
139 if (input.getNodes() == null) {
140 LOG.error("Unable to delete otn service path. input nodes = null");
141 return new OtnServicePathOutputBuilder().setResult("Unable to delete otn service path. input nodes = null")
142 .setSuccess(false).build();
144 List<Nodes> nodes = input.getNodes();
145 AtomicBoolean success = new AtomicBoolean(true);
146 ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
147 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
148 ForkJoinPool forkJoinPool = new ForkJoinPool();
149 ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
150 List<String> interfacesToDelete = new LinkedList<>();
151 String nodeId = node.getNodeId();
152 LOG.info("Deleting service setup on node {}", nodeId);
153 String networkTp = node.getNetworkTp();
154 if (networkTp == null || input.getServiceRate() == null || input.getServiceFormat() == null) {
155 LOG.error("destination ({}) or service-rate ({}) or service-format ({}) is null.", networkTp,
156 input.getServiceRate(), input.getServiceFormat());
159 // if the node is currently mounted then proceed.
160 if (this.deviceTransactionManager.isDeviceMounted(nodeId)) {
161 String connectionNumber = "";
162 switch (input.getServiceRate().intValue()) {
164 if ("ODU".equals(input.getServiceFormat())) {
165 interfacesToDelete.add(networkTp + "-ODU4");
166 if (node.getNetwork2Tp() != null) {
167 interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
169 } else if ("Ethernet".equals(input.getServiceFormat())) {
170 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU4");
174 if ("ODU".equals(input.getServiceFormat())) {
175 interfacesToDelete.add(networkTp + "-ODUC4");
176 if (node.getNetwork2Tp() != null) {
177 interfacesToDelete.add(node.getNetwork2Tp() + "-ODUC4");
182 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
185 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
188 LOG.error("service rate {} not managed yet", input.getServiceRate());
189 String result = input.getServiceRate() + " is not supported";
194 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
195 if (intToDelete != null) {
196 for (String interf : intToDelete) {
197 if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
198 this.deviceTransactionManager)) {
200 interfacesToDelete.add(interf);
201 String supportedInterface = this.openRoadmInterfaces.getSupportedInterface(nodeId, interf);
202 if (input.getServiceRate().intValue() == 100) {
203 if (!supportedInterface.contains("ODUC4")) {
204 interfacesToDelete.add(supportedInterface);
207 if (!supportedInterface.contains("ODU4")) {
208 interfacesToDelete.add(supportedInterface);
215 String result = nodeId + " is not mounted on the controller";
219 forkJoinPool.shutdown();
221 // TODO should deletion end here?
223 for (String interfaceId : interfacesToDelete) {
225 this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
226 } catch (OpenRoadmInterfaceException e) {
227 String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
229 LOG.error(result, e);
233 List<String> interList = interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK"))
234 .collect(Collectors.toList());
235 if (!interList.isEmpty()) {
236 for (String inter : interList) {
237 String tp = inter.split("-ODU")[0];
238 LinkTp otnLinkTp = new LinkTpBuilder()
242 otnLinkTps.add(otnLinkTp);
248 } catch (InterruptedException | ExecutionException e) {
249 LOG.error("Error while deleting service paths!", e);
250 return new OtnServicePathOutputBuilder().setResult("Error while deleting service paths!")
251 .setSuccess(false).build();
253 forkJoinPool.shutdown();
254 OtnServicePathOutputBuilder delServBldr = new OtnServicePathOutputBuilder()
255 .setSuccess(success.get())
256 .setLinkTp(otnLinkTps);
257 if (results.isEmpty()) {
258 return delServBldr.setResult("Request processed").build();
260 return delServBldr.setResult(String.join("\n", results)).build();
264 private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
265 if (node.getClientTp() != null) {
266 return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName);
267 } else if (node.getNetwork2Tp() != null) {
268 return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName);
274 private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
275 throws OpenRoadmInterfaceException {
276 return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
279 private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
280 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
281 for (Nodes node : input.getNodes()) {
282 // check if the node is mounted or not?
283 List<String> createdEthInterfaces = new ArrayList<>();
284 List<String> createdOduInterfaces = new ArrayList<>();
285 switch (input.getServiceRate().intValue()) {
287 LOG.info("Input service is 1G");
288 if (node.getClientTp() != null) {
289 createdEthInterfaces.add(
290 openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
291 node.getClientTp()));
292 createdOduInterfaces.add(
293 // suppporting interface?, payload ?
294 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
295 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
297 createdOduInterfaces.add(
298 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
299 input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
300 LinkTp otnLinkTp = new LinkTpBuilder()
301 .setNodeId(node.getNodeId())
302 .setTpId(node.getNetworkTp())
304 linkTpList.add(otnLinkTp);
305 if (node.getNetwork2Tp() != null) {
306 createdOduInterfaces.add(
307 // supporting interface? payload ?
308 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
309 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
310 input.getTribSlot()));
311 LinkTp otnLinkTp2 = new LinkTpBuilder()
312 .setNodeId(node.getNodeId())
313 .setTpId(node.getNetworkTp())
315 linkTpList.add(otnLinkTp2);
319 LOG.info("Input service is 10G");
320 if (node.getClientTp() != null) {
321 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
322 node.getNodeId(), node.getClientTp()));
323 createdOduInterfaces.add(
324 // suppporting interface?, payload ?
325 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
326 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
327 input.getTribSlot()));
329 createdOduInterfaces.add(
330 // supporting interface? payload ?
331 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
332 input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
333 LinkTp otnLinkTp3 = new LinkTpBuilder()
334 .setNodeId(node.getNodeId())
335 .setTpId(node.getNetworkTp())
337 linkTpList.add(otnLinkTp3);
338 if (node.getNetwork2Tp() != null) {
339 createdOduInterfaces.add(
340 // supporting interface? payload ?
341 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
342 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
343 input.getTribSlot()));
344 LinkTp otnLinkTp4 = new LinkTpBuilder()
345 .setNodeId(node.getNodeId())
346 .setTpId(node.getNetworkTp())
348 linkTpList.add(otnLinkTp4);
352 LOG.info("Input service is 100G");
353 // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
354 // min and max value only, size two)
355 OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
356 input.getOpucnTribSlots().get(0).getValue());
357 OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
358 input.getOpucnTribSlots().get(1).getValue());
359 if (node.getClientTp() != null) {
360 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
361 node.getNodeId(), node.getClientTp()));
362 // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
363 createdOduInterfaces.add(
364 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
365 node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
368 // Here payload-type is optional and is not used for interface creation (especially for network)
369 createdOduInterfaces.add(
370 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
371 node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
373 LinkTp otnLinkTp5 = new LinkTpBuilder()
374 .setNodeId(node.getNodeId())
375 .setTpId(node.getNetworkTp())
377 linkTpList.add(otnLinkTp5);
378 // Here payload-type is optional and is not used for service creation
379 // This is needed if there is an intermediate node
380 if (node.getNetwork2Tp() != null) {
381 createdOduInterfaces.add(
382 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
383 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
385 LinkTp otnLinkTp6 = new LinkTpBuilder()
386 .setNodeId(node.getNodeId())
387 .setTpId(node.getNetworkTp())
389 linkTpList.add(otnLinkTp6);
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 NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
405 .withKey(new NodeInterfaceKey(node.getNodeId()))
406 .setNodeId(node.getNodeId())
407 .setConnectionId(createdConnections)
408 .setEthInterfaceId(createdEthInterfaces)
409 .setOduInterfaceId(createdOduInterfaces);
410 nodeInterfaces.add(nodeInterfaceBuilder.build());
414 private void createOduc4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
415 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
416 if (input.getNodes() == null) {
419 LOG.info("Creation of ODUC4 TTP interface in OTN service path {}", input);
420 for (int i = 0; i < input.getNodes().size(); i++) {
421 Nodes node = input.getNodes().get(i);
422 String supportingOtuInterface = node.getNetworkTp() + "-OTUC4";
423 List<String> createdOduc4Interfaces = new ArrayList<>();
424 // Adding SAPI/DAPI information to the
425 Nodes tgtNode = null;
426 if (i + 1 == input.getNodes().size()) {
427 // For the end node, tgtNode becomes the first node in the list
428 tgtNode = input.getNodes().get(0);
430 tgtNode = input.getNodes().get(i + 1);
432 createdOduc4Interfaces.add(openRoadmInterfaceFactory.createOpenRoadmOtnOduc4Interface(node.getNodeId(),
433 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp()));
435 NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
436 .withKey(new NodeInterfaceKey(node.getNodeId()))
437 .setNodeId(node.getNodeId())
438 .setOduInterfaceId(createdOduc4Interfaces); // though this is odu, actually it has ODUC4 interfaces
439 nodeInterfaces.add(nodeInterfaceBuilder.build());
440 LinkTp otnLinkTp = new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build();
441 linkTpList.add(otnLinkTp);
445 private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
446 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
447 if (input.getNodes() == null) {
450 LOG.info("Creation of ODU4 tp interface {}", input);
451 for (int i = 0; i < input.getNodes().size(); i++) {
452 Nodes node = input.getNodes().get(i);
453 String supportingOtuInterface = node.getNetworkTp() + "-OTU";
454 List<String> createdOdu4Interfaces = new ArrayList<>();
455 // Adding SAPI/DAPI information to the
456 Nodes tgtNode = null;
457 if (i + 1 == input.getNodes().size()) {
458 // For the end node, tgtNode becomes the first node in the list
459 tgtNode = input.getNodes().get(0);
461 tgtNode = input.getNodes().get(i + 1);
464 createdOdu4Interfaces.add(openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
465 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp()));
466 NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder()
467 .withKey(new NodeInterfaceKey(node.getNodeId()))
468 .setNodeId(node.getNodeId())
469 .setOduInterfaceId(createdOdu4Interfaces);
470 nodeInterfaces.add(nodeInterfaceBuilder.build());
471 LinkTp otnLinkTp = new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build();
472 linkTpList.add(otnLinkTp);