From 0c060a0717faee47d216819f225972dbbc9f8d36 Mon Sep 17 00:00:00 2001 From: Gilles Thouenon Date: Thu, 2 Apr 2020 13:46:57 +0200 Subject: [PATCH] Align OTN renderer on OTN PCE and update otn-topo - add dependency towards network module to request NetworkModelService methods - service-path rpc allows creation/deletion of OCH and OTU4 interfaces and updates otn-topology with OTU4 links - otn-service-path rpc allows creation/deletion of ODU4 interfaces, structured for otn low order service, and creation/deletion of otn low order services. Moreover, it creates/updates/deletes consequently otn links and ODU4 termination points in otn-topology (bandwidth parameters, tributary slot and tributary port availabilities...) - adapt otn-renderer functional tests to take into account new behavior JIRA: TRNSPRTPCE-218 Signed-off-by: Gilles Thouenon Change-Id: I85020faf75fa53be1f965becccdf2787f6c743bb --- renderer/pom.xml | 5 + .../DeviceRendererServiceImpl.java | 45 +++- .../OtnDeviceRendererServiceImpl.java | 254 ++++++++++++++---- .../OSGI-INF/blueprint/renderer-blueprint.xml | 3 + ...ceRendererServiceImplCreateOtsOmsTest.java | 2 +- ...ndererServiceOperationsImplDeleteTest.java | 2 +- .../RendererServiceOperationsImplTest.java | 4 +- .../2.2.1/test_otn_renderer.py | 122 +++++++-- 8 files changed, 338 insertions(+), 99 deletions(-) diff --git a/renderer/pom.xml b/renderer/pom.xml index b4838f218..60eb255d0 100644 --- a/renderer/pom.xml +++ b/renderer/pom.xml @@ -28,6 +28,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html transportpce-common ${project.version} + + ${project.groupId} + transportpce-networkmodel + ${project.version} + diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java index bbac76c26..b2c6edc01 100644 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; @@ -37,6 +38,7 @@ import org.opendaylight.transportpce.common.device.DeviceTransactionManager; import org.opendaylight.transportpce.common.mapping.PortMapping; import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException; import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces; +import org.opendaylight.transportpce.networkmodel.service.NetworkModelService; import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory; import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServiceListTopology; import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection; @@ -66,12 +68,12 @@ import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.node.interfaces.NodeInterfaceBuilder; import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.node.interfaces.NodeInterfaceKey; import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.olm.renderer.input.Nodes; +import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev200129.OtnLinkType; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - public class DeviceRendererServiceImpl implements DeviceRendererService { private static final String ODU4 = "-ODU4"; private static final Logger LOG = LoggerFactory.getLogger(DeviceRendererServiceImpl.class); @@ -81,16 +83,18 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { private final OpenRoadmInterfaces openRoadmInterfaces; private final CrossConnect crossConnect; private final PortMapping portMapping; + private final NetworkModelService networkModelService; public DeviceRendererServiceImpl(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager, OpenRoadmInterfaceFactory openRoadmInterfaceFactory, OpenRoadmInterfaces openRoadmInterfaces, - CrossConnect crossConnect, PortMapping portMapping) { + CrossConnect crossConnect, PortMapping portMapping, NetworkModelService networkModelService) { this.dataBroker = dataBroker; this.deviceTransactionManager = deviceTransactionManager; this.openRoadmInterfaceFactory = openRoadmInterfaceFactory; this.openRoadmInterfaces = openRoadmInterfaces; this.crossConnect = crossConnect; this.portMapping = portMapping; + this.networkModelService = networkModelService; } @Override @@ -103,6 +107,7 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { ConcurrentLinkedQueue results = new ConcurrentLinkedQueue<>(); Set nodeInterfaces = Sets.newConcurrentHashSet(); Set nodesProvisioned = Sets.newConcurrentHashSet(); + CopyOnWriteArrayList otnNodesProvisioned = new CopyOnWriteArrayList<>(); ServiceListTopology topology = new ServiceListTopology(); AtomicBoolean success = new AtomicBoolean(true); ForkJoinPool forkJoinPool = new ForkJoinPool(); @@ -123,18 +128,14 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { Long waveNumber = input.getWaveNumber().toJava(); if ((destTp != null) && destTp.contains(StringConstants.NETWORK_TOKEN)) { crossConnectFlag++; - Mapping mapping = this.portMapping.getMapping(nodeId,destTp); String supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface( nodeId, destTp, waveNumber, ModulationFormat.DpQpsk); createdOchInterfaces.add(supportingOchInterface); String supportingOtuInterface = this.openRoadmInterfaceFactory .createOpenRoadmOtu4Interface(nodeId, destTp, supportingOchInterface); createdOtuInterfaces.add(supportingOtuInterface); - if (mapping != null && mapping.getXponderType() != null - && (mapping.getXponderType().getIntValue() == 3 - || mapping.getXponderType().getIntValue() == 2)) { - createdOduInterfaces.add(this.openRoadmInterfaceFactory - .createOpenRoadmOtnOdu4Interface(nodeId,destTp, supportingOtuInterface)); + if (srcTp == null) { + otnNodesProvisioned.add(node); } else { createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOdu4Interface(nodeId, destTp, supportingOtuInterface)); @@ -228,19 +229,20 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { if (success.get()) { results.add("Roadm-connection successfully created for nodes: " + String.join(", ", nodesProvisioned)); } - ServicePathOutputBuilder setServBldr = new ServicePathOutputBuilder() - .setNodeInterface(new ArrayList<>(nodeInterfaces)) - .setSuccess(success.get()) - .setResult(String.join("\n", results)); // setting topology in the service list data store try { setTopologyForService(input.getServiceName(), topology.getTopology()); + updateOtnTopology(otnNodesProvisioned, false); } catch (InterruptedException | TimeoutException | ExecutionException e) { LOG.warn("Failed to write topologies for service {}.", input.getServiceName(), e); } if (!alarmSuppressionNodeRemoval(input.getServiceName())) { LOG.error("Alarm suppresion node removal failed!!!!"); } + ServicePathOutputBuilder setServBldr = new ServicePathOutputBuilder() + .setNodeInterface(new ArrayList<>(nodeInterfaces)) + .setSuccess(success.get()) + .setResult(String.join("\n", results)); return setServBldr.build(); } @@ -260,6 +262,7 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { if (!alarmSuppressionNodeRegistration(input)) { LOG.warn("Alarm suppresion node registraion failed!!!!"); } + CopyOnWriteArrayList otnNodesProvisioned = new CopyOnWriteArrayList<>(); ForkJoinPool forkJoinPool = new ForkJoinPool(); ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> { List interfacesToDelete = new LinkedList<>(); @@ -278,6 +281,7 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { srcTp = node.getSrcTp(); } else { srcTp = ""; + otnNodesProvisioned.add(node); } // if the node is currently mounted then proceed. if (this.deviceTransactionManager.isDeviceMounted(nodeId)) { @@ -308,6 +312,7 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { LOG.error("Error while deleting service paths!", e); } forkJoinPool.shutdown(); + updateOtnTopology(otnNodesProvisioned, true); if (!alarmSuppressionNodeRemoval(input.getServiceName())) { LOG.error("Alarm suppresion node removal failed!!!!"); } @@ -572,4 +577,20 @@ public class DeviceRendererServiceImpl implements DeviceRendererService { } return result; } + + private void updateOtnTopology(CopyOnWriteArrayList nodes, boolean isDeletion) { + if (nodes.size() != 2) { + LOG.error("Error with OTU4 links to update in otn-topology"); + return; + } + if (isDeletion) { + LOG.info("updating otn-topology removing OTU4 links"); + this.networkModelService.deleteOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getDestTp(), + nodes.get(1).getNodeId(), nodes.get(1).getDestTp(), OtnLinkType.OTU4); + } else { + LOG.info("updating otn-topology adding OTU4 links"); + this.networkModelService.createOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getDestTp(), + nodes.get(1).getNodeId(), nodes.get(1).getDestTp(), OtnLinkType.OTU4); + } + } } diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OtnDeviceRendererServiceImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OtnDeviceRendererServiceImpl.java index 191b1998a..1713764f9 100644 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OtnDeviceRendererServiceImpl.java +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OtnDeviceRendererServiceImpl.java @@ -12,15 +12,18 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; import org.opendaylight.transportpce.common.crossconnect.CrossConnect; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException; import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces; +import org.opendaylight.transportpce.networkmodel.service.NetworkModelService; import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.OtnServicePathInput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.device.rev200128.OtnServicePathOutput; @@ -30,25 +33,30 @@ import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.node.interfaces.NodeInterfaceBuilder; import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.node.interfaces.NodeInterfaceKey; import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev200128.otn.renderer.input.Nodes; +import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev200129.OtnLinkType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { - private static final String ODU2E = "-ODU2e-"; private static final Logger LOG = LoggerFactory.getLogger(OtnDeviceRendererServiceImpl.class); + private static final String PT_03 = "03"; + private static final String PT_07 = "07"; private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory; private final CrossConnect crossConnect; private final OpenRoadmInterfaces openRoadmInterfaces; private final DeviceTransactionManager deviceTransactionManager; - + private final NetworkModelService networkModelService; public OtnDeviceRendererServiceImpl(OpenRoadmInterfaceFactory openRoadmInterfaceFactory, CrossConnect crossConnect, OpenRoadmInterfaces openRoadmInterfaces, - DeviceTransactionManager deviceTransactionManager) { + DeviceTransactionManager deviceTransactionManager, + NetworkModelService networkModelService) { this.openRoadmInterfaceFactory = openRoadmInterfaceFactory; this.crossConnect = crossConnect; this.openRoadmInterfaces = openRoadmInterfaces; this.deviceTransactionManager = deviceTransactionManager; + this.networkModelService = networkModelService; } @Override @@ -57,28 +65,72 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { boolean success = true; List nodeInterfaces = new ArrayList<>(); List results = new ArrayList<>(); - if (input.getServiceType().equals("Ethernet")) { - try { - LOG.info("Calling Node interfaces {} {} {} {} {} {} {}", - input.getServiceRate(),input.getEthernetEncoding(), - input.getServiceType(),input.getOperation(),input.getTribPortNumber(), - input.getTribSlot(),input.getNodes()); - nodeInterfaces = createInterface(input); - LOG.info("Node interfaces created just fine "); - } - catch (OpenRoadmInterfaceException e) { - //handle exception - LOG.warn("Set up service path failed {}", e.toString()); - success = false; - } + if (input.getServiceType() == null || input.getServiceRate() == null) { + OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder() + .setSuccess(false) + .setResult("Error - service-type and service-rate must be presents"); + return otnServicePathOutputBuilder.build(); + } + CopyOnWriteArrayList otnNodesProvisioned = new CopyOnWriteArrayList<>(); + switch (input.getServiceType()) { + case "Ethernet": + if ("10G".equals(input.getServiceRate()) || "1G".equals(input.getServiceRate())) { + try { + LOG.info("Calling Node interfaces {} {} {} {} {} {} {}", + input.getServiceRate(), input.getEthernetEncoding(), + input.getServiceType(), input.getOperation(), input.getTribPortNumber(), + input.getTribSlot(), input.getNodes()); + nodeInterfaces = createInterface(input); + LOG.info("Node interfaces created just fine "); + List nodesToUpdate = new ArrayList<>(); + if (!nodeInterfaces.isEmpty()) { + for (NodeInterface nodeInterf : nodeInterfaces) { + if (nodeInterf.getOduInterfaceId() != null) { + List interList = nodeInterf.getOduInterfaceId().stream() + .filter(id -> id.contains("NETWORK")).collect(Collectors.toList()); + if (!interList.isEmpty()) { + for (String inter : interList) { + String tp = inter.split("-ODU")[0]; + String nodeTopo = nodeInterf.getNodeId() + "-" + tp.split("-")[0]; + nodesToUpdate.add(nodeTopo + "--" + tp); + } + } + } + } + } + updateOtnTopology(null, nodesToUpdate, input.getServiceRate(), input.getTribPortNumber(), + input.getTribSlot(), false); + } catch (OpenRoadmInterfaceException e) { + LOG.warn("Set up service path failed", e); + success = false; + } + } else { + LOG.warn("Unsupported serivce-rate for service-type Ethernet"); + } + break; + case "ODU": + if ("100G".equals(input.getServiceRate())) { + try { + createODU4TtpInterface(input, nodeInterfaces, otnNodesProvisioned); + updateOtnTopology(otnNodesProvisioned, null, null, null, null, false); + } catch (OpenRoadmInterfaceException e) { + LOG.warn("Set up service path failed", e); + success = false; + } + } else { + LOG.warn("Unsupported serivce-rate for service-type ODU"); + } + break; + default: + LOG.error("service-type {} not managet yet", input.getServiceType()); + break; } if (success) { LOG.info("Result is success"); - for (NodeInterface nodeInterface: nodeInterfaces) { + for (NodeInterface nodeInterface : nodeInterfaces) { results.add("Otn Service path was set up successfully for node :" + nodeInterface.getNodeId()); } - //TODO Add otn topology links } OtnServicePathOutputBuilder otnServicePathOutputBuilder = new OtnServicePathOutputBuilder() .setSuccess(success) @@ -87,33 +139,41 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { return otnServicePathOutputBuilder.build(); } - @Override public OtnServicePathOutput deleteOtnServicePath(OtnServicePathInput input) { List nodes = input.getNodes(); AtomicBoolean success = new AtomicBoolean(true); ConcurrentLinkedQueue results = new ConcurrentLinkedQueue<>(); + List nodesTpToUpdate = new ArrayList<>(); + CopyOnWriteArrayList otnNodesProvisioned = new CopyOnWriteArrayList<>(); ForkJoinPool forkJoinPool = new ForkJoinPool(); ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> nodes.parallelStream().forEach(node -> { List interfacesToDelete = new LinkedList<>(); String nodeId = node.getNodeId(); LOG.info("Deleting service setup on node {}", nodeId); - String srcTp = node.getClientTp(); - String destTp = node.getNetworkTp(); - if ((srcTp == null) || (destTp == null) || input.getServiceRate() == null) { - LOG.error("Source ({}) or destination ({}) termination point is null.", srcTp, destTp); + String networkTp = node.getNetworkTp(); + if (networkTp == null || input.getServiceRate() == null || input.getServiceType() == null) { + LOG.error("destination ({}) or service rate ({}) or service type ({}) is null.", networkTp, + input.getServiceRate(), input.getServiceType()); return; } // if the node is currently mounted then proceed. if (this.deviceTransactionManager.isDeviceMounted(nodeId)) { String connectionNumber = ""; switch (input.getServiceRate()) { - case("10G"): - connectionNumber = srcTp + ODU2E + input.getServiceName() + "-x-" + destTp - + ODU2E + input.getServiceName(); + case ("100G"): + if ("ODU".equals(input.getServiceType())) { + interfacesToDelete.add(networkTp + "-ODU4"); + otnNodesProvisioned.add(node); + if (node.getNetwork2Tp() != null) { + interfacesToDelete.add(node.getNetwork2Tp() + "-ODU4"); + } + } + break; + case ("10G"): + connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU2e"); break; - case("1G"): - connectionNumber = srcTp + "-ODU0-" + input.getServiceName() + "-x-" + destTp - + ODU2E + input.getServiceName(); + case ("1G"): + connectionNumber = getConnectionNumber(input.getServiceName(), node, networkTp, "ODU0"); break; default: LOG.error("service rate {} not managed yet", input.getServiceRate()); @@ -141,7 +201,7 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { LOG.warn(result); forkJoinPool.shutdown(); return; - //TODO should deletion end here? + // TODO should deletion end here? } for (String interfaceId : interfacesToDelete) { try { @@ -153,6 +213,15 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { results.add(result); } } + List interList = interfacesToDelete.stream().filter(ele -> ele.contains("NETWORK")) + .collect(Collectors.toList()); + if (!interList.isEmpty()) { + for (String inter : interList) { + String tp = inter.split("-ODU")[0]; + String nodeTopo = nodeId + "-" + tp.split("-")[0]; + nodesTpToUpdate.add(nodeTopo + "--" + tp); + } + } })); try { forkJoinTask.get(); @@ -160,6 +229,14 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { LOG.error("Error while deleting service paths!", e); } forkJoinPool.shutdown(); + LOG.info("requesting otn-topology update..."); + if (!nodesTpToUpdate.isEmpty() && !"ODU".equals(input.getServiceType())) { + updateOtnTopology(null, nodesTpToUpdate, input.getServiceRate(), input.getTribPortNumber(), + input.getTribSlot(), true); + } else if (!otnNodesProvisioned.isEmpty()) { + updateOtnTopology(otnNodesProvisioned, null, null, null, null, true); + } + OtnServicePathOutputBuilder delServBldr = new OtnServicePathOutputBuilder(); delServBldr.setSuccess(success.get()); if (results.isEmpty()) { @@ -167,7 +244,16 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { } else { return delServBldr.setResult(String.join("\n", results)).build(); } + } + private String getConnectionNumber(String serviceName, Nodes node, String networkTp, String oduType) { + if (node.getClientTp() != null) { + return String.join("-", node.getClientTp(), oduType, serviceName, "x", networkTp, oduType, serviceName); + } else if (node.getNetwork2Tp() != null) { + return String.join("-", networkTp, oduType, serviceName, "x", node.getNetwork2Tp(), oduType, serviceName); + } else { + return ""; + } } private String getSupportedInterface(String nodeId, String interf) { @@ -199,47 +285,67 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { private Optional postCrossConnect(List createdOduInterfaces, Nodes node) throws OpenRoadmInterfaceException { - return this.crossConnect.postOtnCrossConnect(createdOduInterfaces,node); + return this.crossConnect.postOtnCrossConnect(createdOduInterfaces, node); } private void createLowOrderInterfaces(OtnServicePathInput input, List nodeInterfaces) throws OpenRoadmInterfaceException { - for (Nodes node: input.getNodes()) { - //check if the node is mounted or not? + for (Nodes node : input.getNodes()) { + // check if the node is mounted or not? List createdEthInterfaces = new ArrayList<>(); List createdOduInterfaces = new ArrayList<>(); switch (input.getServiceRate()) { - case("1G"): + case ("1G"): LOG.info("Input service is 1G"); - createdEthInterfaces.add( - openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(), node.getClientTp())); - createdOduInterfaces.add( - //suppporting interface?, payload ? - openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(), - input.getServiceName(), "07", false, input.getTribPortNumber(), input.getTribSlot())); + if (node.getClientTp() != null) { + createdEthInterfaces.add( + openRoadmInterfaceFactory.createOpenRoadmEth1GInterface(node.getNodeId(), + node.getClientTp())); + createdOduInterfaces.add( + // suppporting interface?, payload ? + openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getClientTp(), + input.getServiceName(), PT_07, false, input.getTribPortNumber(), input.getTribSlot())); + } createdOduInterfaces.add( openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), node.getNetworkTp(), - input.getServiceName(), "07", true, input.getTribPortNumber(), input.getTribSlot())); + input.getServiceName(), PT_07, true, input.getTribPortNumber(), input.getTribSlot())); + if (node.getNetwork2Tp() != null) { + createdOduInterfaces.add( + // supporting interface? payload ? + openRoadmInterfaceFactory.createOpenRoadmOdu0Interface(node.getNodeId(), + node.getNetwork2Tp(), input.getServiceName(), PT_07, true, input.getTribPortNumber(), + input.getTribSlot())); + } break; - case("10G"): + case ("10G"): LOG.info("Input service is 10G"); - createdEthInterfaces.add( - openRoadmInterfaceFactory.createOpenRoadmEth10GInterface(node.getNodeId(), node.getClientTp())); - createdOduInterfaces.add( - //suppporting interface?, payload ? - openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getClientTp(), - input.getServiceName(),"03", false ,input.getTribPortNumber(),input.getTribSlot())); + if (node.getClientTp() != null) { + createdEthInterfaces.add(openRoadmInterfaceFactory.createOpenRoadmEth10GInterface( + node.getNodeId(), node.getClientTp())); + createdOduInterfaces.add( + // suppporting interface?, payload ? + openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), + node.getClientTp(), input.getServiceName(), PT_03, false, input.getTribPortNumber(), + input.getTribSlot())); + } createdOduInterfaces.add( // supporting interface? payload ? openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), node.getNetworkTp(), - input.getServiceName(),"03" , true ,input.getTribPortNumber(),input.getTribSlot())); + input.getServiceName(), PT_03, true, input.getTribPortNumber(), input.getTribSlot())); + if (node.getNetwork2Tp() != null) { + createdOduInterfaces.add( + // supporting interface? payload ? + openRoadmInterfaceFactory.createOpenRoadmOdu2eInterface(node.getNodeId(), + node.getNetwork2Tp(), input.getServiceName(), PT_03, true, input.getTribPortNumber(), + input.getTribSlot())); + } break; default: LOG.error("service rate {} not managed yet", input.getServiceRate()); return; } - //implement cross connect + // implement cross connect List createdConnections = new ArrayList<>(); if (!createdOduInterfaces.isEmpty()) { Optional connectionNameOpt = postCrossConnect(createdOduInterfaces, node); @@ -247,12 +353,48 @@ public class OtnDeviceRendererServiceImpl implements OtnDeviceRendererService { LOG.info("Created cross connects"); } NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder() - .withKey(new NodeInterfaceKey(input.getServiceName() + "-" + node.getNodeId())) - .setNodeId(input.getServiceName() + "-" + node.getNodeId()) - .setConnectionId(createdConnections) - .setEthInterfaceId(createdEthInterfaces) - .setOduInterfaceId(createdOduInterfaces); + .withKey(new NodeInterfaceKey(node.getNodeId())) + .setNodeId(node.getNodeId()) + .setConnectionId(createdConnections) + .setEthInterfaceId(createdEthInterfaces) + .setOduInterfaceId(createdOduInterfaces); nodeInterfaces.add(nodeInterfaceBuilder.build()); } } + + private void createODU4TtpInterface(OtnServicePathInput input, List nodeInterfaces, + CopyOnWriteArrayList otnNodesProvisioned) throws OpenRoadmInterfaceException { + for (Nodes node : input.getNodes()) { + String supportingOtuInterface = node.getNetworkTp() + "-OTU"; + List createdOdu4Interfaces = new ArrayList<>(); + createdOdu4Interfaces.add(openRoadmInterfaceFactory.createOpenRoadmOtnOdu4Interface(node.getNodeId(), + node.getNetworkTp(), supportingOtuInterface)); + NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder() + .withKey(new NodeInterfaceKey(node.getNodeId())) + .setNodeId(node.getNodeId()) + .setOduInterfaceId(createdOdu4Interfaces); + nodeInterfaces.add(nodeInterfaceBuilder.build()); + otnNodesProvisioned.add(node); + } + } + + private void updateOtnTopology(CopyOnWriteArrayList nodes, List nodesTps, String serviceRate, + Short tribPortNb, Short tribSlotNb, boolean isDeletion) { + if (nodes != null && nodes.size() == 2) { + if (isDeletion) { + LOG.info("updating otn-topology removing ODU4 links"); + this.networkModelService.deleteOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(), + nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4); + } else { + LOG.info("updating otn-topology adding ODU4 links"); + this.networkModelService.createOtnLinks(nodes.get(0).getNodeId(), nodes.get(0).getNetworkTp(), + nodes.get(1).getNodeId(), nodes.get(1).getNetworkTp(), OtnLinkType.ODTU4); + } + } else if (nodesTps != null && (nodesTps.size() % 2 == 0) && serviceRate != null && tribPortNb != null + && tribSlotNb != null) { + LOG.info("updating otn-topology node tps -tps and tpn pools"); + this.networkModelService.updateOtnLinks(nodesTps, serviceRate, tribPortNb, tribSlotNb, isDeletion); + } + } + } diff --git a/renderer/src/main/resources/OSGI-INF/blueprint/renderer-blueprint.xml b/renderer/src/main/resources/OSGI-INF/blueprint/renderer-blueprint.xml index 94ca0af79..198ddb1b2 100644 --- a/renderer/src/main/resources/OSGI-INF/blueprint/renderer-blueprint.xml +++ b/renderer/src/main/resources/OSGI-INF/blueprint/renderer-blueprint.xml @@ -23,6 +23,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + @@ -61,6 +62,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + @@ -68,6 +70,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + diff --git a/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImplCreateOtsOmsTest.java b/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImplCreateOtsOmsTest.java index 0f94cd9c0..cab783017 100644 --- a/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImplCreateOtsOmsTest.java +++ b/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImplCreateOtsOmsTest.java @@ -95,7 +95,7 @@ public class DeviceRendererServiceImplCreateOtsOmsTest extends AbstractTest { this.crossConnect = Mockito.spy(this.crossConnect); this.deviceRendererService = new DeviceRendererServiceImpl(this.getDataBroker(), this.deviceTransactionManager, this.openRoadmInterfaceFactory, this.openRoadmInterfaces, - this.crossConnect, portMapping); + this.crossConnect, portMapping, null); } @Test diff --git a/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplDeleteTest.java b/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplDeleteTest.java index e788fc9be..629373484 100644 --- a/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplDeleteTest.java +++ b/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplDeleteTest.java @@ -117,7 +117,7 @@ public class RendererServiceOperationsImplDeleteTest extends AbstractTest { this.deviceRenderer = new DeviceRendererServiceImpl(this.getDataBroker(), this.deviceTransactionManager, openRoadmInterfaceFactory, openRoadmInterfaces, crossConnect, - this.portMapping); + this.portMapping, null); } @Before diff --git a/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplTest.java b/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplTest.java index 8fcbed63f..ce1b7fcb1 100644 --- a/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplTest.java +++ b/renderer/src/test/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImplTest.java @@ -120,8 +120,8 @@ public class RendererServiceOperationsImplTest extends AbstractTest { setMountPoint(new MountPointStub(getDataBroker())); this.olmService = new OlmServiceStub(); this.networkModelWavelengthService = new NetworkModelWavelengthServiceImpl(getDataBroker()); - this.deviceRenderer = new DeviceRendererServiceImpl(this.getDataBroker(), - this.deviceTransactionManager, openRoadmInterfaceFactory, openRoadmInterfaces, crossConnect, portMapping); + this.deviceRenderer = new DeviceRendererServiceImpl(this.getDataBroker(), this.deviceTransactionManager, + openRoadmInterfaceFactory, openRoadmInterfaces, crossConnect, portMapping, null); Mockito.doNothing().when(this.openRoadmInterfaces).postEquipmentState(Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean()); NotificationPublishService notificationPublishService = new NotificationPublishServiceMock(); diff --git a/tests/transportpce_tests/2.2.1/test_otn_renderer.py b/tests/transportpce_tests/2.2.1/test_otn_renderer.py index 476f146b6..cfd903830 100644 --- a/tests/transportpce_tests/2.2.1/test_otn_renderer.py +++ b/tests/transportpce_tests/2.2.1/test_otn_renderer.py @@ -125,7 +125,7 @@ class TransportPCEtesting(unittest.TestCase): "xponder-type": "mpdr"}, res['mapping']) - def test_04_service_path_create_ODU4(self): + def test_04_service_path_create_OCH_OTU4(self): url = "{}/operations/transportpce-device-renderer:service-path".format(self.restconf_baseurl) data = {"renderer:input": { "service-name": "service_ODU4", @@ -147,7 +147,6 @@ class TransportPCEtesting(unittest.TestCase): self.assertIn( {'node-id': 'SPDR-SA1', 'otu-interface-id': ['XPDR1-NETWORK1-OTU'], - 'odu-interface-id': ['XPDR1-NETWORK1-ODU4'], 'och-interface-id': ['XPDR1-NETWORK1-1']}, res["output"]['node-interface']) def test_05_get_portmapping_NETWORK1(self): @@ -168,8 +167,7 @@ class TransportPCEtesting(unittest.TestCase): "port-direction": "bidirectional", "port-qual": "xpdr-network", "supporting-circuit-pack-name": "CP1-CFP0", - "xponder-type": "mpdr", - "supporting-odu4": "XPDR1-NETWORK1-ODU4"}, + "xponder-type": "mpdr"}, res['mapping']) def test_06_check_interface_och(self): @@ -210,7 +208,52 @@ class TransportPCEtesting(unittest.TestCase): u'fec': u'scfec'}, res['interface'][0]['org-openroadm-otn-otu-interfaces:otu']) - def test_08_check_interface_ODU4(self): + def test_08_otn_service_path_create_ODU4(self): + url = "{}/operations/transportpce-device-renderer:otn-service-path".format(self.restconf_baseurl) + data = {"renderer:input": { + "service-name": "service_ODU4", + "operation": "create", + "service-rate": "100G", + "service-type": "ODU", + "nodes": [ + {"node-id": "SPDR-SA1", + "network-tp": "XPDR1-NETWORK1"}]}} + headers = {'content-type': 'application/json'} + response = requests.request( + "POST", url, data=json.dumps(data), + headers=headers, auth=('admin', 'admin')) + time.sleep(3) + self.assertEqual(response.status_code, requests.codes.ok) + res = response.json() + self.assertIn('Otn Service path was set up successfully for node :SPDR-SA1', res["output"]["result"]) + self.assertTrue(res["output"]["success"]) + self.assertIn( + {'node-id': 'SPDR-SA1', + 'odu-interface-id': ['XPDR1-NETWORK1-ODU4']}, res["output"]['node-interface']) + + def test_09_get_portmapping_NETWORK1(self): + url = ("{}/config/transportpce-portmapping:network/" + "nodes/SPDR-SA1/mapping/XPDR1-NETWORK1" + .format(self.restconf_baseurl)) + headers = {'content-type': 'application/json'} + response = requests.request( + "GET", url, headers=headers, auth=('admin', 'admin')) + self.assertEqual(response.status_code, requests.codes.ok) + res = response.json() + self.assertIn( + {"logical-connection-point": "XPDR1-NETWORK1", + "supporting-port": "CP1-CFP0-P1", + "supported-interface-capability": [ + "org-openroadm-port-types:if-OCH-OTU4-ODU4" + ], + "port-direction": "bidirectional", + "port-qual": "xpdr-network", + "supporting-circuit-pack-name": "CP1-CFP0", + "xponder-type": "mpdr", + "supporting-odu4": "XPDR1-NETWORK1-ODU4"}, + res['mapping']) + + def test_10_check_interface_ODU4(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-NETWORK1-ODU4" @@ -232,7 +275,7 @@ class TransportPCEtesting(unittest.TestCase): {u'payload-type': u'21', u'exp-payload-type': u'21'}, res['interface'][0]['org-openroadm-otn-odu-interfaces:odu']['opu']) - def test_09_otn_service_path_create_10GE(self): + def test_11_otn_service_path_create_10GE(self): url = "{}/operations/transportpce-device-renderer:otn-service-path".format(self.restconf_baseurl) data = {"renderer:input": { "service-name": "service1", @@ -242,7 +285,6 @@ class TransportPCEtesting(unittest.TestCase): "ethernet-encoding": "eth encode", "trib-slot": ["1"], "trib-port-number": "1", - "opucn-trib-slots": ["1"], "nodes": [ {"node-id": "SPDR-SA1", "client-tp": "XPDR1-CLIENT1", @@ -251,12 +293,18 @@ class TransportPCEtesting(unittest.TestCase): response = requests.request( "POST", url, data=json.dumps(data), headers=headers, auth=('admin', 'admin')) + time.sleep(3) self.assertEqual(response.status_code, requests.codes.ok) res = response.json() - self.assertIn('Otn Service path was set up successfully for node :service1-SPDR-SA1', res["output"]["result"]) + self.assertIn('Otn Service path was set up successfully for node :SPDR-SA1', res["output"]["result"]) self.assertTrue(res["output"]["success"]) + self.assertIn( + {'node-id': 'SPDR-SA1', + 'connection-id': ['XPDR1-CLIENT1-ODU2e-service1-x-XPDR1-NETWORK1-ODU2e-service1'], + 'odu-interface-id': ['XPDR1-NETWORK1-ODU2e-service1', 'XPDR1-CLIENT1-ODU2e-service1'], + 'eth-interface-id': ['XPDR1-CLIENT1-ETHERNET10G']}, res["output"]['node-interface']) - def test_10_check_interface_10GE_CLIENT(self): + def test_12_check_interface_10GE_CLIENT(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-CLIENT1-ETHERNET10G" @@ -274,7 +322,7 @@ class TransportPCEtesting(unittest.TestCase): {u'speed': 10000}, res['interface'][0]['org-openroadm-ethernet-interfaces:ethernet']) - def test_11_check_interface_ODU2E_CLIENT(self): + def test_13_check_interface_ODU2E_CLIENT(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-CLIENT1-ODU2e-service1" @@ -297,7 +345,7 @@ class TransportPCEtesting(unittest.TestCase): {u'payload-type': u'03', u'exp-payload-type': u'03'}, res['interface'][0]['org-openroadm-otn-odu-interfaces:odu']['opu']) - def test_12_check_interface_ODU2E_NETWORK(self): + def test_14_check_interface_ODU2E_NETWORK(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-NETWORK1-ODU2e-service1" @@ -322,7 +370,7 @@ class TransportPCEtesting(unittest.TestCase): self.assertIn(1, res['interface'][0]['org-openroadm-otn-odu-interfaces:odu']['parent-odu-allocation']['trib-slots']) - def test_13_check_ODU2E_connection(self): + def test_15_check_ODU2E_connection(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "odu-connection/XPDR1-CLIENT1-ODU2e-service1-x-XPDR1-NETWORK1-ODU2e-service1" @@ -341,7 +389,7 @@ class TransportPCEtesting(unittest.TestCase): self.assertDictEqual({u'src-if': u'XPDR1-CLIENT1-ODU2e-service1'}, res['odu-connection'][0]['source']) - def test_14_otn_service_path_delete_10GE(self): + def test_16_otn_service_path_delete_10GE(self): url = "{}/operations/transportpce-device-renderer:otn-service-path".format(self.restconf_baseurl) data = {"renderer:input": { "service-name": "service1", @@ -351,7 +399,6 @@ class TransportPCEtesting(unittest.TestCase): "ethernet-encoding": "eth encode", "trib-slot": ["1"], "trib-port-number": "1", - "opucn-trib-slots": ["1"], "nodes": [ {"node-id": "SPDR-SA1", "client-tp": "XPDR1-CLIENT1", @@ -360,12 +407,13 @@ class TransportPCEtesting(unittest.TestCase): response = requests.request( "POST", url, data=json.dumps(data), headers=headers, auth=('admin', 'admin')) + time.sleep(3) self.assertEqual(response.status_code, requests.codes.ok) res = response.json() self.assertIn('Request processed', res["output"]["result"]) self.assertTrue(res["output"]["success"]) - def test_15_check_no_ODU2E_connection(self): + def test_17_check_no_ODU2E_connection(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "odu-connection/XPDR1-CLIENT1-ODU2e-service1-x-XPDR1-NETWORK1-ODU2e-service1" @@ -375,7 +423,7 @@ class TransportPCEtesting(unittest.TestCase): "GET", url, headers=headers, auth=('admin', 'admin')) self.assertEqual(response.status_code, requests.codes.not_found) - def test_16_check_no_interface_ODU2E_NETWORK(self): + def test_18_check_no_interface_ODU2E_NETWORK(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-NETWORK1-ODU2e-service1" @@ -385,7 +433,7 @@ class TransportPCEtesting(unittest.TestCase): "GET", url, headers=headers, auth=('admin', 'admin')) self.assertEqual(response.status_code, requests.codes.not_found) - def test_17_check_no_interface_ODU2E_CLIENT(self): + def test_19_check_no_interface_ODU2E_CLIENT(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-CLIENT1-ODU2e-service1" @@ -395,7 +443,7 @@ class TransportPCEtesting(unittest.TestCase): "GET", url, headers=headers, auth=('admin', 'admin')) self.assertEqual(response.status_code, requests.codes.not_found) - def test_18_check_no_interface_10GE_CLIENT(self): + def test_20_check_no_interface_10GE_CLIENT(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-CLIENT1-ETHERNET10G" @@ -405,16 +453,16 @@ class TransportPCEtesting(unittest.TestCase): "GET", url, headers=headers, auth=('admin', 'admin')) self.assertEqual(response.status_code, requests.codes.not_found) - def test_19_service_path_delete_ODU4(self): - url = "{}/operations/transportpce-device-renderer:service-path".format(self.restconf_baseurl) + def test_21_otn_service_path_delete_ODU4(self): + url = "{}/operations/transportpce-device-renderer:otn-service-path".format(self.restconf_baseurl) data = {"renderer:input": { "service-name": "service_ODU4", - "wave-number": "1", - "modulation-format": "qpsk", "operation": "delete", + "service-rate": "100G", + "service-type": "ODU", "nodes": [ {"node-id": "SPDR-SA1", - "dest-tp": "XPDR1-NETWORK1"}]}} + "network-tp": "XPDR1-NETWORK1"}]}} headers = {'content-type': 'application/json'} response = requests.request( "POST", url, data=json.dumps(data), @@ -425,7 +473,7 @@ class TransportPCEtesting(unittest.TestCase): self.assertIn('Request processed', res["output"]["result"]) self.assertTrue(res["output"]["success"]) - def test_20_check_no_interface_ODU4(self): + def test_22_check_no_interface_ODU4(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-NETWORK1-ODU4" @@ -435,7 +483,27 @@ class TransportPCEtesting(unittest.TestCase): "GET", url, headers=headers, auth=('admin', 'admin')) self.assertEqual(response.status_code, requests.codes.not_found) - def test_21_check_no_interface_OTU(self): + def test_23_service_path_delete_OCH_OTU4(self): + url = "{}/operations/transportpce-device-renderer:service-path".format(self.restconf_baseurl) + data = {"renderer:input": { + "service-name": "service_OTU4", + "wave-number": "1", + "modulation-format": "qpsk", + "operation": "delete", + "nodes": [ + {"node-id": "SPDR-SA1", + "dest-tp": "XPDR1-NETWORK1"}]}} + headers = {'content-type': 'application/json'} + response = requests.request( + "POST", url, data=json.dumps(data), + headers=headers, auth=('admin', 'admin')) + time.sleep(3) + self.assertEqual(response.status_code, requests.codes.ok) + res = response.json() + self.assertIn('Request processed', res["output"]["result"]) + self.assertTrue(res["output"]["success"]) + + def test_24_check_no_interface_OTU4(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-NETWORK1-OTU" @@ -445,7 +513,7 @@ class TransportPCEtesting(unittest.TestCase): "GET", url, headers=headers, auth=('admin', 'admin')) self.assertEqual(response.status_code, requests.codes.not_found) - def test_22_check_no_interface_och(self): + def test_25_check_no_interface_OCH(self): url = ("{}/config/network-topology:network-topology/topology/topology-netconf/" "node/SPDR-SA1/yang-ext:mount/org-openroadm-device:org-openroadm-device/" "interface/XPDR1-NETWORK1-1" @@ -455,7 +523,7 @@ class TransportPCEtesting(unittest.TestCase): "GET", url, headers=headers, auth=('admin', 'admin')) self.assertEqual(response.status_code, requests.codes.not_found) - def test_23_disconnect_SPDR_SA1(self): + def test_26_disconnect_SPDR_SA1(self): url = ("{}/config/network-topology:" "network-topology/topology/topology-netconf/node/SPDR-SA1" .format(self.restconf_baseurl)) -- 2.36.6