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;
66 //TODO Align log messages and returned results messages
68 public OtnServicePathOutput setupOtnServicePath(OtnServicePathInput input) {
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<>();
78 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:
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 ");
93 case StringConstants.SERVICE_TYPE_ODU4:
94 createODU4TtpInterface(input, nodeInterfaces, otnLinkTps);
96 case StringConstants.SERVICE_TYPE_ODUC4:
97 createOduc4TtpInterface(input, nodeInterfaces, otnLinkTps);
100 LOG.error("Service-type {} not managed yet", serviceType);
101 return new OtnServicePathOutputBuilder()
103 .setResult("Service-type not managed")
106 } catch (OpenRoadmInterfaceException e) {
107 LOG.warn("Service path set-up failed", e);
108 Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
109 for (NodeInterface nodeInterface : nodeInterfaces) {
110 if (nodeInterface != null) {
111 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
114 //TODO check if we need to set a NodeInterface Map in the result in that case
115 return new OtnServicePathOutputBuilder()
117 .setNodeInterface(nodeInterfacesMap)
118 .setResult("Service path set-up failed")
119 .setLinkTp(otnLinkTps)
122 LOG.info("Service path set-up succeed");
123 List<String> results = new ArrayList<>();
124 Map<NodeInterfaceKey,NodeInterface> nodeInterfacesMap = new HashMap<>();
125 for (NodeInterface nodeInterface : nodeInterfaces) {
126 if (nodeInterface != null) {
127 results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId());
128 nodeInterfacesMap.put(nodeInterface.key(), nodeInterface);
131 return new OtnServicePathOutputBuilder()
133 .setNodeInterface(nodeInterfacesMap)
134 .setResult(String.join("\n", results))
135 .setLinkTp(otnLinkTps)
139 @SuppressWarnings("rawtypes")
140 // FIXME check if the ForkJoinTask raw type can be avoided
141 // Raw types use are discouraged since they lack type safety.
142 // Resulting Problems are observed at run time and not at compile time
143 public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) {
144 if (input.getNodes() == null) {
145 LOG.error("Unable to delete otn service path. input nodes = null");
146 return new OtnServicePathOutputBuilder()
147 .setResult("Unable to delete otn service path. input nodes = null")
151 List<Nodes> nodes = input.getNodes();
152 AtomicBoolean success = new AtomicBoolean(true);
153 ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
154 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
155 ForkJoinPool forkJoinPool = new ForkJoinPool();
156 ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
157 String nodeId = node.getNodeId();
158 LOG.info("Deleting service setup on node {}", nodeId);
159 String networkTp = node.getNetworkTp();
160 if (networkTp == null || input.getServiceRate() == null || input.getServiceFormat() == null) {
161 LOG.error("destination ({}) or service-rate ({}) or service-format ({}) is null.",
162 networkTp, input.getServiceRate(), input.getServiceFormat());
165 if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
166 String result = nodeId + " is not mounted on the controller";
170 forkJoinPool.shutdown();
172 // TODO should deletion end here?
174 // if the node is currently mounted then proceed.
175 List<String> interfacesToDelete = new LinkedList<>();
176 String connectionNumber = "";
177 switch (input.getServiceRate().intValue()) {
179 if ("ODU".equals(input.getServiceFormat())) {
180 interfacesToDelete.add(networkTp + "-ODU4");
181 if (node.getNetwork2Tp() != null) {
182 interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
184 } else if ("Ethernet".equals(input.getServiceFormat())) {
185 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU4");
189 if ("ODU".equals(input.getServiceFormat())) {
190 interfacesToDelete.add(networkTp + "-ODUC4");
191 if (node.getNetwork2Tp() != null) {
192 interfacesToDelete.add(node.getNetwork2Tp() + "-ODUC4");
197 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
200 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
203 LOG.error("service rate {} not managed yet", input.getServiceRate());
204 String result = input.getServiceRate() + " is not supported";
209 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
210 for (String interf : intToDelete == null ? new ArrayList<String>() : intToDelete) {
211 if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
212 this.deviceTransactionManager)) {
213 interfacesToDelete.add(interf);
214 String supportedInterface = this.openRoadmInterfaces.getSupportedInterface(nodeId, interf);
215 if (input.getServiceRate().intValue() == 100) {
216 if (!supportedInterface.contains("ODUC4")) {
217 interfacesToDelete.add(supportedInterface);
220 if (!supportedInterface.contains("ODU4")) {
221 interfacesToDelete.add(supportedInterface);
227 for (String interfaceId : interfacesToDelete) {
229 this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId);
230 } catch (OpenRoadmInterfaceException e) {
231 String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId);
233 LOG.error(result, e);
237 List<String> interList =
238 interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK")).collect(Collectors.toList());
239 if (!interList.isEmpty()) {
240 for (String inter : interList) {
241 otnLinkTps.add(new LinkTpBuilder()
243 .setTpId(inter.split("-ODU")[0])
250 } catch (InterruptedException | ExecutionException e) {
251 LOG.error("Error while deleting service paths!", e);
252 return new OtnServicePathOutputBuilder()
253 .setResult("Error while deleting service paths!")
257 forkJoinPool.shutdown();
258 return new OtnServicePathOutputBuilder()
259 .setSuccess(success.get())
260 .setLinkTp(otnLinkTps)
263 ? "Request processed"
264 : String.join("\n", results))
268 private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) {
269 if (node.getClientTp() != null) {
270 return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName);
271 } else if (node.getNetwork2Tp() != null) {
272 return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName);
278 private Optional<String> postCrossConnect(List<String> createdOduInterfaces, Nodes node)
279 throws OpenRoadmInterfaceException {
280 return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node);
283 private void createLowOrderInterfaces(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
284 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
285 for (Nodes node : input.getNodes()) {
286 // check if the node is mounted or not?
287 List<String> createdEthInterfaces = new ArrayList<>();
288 List<String> createdOduInterfaces = new ArrayList<>();
289 switch (input.getServiceRate().intValue()) {
291 LOG.info("Input service is 1G");
292 if (node.getClientTp() != null) {
293 createdEthInterfaces.add(
294 openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(),
295 node.getClientTp()));
296 createdOduInterfaces.add(
297 // suppporting interface?, payload ?
298 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(),
299 input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot()));
301 createdOduInterfaces.add(
302 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(),
303 input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot()));
305 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
306 if (node.getNetwork2Tp() != null) {
307 createdOduInterfaces.add(
308 // supporting interface? payload ?
309 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
310 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
311 input.getTribSlot()));
313 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
317 LOG.info("Input service is 10G");
318 if (node.getClientTp() != null) {
319 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
320 node.getNodeId(), node.getClientTp()));
321 createdOduInterfaces.add(
322 // suppporting interface?, payload ?
323 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
324 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
325 input.getTribSlot()));
327 createdOduInterfaces.add(
328 // supporting interface? payload ?
329 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
330 input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
332 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
333 if (node.getNetwork2Tp() != null) {
334 createdOduInterfaces.add(
335 // supporting interface? payload ?
336 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
337 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
338 input.getTribSlot()));
340 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
344 LOG.info("Input service is 100G");
345 // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
346 // min and max value only, size two)
347 OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
348 input.getOpucnTribSlots().get(0).getValue());
349 OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
350 input.getOpucnTribSlots().get(1).getValue());
351 if (node.getClientTp() != null) {
352 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
353 node.getNodeId(), node.getClientTp()));
354 // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
355 createdOduInterfaces.add(
356 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
357 node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
360 // Here payload-type is optional and is not used for interface creation (especially for network)
361 createdOduInterfaces.add(
362 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
363 node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
366 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
367 // Here payload-type is optional and is not used for service creation
368 // This is needed if there is an intermediate node
369 if (node.getNetwork2Tp() != null) {
370 createdOduInterfaces.add(
371 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
372 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
375 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
379 LOG.error("service rate {} not managed yet", input.getServiceRate());
383 // implement cross connect
384 List<String> createdConnections = new ArrayList<>();
385 if (!createdOduInterfaces.isEmpty()) {
386 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
387 createdConnections.add(connectionNameOpt.get());
388 LOG.info("Created cross connects");
390 nodeInterfaces.add(new NodeInterfaceBuilder()
391 .withKey(new NodeInterfaceKey(node.getNodeId()))
392 .setNodeId(node.getNodeId())
393 .setConnectionId(createdConnections)
394 .setEthInterfaceId(createdEthInterfaces)
395 .setOduInterfaceId(createdOduInterfaces)
400 private void createOduc4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
401 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
402 if (input.getNodes() == null) {
405 LOG.info("Creation of ODUC4 TTP interface in OTN service path {}", input);
406 for (int i = 0; i < input.getNodes().size(); i++) {
407 Nodes node = input.getNodes().get(i);
408 String supportingOtuInterface = node.getNetworkTp() + "-OTUC4";
411 i + 1 == input.getNodes().size()
412 // For the end node, tgtNode becomes the first node in the list
413 ? input.getNodes().get(0)
414 : input.getNodes().get(i + 1);
416 nodeInterfaces.add(new NodeInterfaceBuilder()
417 .withKey(new NodeInterfaceKey(node.getNodeId()))
418 .setNodeId(node.getNodeId())
419 .setOduInterfaceId(List.of(
420 // though this is odu, actually it has ODUC4 interfaces
421 openRoadmInterfaceFactory.createOpenRoadmOtnOduc4Interface(node.getNodeId(),
422 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
424 linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
428 private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
429 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
430 if (input.getNodes() == null) {
433 LOG.info("Creation of ODU4 tp interface {}", input);
434 for (int i = 0; i < input.getNodes().size(); i++) {
435 Nodes node = input.getNodes().get(i);
436 String supportingOtuInterface = node.getNetworkTp() + "-OTU";
439 i + 1 == input.getNodes().size()
440 // For the end node, tgtNode becomes the first node in the list
441 ? input.getNodes().get(0)
442 : input.getNodes().get(i + 1);
444 nodeInterfaces.add(new NodeInterfaceBuilder()
445 .withKey(new NodeInterfaceKey(node.getNodeId()))
446 .setNodeId(node.getNodeId())
447 .setOduInterfaceId(List.of(
448 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
449 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
451 linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());