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 public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) {
140 if (input.getNodes() == null) {
141 LOG.error("Unable to delete otn service path. input nodes = null");
142 return new OtnServicePathOutputBuilder()
143 .setResult("Unable to delete otn service path. input nodes = null")
147 List<Nodes> nodes = input.getNodes();
148 AtomicBoolean success = new AtomicBoolean(true);
149 ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
150 CopyOnWriteArrayList<LinkTp> otnLinkTps = new CopyOnWriteArrayList<>();
151 ForkJoinPool forkJoinPool = new ForkJoinPool();
152 ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> {
153 String nodeId = node.getNodeId();
154 LOG.info("Deleting service setup on node {}", nodeId);
155 String networkTp = node.getNetworkTp();
156 if (networkTp == null || input.getServiceRate() == null || input.getServiceFormat() == null) {
157 LOG.error("destination ({}) or service-rate ({}) or service-format ({}) is null.",
158 networkTp, input.getServiceRate(), input.getServiceFormat());
161 if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
162 String result = nodeId + " is not mounted on the controller";
166 forkJoinPool.shutdown();
168 // TODO should deletion end here?
170 // if the node is currently mounted then proceed.
171 List<String> interfacesToDelete = new LinkedList<>();
172 String connectionNumber = "";
173 switch (input.getServiceRate().intValue()) {
175 if ("ODU".equals(input.getServiceFormat())) {
176 interfacesToDelete.add(networkTp + "-ODU4");
177 if (node.getNetwork2Tp() != null) {
178 interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4");
180 } else if ("Ethernet".equals(input.getServiceFormat())) {
181 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU4");
185 if ("ODU".equals(input.getServiceFormat())) {
186 interfacesToDelete.add(networkTp + "-ODUC4");
187 if (node.getNetwork2Tp() != null) {
188 interfacesToDelete.add(node.getNetwork2Tp() + "-ODUC4");
193 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e");
196 connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0");
199 LOG.error("service rate {} not managed yet", input.getServiceRate());
200 String result = input.getServiceRate() + " is not supported";
205 List<String> intToDelete = this.crossConnect.deleteCrossConnect(nodeId, connectionNumber, true);
206 for (String interf : intToDelete == null ? new ArrayList<String>() : intToDelete) {
207 if (!this.openRoadmInterfaceFactory.isUsedByOtnXc(nodeId, interf, connectionNumber,
208 this.deviceTransactionManager)) {
209 interfacesToDelete.add(interf);
210 String supportedInterface = this.openRoadmInterfaces.getSupportedInterface(nodeId, interf);
211 if (input.getServiceRate().intValue() == 100) {
212 if (!supportedInterface.contains("ODUC4")) {
213 interfacesToDelete.add(supportedInterface);
216 if (!supportedInterface.contains("ODU4")) {
217 interfacesToDelete.add(supportedInterface);
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 =
234 interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK")).collect(Collectors.toList());
235 if (!interList.isEmpty()) {
236 for (String inter : interList) {
237 otnLinkTps.add(new LinkTpBuilder()
239 .setTpId(inter.split("-ODU")[0])
246 } catch (InterruptedException | ExecutionException e) {
247 LOG.error("Error while deleting service paths!", e);
248 return new OtnServicePathOutputBuilder()
249 .setResult("Error while deleting service paths!")
253 forkJoinPool.shutdown();
254 return new OtnServicePathOutputBuilder()
255 .setSuccess(success.get())
256 .setLinkTp(otnLinkTps)
259 ? "Request processed"
260 : String.join("\n", results))
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()));
301 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
302 if (node.getNetwork2Tp() != null) {
303 createdOduInterfaces.add(
304 // supporting interface? payload ?
305 openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(),
306 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(),
307 input.getTribSlot()));
309 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
313 LOG.info("Input service is 10G");
314 if (node.getClientTp() != null) {
315 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(
316 node.getNodeId(), node.getClientTp()));
317 createdOduInterfaces.add(
318 // suppporting interface?, payload ?
319 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
320 node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(),
321 input.getTribSlot()));
323 createdOduInterfaces.add(
324 // supporting interface? payload ?
325 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(),
326 input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot()));
328 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
329 if (node.getNetwork2Tp() != null) {
330 createdOduInterfaces.add(
331 // supporting interface? payload ?
332 openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(),
333 node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(),
334 input.getTribSlot()));
336 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
340 LOG.info("Input service is 100G");
341 // Take the first and last value in the list of OpucnTribSlot (assuming SH would provide
342 // min and max value only, size two)
343 OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef.getDefaultInstance(
344 input.getOpucnTribSlots().get(0).getValue());
345 OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef.getDefaultInstance(
346 input.getOpucnTribSlots().get(1).getValue());
347 if (node.getClientTp() != null) {
348 createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth100GInterface(
349 node.getNodeId(), node.getClientTp()));
350 // OPUCn trib information is optional when creating ODU4 ethernet (client) interface
351 createdOduInterfaces.add(
352 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
353 node.getClientTp(), input.getServiceName(), PT_07, false, minOpucnTs,
356 // Here payload-type is optional and is not used for interface creation (especially for network)
357 createdOduInterfaces.add(
358 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
359 node.getNetworkTp(), input.getServiceName(), PT_07, true, minOpucnTs,
362 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
363 // Here payload-type is optional and is not used for service creation
364 // This is needed if there is an intermediate node
365 if (node.getNetwork2Tp() != null) {
366 createdOduInterfaces.add(
367 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4LoInterface(node.getNodeId(),
368 node.getNetwork2Tp(), input.getServiceName(), PT_07, true, minOpucnTs,
371 new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
375 LOG.error("service rate {} not managed yet", input.getServiceRate());
379 // implement cross connect
380 List<String> createdConnections = new ArrayList<>();
381 if (!createdOduInterfaces.isEmpty()) {
382 Optional<String> connectionNameOpt = postCrossConnect(createdOduInterfaces, node);
383 createdConnections.add(connectionNameOpt.get());
384 LOG.info("Created cross connects");
386 nodeInterfaces.add(new NodeInterfaceBuilder()
387 .withKey(new NodeInterfaceKey(node.getNodeId()))
388 .setNodeId(node.getNodeId())
389 .setConnectionId(createdConnections)
390 .setEthInterfaceId(createdEthInterfaces)
391 .setOduInterfaceId(createdOduInterfaces)
396 private void createOduc4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
397 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
398 if (input.getNodes() == null) {
401 LOG.info("Creation of ODUC4 TTP interface in OTN service path {}", input);
402 for (int i = 0; i < input.getNodes().size(); i++) {
403 Nodes node = input.getNodes().get(i);
404 String supportingOtuInterface = node.getNetworkTp() + "-OTUC4";
407 i + 1 == input.getNodes().size()
408 // For the end node, tgtNode becomes the first node in the list
409 ? input.getNodes().get(0)
410 : input.getNodes().get(i + 1);
412 nodeInterfaces.add(new NodeInterfaceBuilder()
413 .withKey(new NodeInterfaceKey(node.getNodeId()))
414 .setNodeId(node.getNodeId())
415 .setOduInterfaceId(List.of(
416 // though this is odu, actually it has ODUC4 interfaces
417 openRoadmInterfaceFactory.createOpenRoadmOtnOduc4Interface(node.getNodeId(),
418 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
420 linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());
424 private void createODU4TtpInterface(OtnServicePathInput input, List<NodeInterface> nodeInterfaces,
425 CopyOnWriteArrayList<LinkTp> linkTpList) throws OpenRoadmInterfaceException {
426 if (input.getNodes() == null) {
429 LOG.info("Creation of ODU4 tp interface {}", input);
430 for (int i = 0; i < input.getNodes().size(); i++) {
431 Nodes node = input.getNodes().get(i);
432 String supportingOtuInterface = node.getNetworkTp() + "-OTU";
435 i + 1 == input.getNodes().size()
436 // For the end node, tgtNode becomes the first node in the list
437 ? input.getNodes().get(0)
438 : input.getNodes().get(i + 1);
440 nodeInterfaces.add(new NodeInterfaceBuilder()
441 .withKey(new NodeInterfaceKey(node.getNodeId()))
442 .setNodeId(node.getNodeId())
443 .setOduInterfaceId(List.of(
444 openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(),
445 node.getNetworkTp(), supportingOtuInterface, tgtNode.getNodeId(), tgtNode.getNetworkTp())))
447 linkTpList.add(new LinkTpBuilder().setNodeId(node.getNodeId()).setTpId(node.getNetworkTp()).build());