X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=pce%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Ftransportpce%2Fpce%2Fgnpy%2FGnpyServiceImpl.java;h=26c1b4c6b50b01f7524518bd02adc0e4f0d710fa;hb=6b6a445c84c2eb1c85d4e48c2d10a89c3d598bc5;hp=34fc4ece9e2ecac54cc610ea64fb33b148d9c084;hpb=e7f86861e87c1fc86e2e06dcd56d33492e9f69be;p=transportpce.git diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java index 34fc4ece9..26c1b4c6b 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java @@ -8,51 +8,67 @@ package org.opendaylight.transportpce.pce.gnpy; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; - +import java.util.Optional; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.transportpce.common.ServiceRateConstant; +import org.opendaylight.transportpce.common.fixedflex.GridConstant; +import org.opendaylight.transportpce.common.fixedflex.GridUtils; import org.opendaylight.transportpce.pce.constraints.PceConstraints; import org.opendaylight.transportpce.pce.constraints.PceConstraints.ResourcePair; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Elements; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.RouteIncludeEro; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TeHopType; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TeNodeId; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TePathDisjointness; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TeTpId; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.common.constraints_config.TeBandwidth; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.common.constraints_config.TeBandwidthBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.Type; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.type.NumUnnumHopBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.type.num.unnum.hop.NumUnnumHop; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.generic.path.constraints.PathConstraints; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.generic.path.constraints.PathConstraintsBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.gnpy.specific.parameters.EffectiveFreqSlot; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.gnpy.specific.parameters.EffectiveFreqSlotBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.ExplicitRouteObjects; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.ExplicitRouteObjectsBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.explicit.route.objects.RouteObjectIncludeExclude; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.explicit.route.objects.RouteObjectIncludeExcludeBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.service.PathRequest; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.service.PathRequestBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.Synchronization; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.SynchronizationBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.synchronization.Svec; -import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.synchronization.SvecBuilder; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.PathComputationRequestInput; -import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirection; -import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirection; -import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.atoz.direction.AToZ; -import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ztoa.direction.ZToA; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.transportpce.pce.gnpy.utils.AToZComparator; +import org.opendaylight.transportpce.pce.gnpy.utils.ZToAComparator; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.Elements; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.ElementsKey; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.RouteIncludeEro; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.TeHopType; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.TePathDisjointness; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.common.constraints_config.TeBandwidth; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.common.constraints_config.TeBandwidthBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.Type; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.type.NumUnnumHopBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.type.num.unnum.hop.NumUnnumHop; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.constraints.PathConstraints; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.constraints.PathConstraintsBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.gnpy.specific.parameters.EffectiveFreqSlot; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.gnpy.specific.parameters.EffectiveFreqSlotBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.ExplicitRouteObjects; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.ExplicitRouteObjectsBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.explicit.route.objects.RouteObjectIncludeExclude; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.explicit.route.objects.RouteObjectIncludeExcludeBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.explicit.route.objects.RouteObjectIncludeExcludeKey; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequest; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequestBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequestKey; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.Synchronization; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.SynchronizationBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.synchronization.Svec; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.synchronization.SvecBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev211210.FrequencyTHz; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.ModulationFormat; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirection; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ZToADirection; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.atoz.direction.AToZ; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ztoa.direction.ZToA; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.Resource; +import org.opendaylight.yangtools.yang.common.Uint32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** - * Class to create the topology corresponding to GNPy requirements. + * Class to create the service corresponding to GNPy requirements. * * @author Ahmed Triki ( ahmed.triki@orange.com ) * @@ -60,295 +76,197 @@ import org.slf4j.LoggerFactory; public class GnpyServiceImpl { private static final Logger LOG = LoggerFactory.getLogger(GnpyServiceImpl.class); - private List pathRequest = new ArrayList<>(); + + private Map pathRequest = new HashMap<>(); private List synchronization = new ArrayList<>(); - private Map mapDisgNodeRefNode = new HashMap(); - private Map mapNodeRefIp = new HashMap(); - private Map mapLinkFiber = new HashMap(); - private Map mapFiberIp = new HashMap(); - private List elements = new ArrayList<>(); + private Map mapDisgNodeRefNode = new HashMap<>(); + private Map> mapLinkFiber = new HashMap<>(); + private List trxList = new ArrayList<>(); + private Map elements = new HashMap<>(); + private Map routeObjectIncludeExcludes = new HashMap<>(); + private String currentNodeId = null; + private AToZComparator atoZComparator = new AToZComparator(); + private ZToAComparator ztoAComparator = new ZToAComparator(); + private static final Table TRX_MODE_TABLE = initTrxModeTable(); + + private static Table initTrxModeTable() { + Table trxModeTable = HashBasedTable.create(); + trxModeTable.put(ServiceRateConstant.RATE_100, GridConstant.SLOT_WIDTH_50, "100 Gbit/s, 27.95 Gbaud, DP-QPSK"); + trxModeTable.put(ServiceRateConstant.RATE_200, GridConstant.SLOT_WIDTH_50, "200 Gbit/s, 31.57 Gbaud, DP-16QAM"); + trxModeTable.put(ServiceRateConstant.RATE_200, GridConstant.SLOT_WIDTH_87_5, "200 Gbit/s, DP-QPSK"); + trxModeTable.put(ServiceRateConstant.RATE_300, GridConstant.SLOT_WIDTH_87_5, "300 Gbit/s, DP-8QAM"); + trxModeTable.put(ServiceRateConstant.RATE_400, GridConstant.SLOT_WIDTH_87_5, "400 Gbit/s, DP-16QAM"); + return trxModeTable; + } + + public static final Map RATE_OUTPUTPOWER = Map.of( + ServiceRateConstant.RATE_100, GridConstant.OUTPUT_POWER_100GB_W, + ServiceRateConstant.RATE_400, GridConstant.OUTPUT_POWER_400GB_W); /* * Construct the GnpyServiceImpl */ - public GnpyServiceImpl(PathComputationRequestInput input, AToZDirection atoz, Long requestId, GnpyTopoImpl gnpyTopo, - PceConstraints pceHardConstraints) { + public GnpyServiceImpl(PathComputationRequestInput input, AToZDirection atoz, Uint32 requestId, + GnpyTopoImpl gnpyTopo, PceConstraints pceHardConstraints) throws GnpyException { this.elements = gnpyTopo.getElements(); this.mapDisgNodeRefNode = gnpyTopo.getMapDisgNodeRefNode(); - this.mapNodeRefIp = gnpyTopo.getMapNodeRefIp(); this.mapLinkFiber = gnpyTopo.getMapLinkFiber(); - this.mapFiberIp = gnpyTopo.getMapFiberIp(); - - this.pathRequest = extractPathRequest(input, atoz, requestId, pceHardConstraints); + this.trxList = gnpyTopo.getTrxList(); + this.pathRequest = extractPathRequest(input, atoz, requestId.toJava(), pceHardConstraints); this.synchronization = extractSynchronization(requestId); } - public GnpyServiceImpl(PathComputationRequestInput input, ZToADirection ztoa, Long requestId, GnpyTopoImpl gnpyTopo, - PceConstraints pceHardConstraints) { + public GnpyServiceImpl(PathComputationRequestInput input, ZToADirection ztoa, Uint32 requestId, + GnpyTopoImpl gnpyTopo, PceConstraints pceHardConstraints) throws GnpyException { this.elements = gnpyTopo.getElements(); this.mapDisgNodeRefNode = gnpyTopo.getMapDisgNodeRefNode(); - this.mapNodeRefIp = gnpyTopo.getMapNodeRefIp(); this.mapLinkFiber = gnpyTopo.getMapLinkFiber(); - this.mapFiberIp = gnpyTopo.getMapFiberIp(); - - pathRequest = extractPathRequest(input, ztoa, requestId, pceHardConstraints); + this.trxList = gnpyTopo.getTrxList(); + pathRequest = extractPathRequest(input, ztoa, requestId.toJava(), pceHardConstraints); synchronization = extractSynchronization(requestId); } - //Create the pathRequest - public List extractPathRequest(PathComputationRequestInput input, AToZDirection atoz, Long requestId, - PceConstraints pceHardConstraints) { - // 1.1 Create explicitRouteObjects - // 1.1.1. create RouteObjectIncludeExclude list - List routeObjectIncludeExcludes = new ArrayList<>(); - IpAddress ipAddressCurrent = null; - Long index = (long) 0; - // List of A to Z - List listAtoZ = atoz.getAToZ(); - if (listAtoZ != null) { - int atozSize = listAtoZ.size(); - for (int i = 0; i < atozSize; i++) { - String nodeId = null; - if (listAtoZ.get(i).getResource().getResource() - instanceof - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Node) { - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Node node = - (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Node) listAtoZ.get(i).getResource().getResource(); - - nodeId = node.getNodeId(); - if (nodeId != null) { - String nodeRef = this.mapDisgNodeRefNode.get(nodeId); - IpAddress ipAddress = this.mapNodeRefIp.get(nodeRef); - for (Elements element : this.elements) { - if (element.getUid().contains(ipAddress.getIpv4Address().getValue().toString())) { - if ((ipAddressCurrent == null) || (ipAddressCurrent != ipAddress)) { - ipAddressCurrent = ipAddress; - // Fill in routeObjectIncludeExcludes - RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude( - ipAddress, 1, index); - routeObjectIncludeExcludes.add(routeObjectIncludeExclude1); - index++; - } - break; - } - } - } else { - LOG.warn("node ID is null"); - } - // TODO else if termination point not implemented in this - // version - } else if (listAtoZ.get(i).getResource().getResource() - instanceof - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Link) { - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Link link = - (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Link) listAtoZ.get(i).getResource().getResource(); - - String clfi = this.mapLinkFiber.get(link.getLinkId()); - IpAddress fiberIp = this.mapFiberIp.get(clfi); - if (clfi != null) { - RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude(fiberIp, 1, - index); - routeObjectIncludeExcludes.add(routeObjectIncludeExclude1); - index++; - } - } - } + private Map extractPathRequest( + PathComputationRequestInput input, AToZDirection atoz, Long requestId, + PceConstraints pceHardConstraints) throws GnpyException { + + // Create the source and destination nodes + String sourceNode = input.getServiceAEnd().getNodeId(); + String destNode = input.getServiceZEnd().getNodeId(); + if (!trxList.contains(sourceNode) || !trxList.contains(destNode)) { + throw new GnpyException("In GnpyServiceImpl: source and destination should be transmitter nodes"); } - else { - routeObjectIncludeExcludes = extractHardConstraints(pceHardConstraints); - //TODO integrate the maxLatency/ Metric and max OSNR as additional constraints to GNPy + + // Create explicitRouteObjects + List listAtoZ = new ArrayList<>(atoz.nonnullAToZ().values()); + if (listAtoZ.isEmpty()) { + extractHardConstraints(pceHardConstraints); + } else { + Collections.sort(listAtoZ, atoZComparator); + extractRouteObjectIcludeAtoZ(listAtoZ); } - // 1.1. Create ExplicitRouteObjects ExplicitRouteObjects explicitRouteObjects = new ExplicitRouteObjectsBuilder() .setRouteObjectIncludeExclude(routeObjectIncludeExcludes).build(); - // 1.2 Create a path constraints - Long rate = atoz.getRate(); - // 1.2.1. Create EffectiveFreqSlot - List effectiveFreqSlot = new ArrayList<>(); - EffectiveFreqSlot effectiveFreqSlot1 = new EffectiveFreqSlotBuilder().setM(5).setN(8).build(); - effectiveFreqSlot.add(effectiveFreqSlot1); - // 1.2.2. Create Te-Bandwidth - TeBandwidth teBandwidth = new TeBandwidthBuilder().setPathBandwidth(new BigDecimal(rate)) - .setTechnology("flexi-grid").setTrxType("openroadm-beta1").setTrxMode("W100G") - .setEffectiveFreqSlot(effectiveFreqSlot).setSpacing(new BigDecimal(50000000000.0)).build(); - PathConstraints pathConstraints = new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build(); - // 1.3. Create the source and destination nodes - String sourceNode = input.getServiceAEnd().getNodeId(); - String destNode = input.getServiceZEnd().getNodeId(); - // Create the path-request elements + //Create Path Constraint + PathConstraints pathConstraints = createPathConstraints(atoz.getRate().toJava(), + atoz.getModulationFormat(), + atoz.getAToZMinFrequency(), + atoz.getAToZMaxFrequency()); + // Create the path request - List pathRequestList = new ArrayList<>(); - PathRequest pathRequest1 = new PathRequestBuilder().setRequestId(requestId) - .setSource(this.mapNodeRefIp.get(sourceNode)).setDestination(this.mapNodeRefIp.get(destNode)) - .setSrcTpId("srcTpId".getBytes()).setDstTpId("dstTpId".getBytes()).setPathConstraints(pathConstraints) + Map pathRequestMap = new HashMap<>(); + PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(requestId.toString()) + .setSource(sourceNode) + .setDestination(destNode) + .setSrcTpId(sourceNode) + .setDstTpId(destNode) + .setBidirectional(false).setPathConstraints(pathConstraints).setPathConstraints(pathConstraints) .setExplicitRouteObjects(explicitRouteObjects).build(); - pathRequestList.add(pathRequest1); - return pathRequestList; + pathRequestMap.put(pathRequestEl.key(),pathRequestEl); + LOG.debug("In GnpyServiceImpl: path request AToZ is extracted"); + return pathRequestMap; } - public List extractPathRequest(PathComputationRequestInput input, ZToADirection ztoa, Long requestId, - PceConstraints pceHardConstraints) { - // 1.1 Create explicitRouteObjects - // 1.1.1. create RouteObjectIncludeExclude list - List routeObjectIncludeExcludes = new ArrayList<>(); - IpAddress ipAddressCurrent = null; - Long index = (long) 0; - List listZtoA = ztoa.getZToA(); - if (listZtoA != null) { - int ztoaSize = listZtoA.size(); - for (int i = 0; i < ztoaSize; i++) { - String nodeId = null; - if (listZtoA.get(i).getResource().getResource() - instanceof - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Node) { - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Node node = - (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Node) listZtoA.get(i).getResource().getResource(); - nodeId = node.getNodeId(); - if (nodeId != null) { - String nodeRef = this.mapDisgNodeRefNode.get(nodeId); - IpAddress ipAddress = this.mapNodeRefIp.get(nodeRef); - for (Elements element : this.elements) { - if (element.getUid().contains(ipAddress.getIpv4Address().getValue().toString())) { - if ((ipAddressCurrent == null) || (ipAddressCurrent != ipAddress)) { - ipAddressCurrent = ipAddress; - // Fill in routeObjectIncludeExcludes - RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude( - ipAddress, 1, index); - routeObjectIncludeExcludes.add(routeObjectIncludeExclude1); - index++; - } - break; - } - } - } else { - LOG.warn("node ID is null"); - } - // TODO else if termination point not implemented in this - // version - } else if (listZtoA.get(i).getResource().getResource() - instanceof - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Link) { - - org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Link link = - (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017 - .pce.resource.resource.resource.Link) listZtoA.get(i).getResource().getResource(); - String clfi = this.mapLinkFiber.get(link.getLinkId()); - IpAddress fiberIp = this.mapFiberIp.get(clfi); - if (clfi != null) { - RouteObjectIncludeExclude routeObjectIncludeExclude1 = - addRouteObjectIncludeExclude(fiberIp, 1, index); - routeObjectIncludeExcludes.add(routeObjectIncludeExclude1); - index++; - } - - } - } + private Map extractPathRequest( + PathComputationRequestInput input, ZToADirection ztoa, Long requestId, + PceConstraints pceHardConstraints) throws GnpyException { + // Create the source and destination nodes + String sourceNode = input.getServiceZEnd().getNodeId(); + String destNode = input.getServiceAEnd().getNodeId(); + if (!trxList.contains(sourceNode) || !trxList.contains(destNode)) { + throw new GnpyException("In GnpyServiceImpl: source and destination should be transmitter nodes"); + } + // Create explicitRouteObjects + @NonNull List listZtoA = new ArrayList<>(ztoa.nonnullZToA().values()); + if (listZtoA.isEmpty()) { + extractHardConstraints(pceHardConstraints); } else { - routeObjectIncludeExcludes = extractHardConstraints(pceHardConstraints); + Collections.sort(listZtoA, ztoAComparator); + extractRouteObjectIcludeZtoA(listZtoA); } - // 1.1. Create ExplicitRouteObjects ExplicitRouteObjects explicitRouteObjects = new ExplicitRouteObjectsBuilder() .setRouteObjectIncludeExclude(routeObjectIncludeExcludes).build(); - // 1.2 Create a path constraints - Long rate = ztoa.getRate(); - // 1.2.1. Create EffectiveFreqSlot - List effectiveFreqSlot = new ArrayList<>(); - EffectiveFreqSlot effectiveFreqSlot1 = new EffectiveFreqSlotBuilder().setM(5).setN(8).build(); - effectiveFreqSlot.add(effectiveFreqSlot1); - // 1.2.2. Create Te-Bandwidth - TeBandwidth teBandwidth = new TeBandwidthBuilder().setPathBandwidth(new BigDecimal(rate)) - .setTechnology("flexi-grid").setTrxType("openroadm-beta1").setTrxMode("W100G") - .setEffectiveFreqSlot(effectiveFreqSlot).setSpacing(new BigDecimal(50000000000.0)).build(); - PathConstraints pathConstraints = new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build(); - // 1.3. Create the source and destination nodes - String sourceNode = input.getServiceZEnd().getNodeId(); - String destNode = input.getServiceAEnd().getNodeId(); - // Create the path-request elements - // Create the path request - List pathRequestList = new ArrayList<>(); - PathRequest pathRequest1 = new PathRequestBuilder().setRequestId(requestId) - .setSource(this.mapNodeRefIp.get(sourceNode)).setDestination(this.mapNodeRefIp.get(destNode)) - .setSrcTpId("srcTpId".getBytes()).setDstTpId("dstTpId".getBytes()).setPathConstraints(pathConstraints) + //Create Path Constraint + PathConstraints pathConstraints = createPathConstraints(ztoa.getRate().toJava(), + ztoa.getModulationFormat(), + ztoa.getZToAMinFrequency(), + ztoa.getZToAMaxFrequency()); + + //Create the path request + Map pathRequestMap = new HashMap<>(); + PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(requestId.toString()) + .setSource(sourceNode) + .setDestination(destNode) + .setSrcTpId(sourceNode) + .setDstTpId(destNode) + .setBidirectional(false).setPathConstraints(pathConstraints) .setExplicitRouteObjects(explicitRouteObjects).build(); - pathRequestList.add(pathRequest1); - return pathRequestList; + pathRequestMap.put(pathRequestEl.key(),pathRequestEl); + LOG.debug("In GnpyServiceImpl: path request ZToA is extracted is extracted"); + return pathRequestMap; } - //Create RouteObjectIncludeExclude list - public List extractHardConstraints(PceConstraints pceHardConstraints) { - List listNodeToInclude = getListToInclude(pceHardConstraints); - List routeObjectIncludeExcludes = new ArrayList<>(); - IpAddress ipAddressCurrent = null; - Long index = (long) 0; - if (listNodeToInclude != null) { - for (int i = 0; i < listNodeToInclude.size(); i++) { - String nodeId = listNodeToInclude.get(i); - if (nodeId != null) { - IpAddress ipAddress = this.mapNodeRefIp.get(nodeId); - for (Elements element : this.elements) { - if (element.getUid().contains(ipAddress.getIpv4Address().getValue().toString())) { - if ((ipAddressCurrent == null) || (ipAddressCurrent != ipAddress)) { - ipAddressCurrent = ipAddress; - // Fill in routeObjectIncludeExcludes - RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude( - ipAddress, 1, index); - routeObjectIncludeExcludes.add(routeObjectIncludeExclude1); - index++; - } - break; - } - } - } else { - LOG.warn("node ID is null"); - } - } + //Extract RouteObjectIncludeExclude list in the case of pre-computed path A-to-Z + private void extractRouteObjectIcludeAtoZ(Collection listAtoZ) throws GnpyException { + Long index = 0L; + for (AToZ entry : listAtoZ) { + index = createResource(entry.getResource().getResource(),index); } - return routeObjectIncludeExcludes; } - // Create the synchronization - public List extractSynchronization(Long requestId) { - // Create RequestIdNumber - List requestIdNumber = new ArrayList<>(); - requestIdNumber.add(requestId); - // Create a synchronization - Svec svec = new SvecBuilder().setRelaxable(true).setDisjointness(new TePathDisjointness(true, true, false)) - .setRequestIdNumber(requestIdNumber).build(); - List synchro = new ArrayList<>(); - Synchronization synchronization1 = new SynchronizationBuilder().setSynchronizationId(new Long(0)).setSvec(svec) - .build(); - synchro.add(synchronization1); - return (synchro); + //Extract RouteObjectIncludeExclude list in the case of pre-computed path Z-to-A + private void extractRouteObjectIcludeZtoA(@NonNull List listZtoA) throws GnpyException { + Long index = 0L; + for (ZToA entry : listZtoA) { + index = createResource(entry.getResource().getResource(),index); + } } - // Add routeObjectIncludeExclude - private RouteObjectIncludeExclude addRouteObjectIncludeExclude(IpAddress ipAddress, long teTpValue, long index) { - TeNodeId teNodeId = new TeNodeId(ipAddress); - TeTpId teTpId = new TeTpId(teTpValue); - NumUnnumHop numUnnumHop = new org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.type.num - .unnum.hop.NumUnnumHopBuilder().setNodeId(teNodeId.getIpv4Address().getValue().toString()) - .setLinkTpId(teTpId.getUint32().toString()).setHopType(TeHopType.STRICT).build(); - Type type1 = new NumUnnumHopBuilder().setNumUnnumHop(numUnnumHop).build(); - // Create routeObjectIncludeExclude element 1 - RouteObjectIncludeExclude routeObjectIncludeExclude1 = new RouteObjectIncludeExcludeBuilder().setIndex(index) - .setExplicitRouteUsage(RouteIncludeEro.class).setType(type1).build(); - return routeObjectIncludeExclude1; + //Create a new resource node or link + private Long createResource(@Nullable Resource resource, Long index) throws GnpyException { + Long idx = index; + if (resource + instanceof + org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705 + .pce.resource.resource.resource.Node) { + org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705 + .pce.resource.resource.resource.Node node = + (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705 + .pce.resource.resource.resource.Node) resource; + if (node.getNodeId() == null) { + throw new GnpyException("In gnpyServiceImpl: nodeId is null"); + } + idx = addNodeToRouteObject(this.mapDisgNodeRefNode.get(node.getNodeId()),idx); + } + + if (resource + instanceof + org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705 + .pce.resource.resource.resource.Link) { + org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705 + .pce.resource.resource.resource.Link link = + (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705 + .pce.resource.resource.resource.Link) resource; + idx = addLinkToRouteObject(link.getLinkId(),idx); + } + return idx; + } + + //Create RouteObjectIncludeExclude list in the case of hard constraint + private void extractHardConstraints(PceConstraints pceHardConstraints) throws GnpyException { + List listNodeToInclude = getListToInclude(pceHardConstraints); + if (!listNodeToInclude.isEmpty()) { + Long index = 0L; + for (int i = 0; i < listNodeToInclude.size(); i++) { + String nodeId = listNodeToInclude.get(i); + index = addNodeToRouteObject(nodeId, index); + } + } } - // Create the list of nodes to include + //Create the list of nodes to include private List getListToInclude(PceConstraints pceHardConstraints) { List listNodeToInclude = new ArrayList<>(); if (pceHardConstraints != null) { @@ -364,11 +282,121 @@ public class GnpyServiceImpl { return listNodeToInclude; } - public List getPathRequest() { + //Add a node to the route object + private Long addNodeToRouteObject(String nodeRef, Long index) throws GnpyException { + Long idx = index; + for (Elements element : this.elements.values()) { + if (element.getUid().equals(nodeRef)) { + if ((this.currentNodeId == null) || (!this.currentNodeId.equals(nodeRef))) { + this.currentNodeId = nodeRef; + RouteObjectIncludeExclude routeObjectIncludeExclude = addRouteObjectIncludeExclude(nodeRef, + Uint32.valueOf(1), idx); + RouteObjectIncludeExcludeKey key = new RouteObjectIncludeExcludeKey(Uint32.valueOf(idx)); + routeObjectIncludeExcludes.put(key, routeObjectIncludeExclude); + idx += 1; + } + return idx; + } + } + throw new GnpyException(String.format("In gnpyServiceImpl : NodeRef %s does not exist",nodeRef)); + } + + //Add a link to the route object + private Long addLinkToRouteObject(String linkId, Long index) throws GnpyException { + Long idx = index; + if (linkId == null) { + throw new GnpyException("In GnpyServiceImpl: the linkId is null"); + } + //Only the ROADM-to-ROADM link are included in the route object + if (!mapLinkFiber.containsKey(linkId)) { + return idx; + } + List listSubLink = this.mapLinkFiber.get(linkId); + if (listSubLink == null) { + throw new GnpyException(String.format("In gnpyServiceImpl addNodeRouteObject : no sublink in %s",linkId)); + } + for (String subLink : listSubLink) { + RouteObjectIncludeExclude routeObjectIncludeExclude = + addRouteObjectIncludeExclude(subLink, Uint32.valueOf(1),idx); + RouteObjectIncludeExcludeKey key = new RouteObjectIncludeExcludeKey(Uint32.valueOf(idx)); + routeObjectIncludeExcludes.put(key, routeObjectIncludeExclude); + idx += 1; + } + return idx; + } + + // Add routeObjectIncludeExclude + private RouteObjectIncludeExclude addRouteObjectIncludeExclude(String nodeId, Uint32 teTpValue, Long index) { + NumUnnumHop numUnnumHop = new org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.type.num + .unnum.hop.NumUnnumHopBuilder() + .setNodeId(nodeId) + .setLinkTpId(teTpValue.toString()) + .setHopType(TeHopType.STRICT).build(); + Type type1 = new NumUnnumHopBuilder().setNumUnnumHop(numUnnumHop).build(); + // Create routeObjectIncludeExclude element + return new RouteObjectIncludeExcludeBuilder() + .setIndex(Uint32.valueOf(index)).setExplicitRouteUsage(RouteIncludeEro.class).setType(type1).build(); + } + + //Create the path constraints + private PathConstraints createPathConstraints(Long rate, String modulationFormat, FrequencyTHz minFrequency, + FrequencyTHz maxFrequency) { + BigDecimal spacing = GridConstant.SLOT_WIDTH_50; + int mvalue = GridConstant.NB_SLOTS_100G; + int nvalue = 0; + if (minFrequency != null && maxFrequency != null && modulationFormat != null) { + LOG.info("Creating path constraints for rate {}, modulationFormat {}, min freq {}, max freq {}", rate, + modulationFormat, minFrequency, maxFrequency); + ModulationFormat mformat = ModulationFormat.DpQpsk; + Optional optionalModulationFormat = ModulationFormat.forName(modulationFormat); + if (optionalModulationFormat.isPresent()) { + mformat = optionalModulationFormat.get(); + } + spacing = GridConstant.FREQUENCY_SLOT_WIDTH_TABLE.get(Uint32.valueOf(rate), mformat); + FrequencyTHz centralFrequency = GridUtils + .getCentralFrequency(minFrequency.getValue(), maxFrequency.getValue()); + int centralFrequencyBitSetIndex = GridUtils.getIndexFromFrequency(centralFrequency.getValue()); + mvalue = (int) Math.ceil(spacing.doubleValue() / (GridConstant.GRANULARITY)); + nvalue = GridUtils.getNFromFrequencyIndex(centralFrequencyBitSetIndex); + } + LOG.info("Creating path constraints for rate {}, mvalue {}, nvalue {}, spacing {}", rate, + mvalue, nvalue, spacing); + EffectiveFreqSlot effectiveFreqSlot = new EffectiveFreqSlotBuilder() + .setM(Uint32.valueOf(mvalue / 2)).setN(nvalue).build(); + + TeBandwidth teBandwidth = new TeBandwidthBuilder() + .setPathBandwidth(BigDecimal.valueOf(rate * 1e9)) + .setTechnology("flexi-grid").setTrxType("OpenROADM MSA ver. 5.0") + .setTrxMode(TRX_MODE_TABLE.get(Uint32.valueOf(rate), spacing)) + .setOutputPower(GridUtils.convertDbmW(GridConstant.OUTPUT_POWER_100GB_DBM + + 10 * Math.log10(mvalue / (double)GridConstant.NB_SLOTS_100G))) + .setEffectiveFreqSlot(Map.of(effectiveFreqSlot.key(), effectiveFreqSlot)) + .setSpacing(spacing.multiply(BigDecimal.valueOf(1e9))).build(); + return new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build(); + } + + //Create the synchronization + private List extractSynchronization(Uint32 requestId) { + // Create RequestIdNumber + List requestIdNumber = new ArrayList<>(); + requestIdNumber.add(requestId.toString()); + // Create a synchronization + Svec svec = new SvecBuilder().setRelaxable(true) + .setDisjointness(new TePathDisjointness(true, true, false)) + .setRequestIdNumber(requestIdNumber).build(); + List synchro = new ArrayList<>(); + Synchronization synchronization1 = new SynchronizationBuilder() + .setSynchronizationId(Uint32.valueOf(0).toString()) + .setSvec(svec).build(); + synchro.add(synchronization1); + return (synchro); + } + + public Map getPathRequest() { return pathRequest; } - public void setPathRequest(List pathRequest) { + public void setPathRequest(Map pathRequest) { this.pathRequest = pathRequest; }