From: atriki Date: Wed, 8 Jan 2020 09:51:52 +0000 (+0100) Subject: Consolidation of the GNPy module X-Git-Tag: 1.0.0~33^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=transportpce.git;a=commitdiff_plain;h=56dd2add269f0fdc8efdc1e3bfece25301ba6a3f;ds=sidebyside Consolidation of the GNPy module - add GnpyException to manage unexpected events - expand the 32-bit identification field of fibers to range from 243.0.0.1 to 243.255.255.255 - expand the 32-bit identification field of EDFAs to range from 244.0.0.1 to 244.255.255.255 (the 32-bit identifiers are not ipv4 addresses but use the same dotted-decimal notation. This format is imposed by GNPy yang model to comply with the IETF recommendations and to be compliant with planning tools coming from the IP world.) - code refactoring Signed-off-by: atriki Change-Id: Ifa41c68874b8d87abe746cd6c1b87ee950131a32 --- diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java b/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java index 3ca6b942e..4b6b05133 100755 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java @@ -13,6 +13,7 @@ import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.pce.constraints.PceConstraints; import org.opendaylight.transportpce.pce.constraints.PceConstraintsCalc; import org.opendaylight.transportpce.pce.gnpy.ConnectToGnpyServer; +import org.opendaylight.transportpce.pce.gnpy.GnpyException; import org.opendaylight.transportpce.pce.gnpy.GnpyResult; import org.opendaylight.transportpce.pce.gnpy.GnpyUtilitiesImpl; import org.opendaylight.transportpce.pce.graph.PceGraph; @@ -86,8 +87,7 @@ public class PceSendingPceRPCs { LOG.info("cancelResourceReserve ..."); } - public void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints) - throws Exception { + public void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints) { PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc); @@ -137,71 +137,88 @@ public class PceSendingPceRPCs { this.message = rc.getMessage(); this.responseCode = rc.getResponseCode(); - if (!rc.getStatus()) { - LOG.error("In pathComputation, pathComputationWithConstraints: result = {}", rc.toString()); - return; + AToZDirection atoz = null; + ZToADirection ztoa = null; + if (rc.getStatus()) { + atoz = rc.getAtoZDirection(); + ztoa = rc.getZtoADirection(); } - // Verify the path with GNPy - AToZDirection atoz = rc.getAtoZDirection(); - ZToADirection ztoa = rc.getZtoADirection(); - ConnectToGnpyServer connectToGnpy = new ConnectToGnpyServer(); - - // Verify that the GNPy server exists - if (connectToGnpy.isGnpyURLExist()) { - LOG.info("Gnpy instance is connected T-PCE"); - GnpyUtilitiesImpl gnpy = new GnpyUtilitiesImpl(networkTransaction, input); - if (gnpy.verifyComputationByGnpy(atoz, ztoa, pceHardConstraints)) { - LOG.info("The path is feasible according to Gnpy"); - setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa)); - } - else { - LOG.info("The path is not feasible according to Gnpy"); - HardConstraints gnpyPathAsHC = null; - gnpyPathAsHC = gnpy.askNewPathFromGnpy(atoz, ztoa, gnpyPathAsHC, pceHardConstraints); - if (gnpyPathAsHC != null) { - LOG.info("GNPy succeed to find another path"); - // Compute the path - PathComputationRequestInput inputFromGnpy = new PathComputationRequestInputBuilder() - .setServiceName(input.getServiceName()) - .setHardConstraints(gnpyPathAsHC) - .setSoftConstraints(input.getSoftConstraints()) - .setPceMetric(PceMetric.HopCount) - .setServiceAEnd(input.getServiceAEnd()) - .setServiceZEnd(input.getServiceZEnd()) - .build(); - PceConstraintsCalc constraintsGnpy = new PceConstraintsCalc(inputFromGnpy, networkTransaction); - PceConstraints gnpyHardConstraints = constraintsGnpy.getPceHardConstraints(); - PceConstraints gnpySoftConstraints = constraintsGnpy.getPceSoftConstraints(); - pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints); - atoz = rc.getAtoZDirection(); - ztoa = rc.getZtoADirection(); + try { + ConnectToGnpyServer connectToGnpy = new ConnectToGnpyServer(); + if (connectToGnpy.isGnpyURLExist()) { + GnpyUtilitiesImpl gnpy = new GnpyUtilitiesImpl(networkTransaction, input); + if (rc.getStatus() && gnpyToCheckFeasiblity(atoz,ztoa,gnpy)) { setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa)); - if (gnpy.verifyComputationByGnpy(atoz, ztoa, pceHardConstraints)) { - LOG.info("In pathComputation: the new path computed by GNPy is valid"); - setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa)); - this.success = true; - this.message = "Path is calculated by GNPy "; - this.responseCode = ResponseCodes.RESPONSE_OK; - } else { - LOG.info("In pathComputation: the new path computed by GNPy is not valid"); - this.success = false; - this.message = "No path available "; - this.responseCode = ResponseCodes.RESPONSE_FAILED; - } - } else { - LOG.info("GNPy failed to find another path"); - this.success = false; - this.message = "No path available by PCE and GNPy "; - this.responseCode = ResponseCodes.RESPONSE_FAILED; + return; } + callGnpyToComputeNewPath(gnpy); + } else { + setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa)); + return; } + } + catch (GnpyException e) { + LOG.error("Exception raised by GNPy {}",e.getMessage()); + setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa)); + return; + } + return; + } + + private boolean gnpyToCheckFeasiblity(AToZDirection atoz, ZToADirection ztoa, GnpyUtilitiesImpl gnpy) + throws GnpyException, Exception { + + //Call GNPy for path verification + if (gnpy.verifyComputationByGnpy(atoz, ztoa, pceHardConstraints)) { + LOG.info("In pceSendingPceRPC: the path is feasible according to Gnpy"); gnpyAtoZ = gnpy.getGnpyAtoZ(); gnpyZtoA = gnpy.getGnpyZtoA(); - } else { - LOG.info("in PCESendingPceRPCs: Cannot connect to GNPy!!"); + return true; + } + return false; + } + + private void callGnpyToComputeNewPath(GnpyUtilitiesImpl gnpy) throws GnpyException, Exception { + + //Call GNPy in the case of non feasibility + LOG.info("In pceSendingPceRPC: the path is not feasible according to Gnpy"); + HardConstraints gnpyPathAsHC = null; + gnpyPathAsHC = gnpy.askNewPathFromGnpy(gnpyPathAsHC, pceHardConstraints); + if (gnpyPathAsHC == null) { + LOG.info("In pceSendingPceRPC: GNPy failed to find another path"); + this.success = false; + this.message = "No path available by PCE and GNPy "; + this.responseCode = ResponseCodes.RESPONSE_FAILED; + gnpyAtoZ = gnpy.getGnpyAtoZ(); + gnpyZtoA = gnpy.getGnpyZtoA(); + return; + } + + LOG.info("In pceSendingPceRPC: GNPy succeed to find another path"); + // Compute the path + PathComputationRequestInput inputFromGnpy = new PathComputationRequestInputBuilder() + .setServiceName(input.getServiceName()).setHardConstraints(gnpyPathAsHC) + .setSoftConstraints(input.getSoftConstraints()).setPceMetric(PceMetric.HopCount) + .setServiceAEnd(input.getServiceAEnd()).setServiceZEnd(input.getServiceZEnd()).build(); + PceConstraintsCalc constraintsGnpy = new PceConstraintsCalc(inputFromGnpy, networkTransaction); + PceConstraints gnpyHardConstraints = constraintsGnpy.getPceHardConstraints(); + PceConstraints gnpySoftConstraints = constraintsGnpy.getPceSoftConstraints(); + pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints); + AToZDirection atoz = rc.getAtoZDirection(); + ZToADirection ztoa = rc.getZtoADirection(); + if (gnpyToCheckFeasiblity(atoz, ztoa,gnpy)) { + LOG.info("In pceSendingPceRPC: the new path computed by GNPy is valid"); + this.success = true; + this.message = "Path is calculated by GNPy"; + this.responseCode = ResponseCodes.RESPONSE_OK; setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa)); - LOG.info("In pathComputation Graph is Found"); + } else { + LOG.info("In pceSendingPceRPC: the new path computed by GNPy is not valid"); + this.success = false; + this.message = "No path available"; + this.responseCode = ResponseCodes.RESPONSE_FAILED; + setPathDescription(new PathDescriptionBuilder().setAToZDirection(null).setZToADirection(null)); } } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ConnectToGnpyServer.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ConnectToGnpyServer.java index ef5a7054b..5c88fab8c 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ConnectToGnpyServer.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ConnectToGnpyServer.java @@ -15,7 +15,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; -import java.net.MalformedURLException; import java.net.URL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,8 +31,9 @@ public class ConnectToGnpyServer { private static final Logger LOG = LoggerFactory.getLogger(ConnectToGnpyServer.class); static final String URL_GNPY = "http://127.0.0.1:8008/gnpy/api/v1.0/files"; - public String gnpyCnx(String jsonTxt) { + public String gnpyCnx(String jsonTxt) throws GnpyException { String jsonRespTxt = null; + try { URL url = new URL(URL_GNPY); String userCredentials = "gnpy:gnpy"; @@ -50,22 +50,16 @@ public class ConnectToGnpyServer { os.write(jsonTxt.getBytes()); os.flush(); if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) { - LOG.error("No valid response from GNPy : HTTP error code : {}", conn.getResponseCode()); - return null; + throw new GnpyException(String.format( + "In connectToGnpyServer: could not connect to GNPy - response code: %s",conn.getResponseCode())); } InputStreamReader response = new InputStreamReader((conn.getInputStream())); if (response != null) { - try { - jsonRespTxt = CharStreams.toString(response); - } catch (IOException e1) { - LOG.warn("Could not read characters of GNPy response: {}", e1.getMessage()); - } + jsonRespTxt = CharStreams.toString(response); } conn.disconnect(); - } catch (MalformedURLException e) { - LOG.warn("Exception : Malformed GNPy URL"); } catch (IOException e) { - LOG.warn("IOException when connecting to GNPy server: {}", e.getMessage()); + throw new GnpyException("In connectToGnpyServer: excpetion",e); } return jsonRespTxt; } @@ -83,17 +77,19 @@ public class ConnectToGnpyServer { conn.setRequestProperty("Content-Type", "application/json"); conn.connect(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + LOG.info("In connectToGnpyServer: Gnpy instance is connected to T-PCE"); exist = true; } conn.disconnect(); } catch (IOException e) { - LOG.warn("Could not connect to GNPy server"); + LOG.warn("In connectToGnpyserver: could not connect to GNPy server {}",e.getMessage()); + return exist; } return exist; } - public String readResponse(InputStreamReader response) { + public String readResponse(InputStreamReader response) throws GnpyException { String output = null; BufferedReader br = new BufferedReader(response); String line; @@ -104,7 +100,7 @@ public class ConnectToGnpyServer { } output = sb.toString(); } catch (IOException e) { - LOG.warn("IOException when reading GNPy response: {}", e.getMessage()); + throw new GnpyException("In connectToGnpyserver: could not read response",e); } return output; } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyException.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyException.java new file mode 100644 index 000000000..ae6dbc64f --- /dev/null +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyException.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2020 Orange, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.gnpy; + +/** + * Class to create exception to manage missing data for GNPy. + * + * @author Ahmed Triki ( ahmed.triki@orange.com ) + * + */ + +@SuppressWarnings("serial") +public class GnpyException extends Exception { + + public GnpyException(String message) { + super(message); + } + + public GnpyException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java index 50e2b7c8d..89adaec01 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java @@ -85,14 +85,15 @@ public class GnpyResult { private Map mapNodeRefIp = new HashMap(); //private Map mapFiberIp = new HashMap(); - public GnpyResult(String gnpyResponseString, GnpyTopoImpl gnpyTopo) throws Exception { - + public GnpyResult(String gnpyResponseString, GnpyTopoImpl gnpyTopo) throws GnpyException, Exception { this.mapNodeRefIp = gnpyTopo.getMapNodeRefIp(); // Create the schema context final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create(); Iterable moduleInfos; + moduleInfos = Collections.singleton(BindingReflections.getModuleInfo(Result.class)); moduleContext.addModuleInfos(moduleInfos); + SchemaContext schemaContext = moduleContext.tryToCreateSchemaContext().get(); // Create the binding binding normalized node codec registry @@ -106,8 +107,8 @@ public class GnpyResult { pathQname.getModule()); YangInstanceIdentifier yangId = YangInstanceIdentifier.of(pathQname); DataObject dataObject = null; + // Create the object response - // Create JsonReader from String InputStream streamGnpyRespnse = new ByteArrayInputStream(gnpyResponseString.getBytes(StandardCharsets.UTF_8)); InputStreamReader gnpyResultReader = new InputStreamReader(streamGnpyRespnse); JsonReader jsonReader = new JsonReader(gnpyResultReader); @@ -117,15 +118,14 @@ public class GnpyResult { if (codecRegistry.fromNormalizedNode(yangId, normalizedNode) != null) { dataObject = codecRegistry.fromNormalizedNode(yangId, normalizedNode).getValue(); } else { - LOG.warn("The codec registry from the normalized node is null!"); + throw new GnpyException("In GnpyResult: the codec registry from the normalized node is null!"); } List responses = null; responses = ((Result) dataObject).getResponse(); - if (responses != null) { - LOG.info("The response id is {}; ", responses.get(0).getResponseId()); - } else { - LOG.warn("The response is null!"); + if (responses == null) { + throw new GnpyException("In GnpyResult: the response from GNpy is null!"); } + LOG.info("The response id is {}; ", responses.get(0).getResponseId()); this.response = responses.get(0); analyzeResult(); } @@ -135,10 +135,10 @@ public class GnpyResult { if (response != null) { if (response.getResponseType() instanceof NoPathCase) { isFeasible = false; - LOG.info("The path is not feasible "); + LOG.info("In GnpyResult: The path is not feasible "); } else if (response.getResponseType() instanceof PathCase) { isFeasible = true; - LOG.info("The path is feasible "); + LOG.info("In GnpyResult: The path is feasible "); } } return isFeasible; @@ -250,7 +250,8 @@ public class GnpyResult { return Optional.ofNullable(result.getResult()); } - private SchemaContext getSchemaContext(Class objectClass) throws Exception { + private SchemaContext getSchemaContext(Class objectClass) throws GnpyException, Exception { + final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create(); Iterable moduleInfos; SchemaContext schemaContext = null; 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..34bbccb2d 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 @@ -15,6 +15,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import org.eclipse.jdt.annotation.Nullable; 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; @@ -47,12 +48,13 @@ import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdes 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.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce.resource.resource.Resource; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; 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,292 +62,178 @@ import org.slf4j.LoggerFactory; public class GnpyServiceImpl { private static final Logger LOG = LoggerFactory.getLogger(GnpyServiceImpl.class); + private static final double FIX_CH = 0.05; //Fix-grid channel width (THz) + private static final int NB_SLOT_BW = 4; //Number of slot in 50GHz channel (THz) + private static final double SLOT_BW = 0.00625; //Nominal central frequency granularity (THz) + private static final double MAX_CENTRAL_FREQ = 196.1; //Minimum channel center frequency (openRoadm spec) (THz) + private static final double FLEX_CENTRAL_FREQ = 193.1; //Flex-grid reference channel frequency (THz) + private static final double CONVERT_TH_HZ = 1e12; //Convert THz to Hz + private List pathRequest = new ArrayList<>(); private List synchronization = new ArrayList<>(); private Map mapDisgNodeRefNode = new HashMap(); private Map mapNodeRefIp = new HashMap(); - private Map mapLinkFiber = new HashMap(); + private Map> mapLinkFiber = new HashMap>(); private Map mapFiberIp = new HashMap(); + private List trxList = new ArrayList<>(); private List elements = new ArrayList<>(); + private List routeObjectIncludeExcludes = new ArrayList<>(); + private Long index = (long) 0; //index of the element in the path + private IpAddress currentNodeIpAddress = null; /* * Construct the GnpyServiceImpl */ public GnpyServiceImpl(PathComputationRequestInput input, AToZDirection atoz, Long requestId, GnpyTopoImpl gnpyTopo, - PceConstraints pceHardConstraints) { + 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.synchronization = extractSynchronization(requestId); + this.trxList = gnpyTopo.getTrxList(); + try { + this.pathRequest = extractPathRequest(input, atoz, requestId, pceHardConstraints); + this.synchronization = extractSynchronization(requestId); + } catch (NullPointerException e) { + throw new GnpyException("In GnpyServiceImpl: one of the elements is null",e); + } } public GnpyServiceImpl(PathComputationRequestInput input, ZToADirection ztoa, Long requestId, GnpyTopoImpl gnpyTopo, - PceConstraints pceHardConstraints) { + 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); - synchronization = extractSynchronization(requestId); + this.trxList = gnpyTopo.getTrxList(); + try { + pathRequest = extractPathRequest(input, ztoa, requestId, pceHardConstraints); + synchronization = extractSynchronization(requestId); + } catch (NullPointerException e) { + throw new GnpyException("In GnpyServiceImpl: one of the elements of service is null",e); + } } - //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(); + private List extractPathRequest(PathComputationRequestInput input, AToZDirection atoz, Long requestId, + PceConstraints pceHardConstraints) throws GnpyException { - 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++; - } - } - } - } - else { - routeObjectIncludeExcludes = extractHardConstraints(pceHardConstraints); - //TODO integrate the maxLatency/ Metric and max OSNR as additional constraints to GNPy + // 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"); } - // 1.1. Create ExplicitRouteObjects + // Create explicitRouteObjects + List listAtoZ = atoz.getAToZ(); + if (listAtoZ != null) { + extractRouteObjectIcludeAtoZ(listAtoZ); + } else { + extractHardConstraints(pceHardConstraints); + } 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(),atoz.getAToZWavelengthNumber()); + // Create the path request List pathRequestList = new ArrayList<>(); - PathRequest pathRequest1 = new PathRequestBuilder().setRequestId(requestId) + PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(requestId) .setSource(this.mapNodeRefIp.get(sourceNode)).setDestination(this.mapNodeRefIp.get(destNode)) .setSrcTpId("srcTpId".getBytes()).setDstTpId("dstTpId".getBytes()).setPathConstraints(pathConstraints) .setExplicitRouteObjects(explicitRouteObjects).build(); - pathRequestList.add(pathRequest1); + pathRequestList.add(pathRequestEl); + LOG.debug("In GnpyServiceImpl: path request AToZ is extracted"); return pathRequestList; } - 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; + private List 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 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++; - } - - } - } + extractRouteObjectIcludeZtoA(listZtoA); } else { - routeObjectIncludeExcludes = extractHardConstraints(pceHardConstraints); + extractHardConstraints(pceHardConstraints); } - - // 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 Path Constraint + //to be deleted + //Long wavelengthNumber = (ztoa.getZToAWavelengthNumber() != null) ? ztoa.getZToAWavelengthNumber() : null; + PathConstraints pathConstraints = createPathConstraints(ztoa.getRate(),ztoa.getZToAWavelengthNumber()); // Create the path request List pathRequestList = new ArrayList<>(); - PathRequest pathRequest1 = new PathRequestBuilder().setRequestId(requestId) + PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(requestId) .setSource(this.mapNodeRefIp.get(sourceNode)).setDestination(this.mapNodeRefIp.get(destNode)) .setSrcTpId("srcTpId".getBytes()).setDstTpId("dstTpId".getBytes()).setPathConstraints(pathConstraints) .setExplicitRouteObjects(explicitRouteObjects).build(); - pathRequestList.add(pathRequest1); + pathRequestList.add(pathRequestEl); + LOG.debug("In GnpyServiceImpl: path request ZToA is extracted"); return pathRequestList; } - //Create RouteObjectIncludeExclude list - public List extractHardConstraints(PceConstraints pceHardConstraints) { + //Extract RouteObjectIncludeExclude list in the case of pre-computed path A-to-Z + private void extractRouteObjectIcludeAtoZ(List listAtoZ) throws GnpyException { + for (int i = 0; i < listAtoZ.size(); i++) { + createResource(listAtoZ.get(i).getResource().getResource()); + } + } + + //Extract RouteObjectIncludeExclude list in the case of pre-computed path Z-to-A + private void extractRouteObjectIcludeZtoA(List listZtoA) throws GnpyException { + for (int i = 0; i < listZtoA.size(); i++) { + createResource(listZtoA.get(i).getResource().getResource()); + } + } + + //Create a new resource node or link + private void createResource(@Nullable Resource resource) throws GnpyException { + if (resource + 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) resource; + if (node.getNodeId() == null) { + throw new GnpyException("In gnpyServiceImpl: nodeId is null"); + } + addNodeToRouteObject(this.mapDisgNodeRefNode.get(node.getNodeId())); + return; + } + + if (resource + 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) resource; + addLinkToRouteObject(link.getLinkId()); + return; + } + } + + //Create RouteObjectIncludeExclude list in the case of hard constraint + private void extractHardConstraints(PceConstraints pceHardConstraints) throws GnpyException { 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"); - } + addNodeToRouteObject(nodeId); } } - 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); - } - - // 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 the list of nodes to include @@ -364,6 +252,108 @@ public class GnpyServiceImpl { return listNodeToInclude; } + //Add a node to the route object + private void addNodeToRouteObject(String nodeRef) throws GnpyException { + boolean found = false; + IpAddress ipAddress = this.mapNodeRefIp.get(nodeRef); + if (ipAddress == null) { + throw new GnpyException(String.format("In gnpyServiceImpl : NodeRef %s does not exist", nodeRef)); + } + + for (Elements element : this.elements) { + if (element.getUid().contains(ipAddress.getIpv4Address().getValue().toString())) { + if ((this.currentNodeIpAddress == null) || (this.currentNodeIpAddress != ipAddress)) { + this.currentNodeIpAddress = ipAddress; + RouteObjectIncludeExclude routeObjectIncludeExclude = addRouteObjectIncludeExclude(ipAddress, 1); + routeObjectIncludeExcludes.add(routeObjectIncludeExclude); + index++; + found = true; + } + return; + } + } + if (!found) { + throw new GnpyException(String.format("In gnpyServiceImpl : NodeRef %s does not exist",nodeRef)); + } + } + + //Add a link to the route object + private void addLinkToRouteObject(String linkId) throws GnpyException { + if (linkId == null) { + throw new GnpyException(String.format("In GnpyServiceImpl: the linkId %s does not exist",linkId)); + } + //Only the ROADM-to-ROADM link are included in the route object + if (!mapLinkFiber.containsKey(linkId)) { + return; + } + 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) { + IpAddress fiberIp = this.mapFiberIp.get(subLink); + if (fiberIp == null) { + throw new GnpyException(String.format("In gnpyServiceImpl addNodeRouteObject : fiberIp of %s is null", + subLink)); + } + RouteObjectIncludeExclude routeObjectIncludeExclude = addRouteObjectIncludeExclude(fiberIp, 1); + routeObjectIncludeExcludes.add(routeObjectIncludeExclude); + index++; + } + } + + // Add routeObjectIncludeExclude + private RouteObjectIncludeExclude addRouteObjectIncludeExclude(IpAddress ipAddress, long teTpValue) { + 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 + RouteObjectIncludeExclude routeObjectIncludeExclude = new RouteObjectIncludeExcludeBuilder() + .setIndex(this.index).setExplicitRouteUsage(RouteIncludeEro.class).setType(type1).build(); + return routeObjectIncludeExclude; + } + + //Create the path constraints + private PathConstraints createPathConstraints(Long rate, Long wavelengthNumber) { + // Create EffectiveFreqSlot + int freqNdex = 0; + if (wavelengthNumber != null) { + double freq = (MAX_CENTRAL_FREQ - FIX_CH * (wavelengthNumber - 1)); + freqNdex = (int) Math.round((freq - FLEX_CENTRAL_FREQ) / SLOT_BW); + } + List effectiveFreqSlot = new ArrayList<>(); + EffectiveFreqSlot effectiveFreqSlot1 = new EffectiveFreqSlotBuilder().setM(NB_SLOT_BW).setN(freqNdex).build(); + effectiveFreqSlot.add(effectiveFreqSlot1); + // Create Te-Bandwidth + TeBandwidth teBandwidth = new TeBandwidthBuilder().setPathBandwidth(new BigDecimal(rate)) + .setTechnology("flexi-grid").setTrxType("openroadm-beta1") + .setTrxMode("W100G").setEffectiveFreqSlot(effectiveFreqSlot) + .setSpacing(new BigDecimal(FIX_CH * CONVERT_TH_HZ)).build(); + PathConstraints pathConstraints = new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build(); + return pathConstraints; + } + + //Create the synchronization + private 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); + } + public List getPathRequest() { return pathRequest; } @@ -380,4 +370,4 @@ public class GnpyServiceImpl { this.synchronization = synchronization; } -} +} \ No newline at end of file diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java index 3bcdc327b..f0f55dca7 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java @@ -14,9 +14,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import java.util.regex.Pattern; import java.util.stream.IntStream; -import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; import org.opendaylight.transportpce.common.network.NetworkTransactionService; @@ -44,12 +44,14 @@ import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.El import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.elements.Metadata; import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.elements.MetadataBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.SpanAttributes; import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.amplified.link.attributes.AmplifiedLink; import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.amplified.link.attributes.amplified.link.section.element.section.element.Span; import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.amplified.link.attributes.amplified.link.section.element.section.element.ila.Ila; import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.span.attributes.LinkConcatenation; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev181130.Node1; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.networks.network.link.OMSAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId; @@ -74,6 +76,7 @@ import org.slf4j.LoggerFactory; public class GnpyTopoImpl { private static final Logger LOG = LoggerFactory.getLogger(GnpyTopoImpl.class); private final NetworkTransactionService networkTransactionService; + //List of elements private List elements = new ArrayList<>(); private List connections = new ArrayList<>(); //Mapping elements @@ -81,28 +84,37 @@ public class GnpyTopoImpl { private Map mapDisgNodeRefNode = new HashMap(); //Mapping between the ord-ntw and node ip private Map mapNodeRefIp = new HashMap(); - //Mapping between link id and clfi - private Map mapLinkFiber = new HashMap(); - //Mapping between fiber clfi and ipAddress + //Mapping between the ROADM-ROADM linkId/secElement and the linkId + private Map> mapLinkFiber = new HashMap>(); + //Mapping between the ROADM-ROADM linkId/secElement and ipAddress private Map mapFiberIp = new HashMap(); - private static int convertKmM = 1000; + //List of Xponders + private List trxList = new ArrayList<>(); + //Initialize the 32 bit identifiers for the edfa and the fiber. + //These 32-bit identifiers are not ipv4 addresses (despite having ipv4Adresses format, dotted-decimal notation). + //They are imposed by the GNPy yang model to identify network elements and not used for any routing purposes. + private Ipv4Address edfaId; + private Ipv4Address fiberId; + private static final double LATITUDE = 0; + private static final double LONGITUTE = 0; + private static final String REGION = "N/A"; + private static final String CITY = "N/A"; + private static final int CONVERT_KM_M = 1000; + private static final double TARGET_PCH_OUT_DB = -20; /* * Construct the ExtractTopoDataStoreImpl. */ - @SuppressWarnings("unchecked") - public GnpyTopoImpl(final NetworkTransactionService networkTransactionService) { + public GnpyTopoImpl(final NetworkTransactionService networkTransactionService) throws GnpyException { this.networkTransactionService = networkTransactionService; - Map> map = extractTopo(); - if (map.containsKey("Elements")) { - elements = (List) map.get("Elements"); - } else { - elements = null; - } - if (map.containsKey("Connections")) { - connections = (List) map.get("Connections"); - } else { - connections = null; + //32-bit identifier for the fiber. The dotted decimal notation has the format 243.x.x.x (0<=x<=255) + fiberId = new Ipv4Address("243.0.0.1"); + //32-bit identifier for the edfa. The dotted decimal notation has the format 244.x.x.x (0<=x<=255) + edfaId = new Ipv4Address("244.0.0.1"); + try { + extractTopo(); + } catch (NullPointerException e) { + throw new GnpyException("In GnpyTopoImpl: one of the elements is null",e); } } @@ -111,12 +123,7 @@ public class GnpyTopoImpl { * a mapping structure to map between the nodeId and the ipAddress (uid) * */ - public Map> extractTopo() { - Map> map = new HashMap>(); - // Define the elements - List topoElements = new ArrayList<>(); - // Define the connections - List topoConnections = new ArrayList<>(); + private void extractTopo() throws GnpyException { // Define the instance identifier of the OpenRoadm topology InstanceIdentifier insIdOpenRoadmTopo = InstanceIdentifier .builder(Networks.class) @@ -127,238 +134,221 @@ public class GnpyTopoImpl { .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))).build(); try { // Initialize the reading of the networkTransactionService - // read the configuration part of the data broker that concerns - // the openRoadm topology and get all the nodes + // read the configuration part of the data broker that concerns the openRoadm topology and get all the nodes java.util.Optional openRoadmTopo = this.networkTransactionService .read(LogicalDatastoreType.CONFIGURATION, insIdOpenRoadmTopo).get(); java.util.Optional openRoadmNet = this.networkTransactionService .read(LogicalDatastoreType.CONFIGURATION, insIdrOpenRoadmNet).get(); - if (openRoadmNet.isPresent()) { - List openRoadmNetNodeList = openRoadmNet.get().getNode(); - if (openRoadmTopo.isPresent()) { - List openRoadmTopoNodeList = openRoadmTopo.get().getNode(); - List nodesList = new ArrayList<>(); - // Create the list of nodes - if (!openRoadmTopoNodeList.isEmpty()) { - // Create elements - for (Node openRoadmTopoNode : openRoadmTopoNodeList) { - // Retrieve the supporting node and the type of the - // node in openRoadm network - List supportingNodeList = openRoadmTopoNode.getSupportingNode(); - for (SupportingNode supportingNode : supportingNodeList) { - String nodeRef = supportingNode.getNodeRef().getValue(); - IpAddress ipAddress = null; - // Retrieve the mapping between the openRoadm - // topology and openRoadm network - mapDisgNodeRefNode.put(openRoadmTopoNode.getNodeId().getValue(), nodeRef); - Node1 openRoadmNetNode1 = null; - org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130 - .Node1 commonNetworkNode1 = null; - for (Node openRoadmNetNode : openRoadmNetNodeList) { - if (openRoadmNetNode.getNodeId().getValue().equals(nodeRef)) { - openRoadmNetNode1 = openRoadmNetNode.augmentation(Node1.class); - commonNetworkNode1 = openRoadmNetNode.augmentation(org.opendaylight.yang.gen.v1 - .http.org.openroadm.common.network.rev181130.Node1.class); - ipAddress = openRoadmNetNode1.getIp(); - mapNodeRefIp.put(nodeRef, ipAddress); - break; - } - } - if (commonNetworkNode1.getNodeType().getName().equals("ROADM")) { - //if (((org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Node1) - // openRoadmNetNode1).getNodeType().getName().equals("ROADM")) { - if (!nodesList.contains(nodeRef)) { - Elements element = addElementsRoadm(2, 0, nodeRef, openRoadmNetNode1.getShelf(), - -20, ipAddress.getIpv4Address().getValue().toString()); - topoElements.add(element); - nodesList.add(nodeRef); - } - } else if (commonNetworkNode1.getNodeType().getName().equals("XPONDER")) { - //} else if (((org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130 - // .Node1) openRoadmNetNode1).getNodeType().getName().equals("XPONDER")) { - if (!nodesList.contains(nodeRef)) { - Elements element = addElementsTransceiver(2, 0, nodeRef, - openRoadmNetNode1.getShelf(), - ipAddress.getIpv4Address().getValue().toString()); - topoElements.add(element); - nodesList.add(nodeRef); - } - } else { - LOG.warn("the type is not implemented"); - } - } - } - } else { - LOG.warn("no nodes in the network"); - } + if (openRoadmNet.isPresent() && openRoadmTopo.isPresent()) { + extractElements(openRoadmTopo,openRoadmNet); + extractConnections(openRoadmTopo,openRoadmNet); + LOG.debug("In GnpyTopoImpl : elements and connections are well extracted"); + } + else { + throw new GnpyException( + "In GnpyTopoImpl : openroadm topology network or openroadm network are not well mounted ..."); + } + } catch (InterruptedException | ExecutionException e) { + this.networkTransactionService.close(); + throw new GnpyException("In gnpyTopoImpl: error in reading the topology", e); + } + this.networkTransactionService.close(); + } + + private void extractElements(java.util.Optional openRoadmTopo, + java.util.Optional openRoadmNet) throws GnpyException { + // Create the list of nodes + List openRoadmNetNodeList = openRoadmNet.get().getNode(); + List openRoadmTopoNodeList = openRoadmTopo.get().getNode(); + List nodesList = new ArrayList<>(); - // Create the list of connections - Network1 nw1 = openRoadmTopo.get().augmentation(Network1.class); - List linksList = nw1.getLink(); - // 1:EXPRESS-LINK 2:ADD-LINK 3:DROP-LINK - // 4:ROADM-To-ROADM 5:XPONDER-INPUT 6:XPONDER-OUTPUT - int[] externalLink = {4,5,6}; - int idFiber = 0; - int nbEDFA = 0; - if (!linksList.isEmpty()) { - LOG.debug("The link list is not empty"); - for (Link link : linksList) { - Link1 link1 = link.augmentation(Link1.class); - org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130 - .Link1 openroadmNetworkLink1 = link.augmentation(org.opendaylight.yang.gen.v1.http.org - .openroadm.network.topology.rev181130.Link1.class); - int linkType = link1.getLinkType().getIntValue(); - // the previous line generates a warning - // but the following cast in comment makes the gnpy tox test fail - // ((org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1) link1) - if (IntStream.of(externalLink).anyMatch(x -> x == linkType)) { - // Verify if the node is a ROADM - String srcId = mapDisgNodeRefNode.get(link.getSource().getSourceNode().getValue()); - IpAddress srcIp = mapNodeRefIp.get(srcId); - String clfi = link1.getClfi(); - String destId = null; - IpAddress destIp = null; - // Add the links between amplifiers - OMSAttributes omsAttributes = null; - if (linkType == 4) { - omsAttributes = openroadmNetworkLink1.getOMSAttributes(); - } - if (omsAttributes != null) { - if (omsAttributes.getAmplifiedLink() != null) { - List amplifiedLinkList = omsAttributes.getAmplifiedLink() - .getAmplifiedLink(); - if (!amplifiedLinkList.isEmpty()) { - for (AmplifiedLink amplifiedLink : amplifiedLinkList) { - Elements element1 = null; - if (amplifiedLink.getSectionElement() - .getSectionElement() instanceof Ila) { - Ila ila = (Ila) amplifiedLink.getSectionElement() - .getSectionElement(); - String nodeId = ila.getNodeId().getValue(); - IpAddress ipEdfa = new IpAddress( - new Ipv4Address("1.1.1." + nbEDFA)); - nbEDFA++; - mapDisgNodeRefNode.put(nodeId, nodeId); - mapNodeRefIp.put(nodeId, ipEdfa); - element1 = addElementsEdfa(2, 0, "RLD", "Lannion_CAS", - ila.getGain().getValue(), ila.getTilt().getValue(), - ila.getOutVoaAtt().getValue(), "std_medium_gain", - ipEdfa.getIpv4Address().getValue().toString()); - } else if (amplifiedLink.getSectionElement() - .getSectionElement() instanceof Span) { - // Create the location - IpAddress ipFiber = new IpAddress( - new Ipv4Address("2.2.2." + idFiber)); - mapLinkFiber.put(link.getLinkId().getValue(), clfi); - mapFiberIp.put(clfi, ipFiber); - idFiber++; - element1 = addElementsFiber(2, 0, "RLD", "Lannion_CAS", - ipFiber.getIpv4Address().getValue(), 20, 0, 0.2, 0, 0, - "SSMF"); - } - if (element1 != null) { - topoElements.add(element1); - destId = element1.getUid(); - destIp = null; - // Create a new link - if (srcId != destId) { - Connections connection = createNewConnection(srcId, srcIp, - destId, destIp); - topoConnections.add(connection); - srcId = destId; - srcIp = destIp; - } - } - } - } - } else if (omsAttributes.getSpan() != null) { - IpAddress ipFiber = new IpAddress(new Ipv4Address("2.2.2." + idFiber)); - mapLinkFiber.put(link.getLinkId().getValue(), clfi); - mapFiberIp.put(clfi, ipFiber); - idFiber++; - double attIn = 0; - double connIn = 0; - double connOut = 0; - String typeVariety = "SSMF"; - double length = 0; - // Compute the length of the link - org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130 - .networks.network.link.oms.attributes.@Nullable Span span = - omsAttributes.getSpan(); - List linkConcatenationList = span.getLinkConcatenation(); - for (LinkConcatenation linkConcatenation : linkConcatenationList) { - double srlgLength = linkConcatenation.getSRLGLength(); - //convert to kilometer - length += srlgLength / convertKmM; - } - double lossCoef = span.getSpanlossCurrent().getValue().doubleValue() / length; - Elements element1 = addElementsFiber(2, 0, "RLD", "Lannion_CAS", - ipFiber.getIpv4Address().getValue(), length, attIn, lossCoef, connIn, - connOut, typeVariety); - topoElements.add(element1); - // Create a new link - destId = element1.getUid(); - destIp = null; - if (srcId != destId) { - Connections connection = createNewConnection(srcId, srcIp, destId, destIp); - topoConnections.add(connection); - srcId = destId; - srcIp = destIp; - } - } else { - // Add a fiber - clfi = "Fiber" + idFiber; - IpAddress ipFiber = new IpAddress(new Ipv4Address("2.2.2." + idFiber)); - mapLinkFiber.put(link.getLinkId().getValue(), clfi); - mapFiberIp.put(clfi, ipFiber); - idFiber++; - // Create a new element - Elements element1 = addElementsFiber(2, 0, "RLD", "Lannion_CAS", - ipFiber.getIpv4Address().getValue(), 20, 0, 0.2, 0, 0, "SSMF"); - topoElements.add(element1); - // Create a new link - destId = element1.getUid(); - destIp = null; - if (srcId != destId) { - Connections connection = createNewConnection(srcId, srcIp, destId, destIp); - topoConnections.add(connection); - srcId = destId; - srcIp = destIp; - } - } - } else { - LOG.warn("The oms attributes is null {} !",link1.getLinkType().getName()); - } - // Create a new link - destId = mapDisgNodeRefNode.get(link.getDestination().getDestNode().getValue()); - destIp = mapNodeRefIp.get(destId); - Connections connection = createNewConnection(srcId, srcIp, destId, destIp); - topoConnections.add(connection); - } - } - } else { - LOG.warn("no links in the network"); + if (openRoadmTopoNodeList.isEmpty() || openRoadmNetNodeList.isEmpty()) { + throw new GnpyException("In gnpyTopoImpl: no nodes in the openradm topology or openroadm network"); + } + // Create elements + for (Node openRoadmTopoNode : openRoadmTopoNodeList) { + // Retrieve the supporting node and the type of the node in openRoadm network + List supportingNodeList = openRoadmTopoNode.getSupportingNode(); + for (SupportingNode supportingNode : supportingNodeList) { + IpAddress ipAddress = null; + String nodeRef = supportingNode.getNodeRef().getValue(); + // Retrieve the mapping between the openRoadm topology and openRoadm network + mapDisgNodeRefNode.put(openRoadmTopoNode.getNodeId().getValue(), nodeRef); + Node1 openRoadmNetNode1 = null; + org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130 + .Node1 commonNetworkNode1 = null; + for (Node openRoadmNetNode : openRoadmNetNodeList) { + if (openRoadmNetNode.getNodeId().getValue().equals(nodeRef)) { + openRoadmNetNode1 = openRoadmNetNode.augmentation(Node1.class); + commonNetworkNode1 = openRoadmNetNode.augmentation(org.opendaylight.yang.gen.v1 + .http.org.openroadm.common.network.rev181130.Node1.class); + ipAddress = openRoadmNetNode1.getIp(); + mapNodeRefIp.put(nodeRef, ipAddress); + break; + } + } + if (commonNetworkNode1.getNodeType().getName().equals("ROADM")) { + if (!nodesList.contains(nodeRef)) { + Elements element = createElementsRoadm(LATITUDE, LONGITUTE, nodeRef, + openRoadmNetNode1.getShelf(),TARGET_PCH_OUT_DB, ipAddress.getIpv4Address().getValue() + .toString()); + this.elements.add(element); + nodesList.add(nodeRef); + } + } else if (commonNetworkNode1.getNodeType().getName().equals("XPONDER")) { + if (!nodesList.contains(nodeRef)) { + Elements element = createElementsTransceiver(LATITUDE, LONGITUTE, nodeRef, + openRoadmNetNode1.getShelf(),ipAddress.getIpv4Address().getValue().toString()); + this.elements.add(element); + nodesList.add(nodeRef); + trxList.add(nodeRef); } } else { - LOG.warn("No nodes in the selected network ..."); + throw new GnpyException("In gnpyTopoImpl: the type is not implemented"); } } - } catch (InterruptedException | ExecutionException e) { - LOG.error("Error reading the topology", e); - this.networkTransactionService.close(); } - this.networkTransactionService.close(); - map.put("Elements", topoElements); - map.put("Connections", topoConnections); - return map; + } + + private void extractConnections(java.util.Optional openRoadmTopo, + java.util.Optional openRoadmNet) throws GnpyException { + // Create the list of connections + Network1 nw1 = openRoadmTopo.get().augmentation(Network1.class); + List linksList = nw1.getLink(); + // 1:EXPRESS-LINK 2:ADD-LINK 3:DROP-LINK + // 4:ROADM-To-ROADM 5:XPONDER-INPUT 6:XPONDER-OUTPUT + int[] externalLink = {OpenroadmLinkType.ROADMTOROADM.getIntValue(),OpenroadmLinkType.XPONDERINPUT.getIntValue(), + OpenroadmLinkType.XPONDEROUTPUT.getIntValue()}; + + if (linksList.isEmpty()) { + throw new GnpyException("In gnpyTopoImpl: no links in the network"); + } + + for (Link link : linksList) { + Link1 link1 = link.augmentation(Link1.class); + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130 + .Link1 openroadmNetworkLink1 = link.augmentation(org.opendaylight.yang.gen.v1.http.org + .openroadm.network.topology.rev181130.Link1.class); + int linkType = link1.getLinkType().getIntValue(); + if (! IntStream.of(externalLink).anyMatch(x -> x == linkType)) { + continue; + } + + String srcId = mapDisgNodeRefNode.get(link.getSource().getSourceNode().getValue()); + IpAddress srcIp = mapNodeRefIp.get(srcId); + String linkId = link.getLinkId().getValue(); + String destId = null; + IpAddress destIp = null; + if (linkType == OpenroadmLinkType.ROADMTOROADM.getIntValue()) { + OMSAttributes omsAttributes = openroadmNetworkLink1.getOMSAttributes(); + if (omsAttributes == null) { + throw new GnpyException(String.format( + "In gnpyTopoImpl: OMS attributes do not exit for ROADM to ROADM link: %s",linkId)); + } + //Case of amplified link + if (omsAttributes.getAmplifiedLink() != null) { + srcIp = extractAmplifiedLink(omsAttributes, linkId, srcIp); + } + //Case of one span link + if (omsAttributes.getSpan() != null) { + srcIp = extractSpanLink(omsAttributes, linkId, srcIp); + } + } + // Create a new link + destId = mapDisgNodeRefNode.get(link.getDestination().getDestNode().getValue()); + destIp = mapNodeRefIp.get(destId); + createNewConnection(srcIp,destIp); + } + } + + private IpAddress extractAmplifiedLink(OMSAttributes omsAttributes, String linkId, IpAddress srcIp) + throws GnpyException { + + List amplifiedLinkList = omsAttributes.getAmplifiedLink() + .getAmplifiedLink(); + IpAddress destIp = null; + if (!amplifiedLinkList.isEmpty()) { + for (AmplifiedLink amplifiedLink : amplifiedLinkList) { + String secElt = amplifiedLink.getSectionEltNumber().toString(); + //Case of ILA + if (amplifiedLink.getSectionElement().getSectionElement() instanceof Ila) { + Ila ila = (Ila) amplifiedLink.getSectionElement().getSectionElement(); + destIp = extractILAFromAmpLink(ila); + } + //Case of Span + if (amplifiedLink.getSectionElement().getSectionElement() instanceof Span) { + Span span = (Span) amplifiedLink.getSectionElement().getSectionElement(); + destIp = extractSpan((SpanAttributes) span.getSpan(), linkId, secElt); + } + // Create a new link + if (createNewConnection(srcIp,destIp)) { + srcIp = destIp; + } + } + } + return srcIp; + } + + private IpAddress extractSpanLink(OMSAttributes omsAttributes, String linkId, IpAddress srcIp) + throws GnpyException { + + SpanAttributes span = omsAttributes.getSpan(); + IpAddress destIp = extractSpan((SpanAttributes) span, linkId, linkId); + if (createNewConnection(srcIp, destIp)) { + return destIp; + } + return srcIp; + } + + private IpAddress extractILAFromAmpLink(Ila ila) throws GnpyException { + String nodeId = ila.getNodeId().getValue(); + IpAddress ipEdfa = new IpAddress(edfaId); + edfaId = incrementIdentifier(edfaId); + mapDisgNodeRefNode.put(nodeId, nodeId); + mapNodeRefIp.put(nodeId, ipEdfa); + Elements element = createElementsEdfa(LATITUDE, LONGITUTE, REGION, CITY, + ila.getGain().getValue(), ila.getTilt().getValue(), + ila.getOutVoaAtt().getValue(), "std_medium_gain", + ipEdfa.getIpv4Address().getValue().toString()); + this.elements.add(element); + return ipEdfa; + } + + private IpAddress extractSpan(SpanAttributes span, String linkId, String subLinkId) throws GnpyException { + IpAddress ipFiber = new IpAddress(fiberId); + + if (!mapLinkFiber.containsKey(linkId)) { + mapLinkFiber.put(linkId, new ArrayList()); + } + mapLinkFiber.get(linkId).add(subLinkId); + mapFiberIp.put(subLinkId, ipFiber); + fiberId = incrementIdentifier(fiberId); + double attIn = 0; + double connIn = 0; + double connOut = 0; + String typeVariety = "SSMF"; + double length = 0; + // Compute the length of the link + List linkConcatenationList = span.getLinkConcatenation(); + for (LinkConcatenation linkConcatenation : linkConcatenationList) { + double srlgLength = linkConcatenation.getSRLGLength(); + //convert to kilometer + length += srlgLength / CONVERT_KM_M; + } + double lossCoef = span.getSpanlossCurrent().getValue().doubleValue() / length; + Elements element = createElementsFiber(LATITUDE, LONGITUTE, REGION, CITY, + ipFiber.getIpv4Address().getValue(), length, attIn, lossCoef, connIn, connOut, typeVariety); + this.elements.add(element); + return ipFiber; + } /* - * Method to add Fiber + * Method to create Fiber */ - private Elements addElementsFiber(double latitude, double longitude, String region, String city, String clfi, + private Elements createElementsFiber(double latitude, double longitude, String region, String city, String uidFiber, double length, double attIn, double lossCoef, double connIn, double connOut, String typeVariety) { - // Create an amplifier after the roadm + // Create an amplifier after the ROADM Coordinate c1 = new Coordinate(new BigDecimal(latitude)); Coordinate c2 = new Coordinate(new BigDecimal(longitude)); Location location1 = new LocationBuilder().setRegion(region).setCity(city).setLatitude(c1).setLongitude(c2) @@ -368,7 +358,7 @@ public class GnpyTopoImpl { .setAttIn(new BigDecimal(attIn)).setLossCoef(new BigDecimal(lossCoef)).setConIn(new BigDecimal(connIn)) .setConOut(new BigDecimal(connOut)).build(); Params params1 = new ParamsBuilder().setFiberroadm(fiber).build(); - Elements element1 = new ElementsBuilder().setUid(clfi) + Elements element1 = new ElementsBuilder().setUid(uidFiber) .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Fiber.class) .setTypeVariety(typeVariety).setMetadata(metadata1) .setElementType(new FiberRoadmBuilder().setParams(params1).build()).build(); @@ -376,11 +366,11 @@ public class GnpyTopoImpl { } /* - * Method to add Edfa + * Method to create EDFA */ - private Elements addElementsEdfa(double latitude, double longitude, String region, String city, + private Elements createElementsEdfa(double latitude, double longitude, String region, String city, BigDecimal gainTarget, BigDecimal tiltTarget, BigDecimal outVoa, String typeVariety, String uidEdfa) { - // Create an amplifier after the roadm + // Create an amplifier after the ROADM Coordinate c1 = new Coordinate(new BigDecimal(latitude)); Coordinate c2 = new Coordinate(new BigDecimal(longitude)); Location location1 = new LocationBuilder().setRegion(region).setCity(city).setLatitude(c1).setLongitude(c2) @@ -391,16 +381,15 @@ public class GnpyTopoImpl { Edfa edfa = new EdfaBuilder() .setOperational(operational).build(); Elements element1 = new ElementsBuilder().setUid(uidEdfa) - // Choose an ip address .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Edfa.class) .setMetadata(metadata1).setElementType(edfa).setTypeVariety(typeVariety).build(); return element1; } /* - * Method to add ROADM + * Method to create ROADM */ - private Elements addElementsRoadm(double latitude, double longitude, String region, String city, + private Elements createElementsRoadm(double latitude, double longitude, String region, String city, double targetPchOutDb, String uidRoadm) { Coordinate c1 = new Coordinate(new BigDecimal(latitude)); @@ -408,7 +397,6 @@ public class GnpyTopoImpl { Location location1 = new LocationBuilder().setRegion(region).setCity(city).setLatitude(c1).setLongitude(c2) .build(); Metadata metadata1 = new MetadataBuilder().setLocation(location1).build(); - // Create the roadm Roadm roadm = new RoadmBuilder().setTargetPchOutDb(new BigDecimal(targetPchOutDb)).build(); Params params1 = new ParamsBuilder().setFiberroadm(roadm).build(); Elements element1 = new ElementsBuilder().setUid(uidRoadm) @@ -418,9 +406,9 @@ public class GnpyTopoImpl { } /* - * Method to add Transceiver + * Method to create Transceiver */ - private Elements addElementsTransceiver(double latitude, double longitude, String region, String city, + private Elements createElementsTransceiver(double latitude, double longitude, String region, String city, String uidTrans) { Coordinate c1 = new Coordinate(new BigDecimal(latitude)); Coordinate c2 = new Coordinate(new BigDecimal(longitude)); @@ -434,17 +422,54 @@ public class GnpyTopoImpl { return element1; } - private Connections createNewConnection(String srcId, IpAddress srcIp, String destId, IpAddress destIp) { - String fromNode = srcId; - String toNode = destId; - if (srcIp != null) { - fromNode = srcIp.getIpv4Address().getValue().toString(); + /* + * Method to create Connection + */ + private boolean createNewConnection(IpAddress srcIp, IpAddress destIp) throws GnpyException { + if (srcIp == null || destIp == null) { + throw new GnpyException("create new connection : null node IpAddress"); + } + String fromNode = srcIp.getIpv4Address().getValue(); + String toNode = destIp.getIpv4Address().getValue(); + if (fromNode == toNode) { + return false; } - if (destIp != null) { - toNode = destIp.getIpv4Address().getValue().toString(); + Connections connection = new ConnectionsBuilder().setFromNode(fromNode).setToNode(toNode).build(); + this.connections.add(connection); + return true; + } + + /* + * Increment 32-bit identifier + */ + private Ipv4Address incrementIdentifier(Ipv4Address id) throws GnpyException { + String ips = id.getValue(); + String [] fields = ips.split(Pattern.quote(".")); + int intF1 = Integer.parseInt(fields[1]); + int intF2 = Integer.parseInt(fields[2]); + int intF3 = Integer.parseInt(fields[3]); + if (intF3 < 255) { + intF3++; + } else { + if (intF2 < 255) { + intF2++; + intF3 = 0; + } else { + if (intF1 < 255) { + intF1++; + intF2 = 0; + intF3 = 0; + } else { + throw new GnpyException("GnpyTopoImpl : the topology is not supported by gnpy"); + } + fields[1] = Integer.toString(intF1); + } + fields[2] = Integer.toString(intF2); } - Connections connection1 = new ConnectionsBuilder().setFromNode(fromNode).setToNode(toNode).build(); - return (connection1); + fields[3] = Integer.toString(intF3); + String nidString = fields[0] + "." + fields[1] + "." + fields[2] + "." + fields[3]; + Ipv4Address nid = new Ipv4Address(nidString); + return nid; } public List getElements() { @@ -479,11 +504,11 @@ public class GnpyTopoImpl { this.mapNodeRefIp = mapNodeRefIp; } - public Map getMapLinkFiber() { + public Map> getMapLinkFiber() { return mapLinkFiber; } - public void setMapLinkFiber(Map mapLinkFiber) { + public void setMapLinkFiber(Map> mapLinkFiber) { this.mapLinkFiber = mapLinkFiber; } @@ -494,4 +519,12 @@ public class GnpyTopoImpl { public void setMapFiberIp(Map mapFiberIp) { this.mapFiberIp = mapFiberIp; } + + public List getTrxList() { + return trxList; + } + + public void setTrxList(List trxList) { + this.trxList = trxList; + } } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java index a850db000..6ef4a1b66 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java @@ -46,8 +46,11 @@ public class GnpyUtilitiesImpl { private GnpyResult gnpyAtoZ; private GnpyResult gnpyZtoA; private Long requestId; + //private boolean status; + + public GnpyUtilitiesImpl(NetworkTransactionService networkTransaction, PathComputationRequestInput input) + throws GnpyException { - public GnpyUtilitiesImpl(NetworkTransactionService networkTransaction, PathComputationRequestInput input) { this.networkTransaction = networkTransaction; this.gnpyTopo = new GnpyTopoImpl(networkTransaction); this.input = input; @@ -57,106 +60,82 @@ public class GnpyUtilitiesImpl { } public boolean verifyComputationByGnpy(AToZDirection atoz, ZToADirection ztoa, PceConstraints pceHardConstraints) - throws Exception { - boolean isPcePathFeasible = false; - List elementsList = gnpyTopo.getElements(); - List connectionsList = gnpyTopo.getConnections(); + throws GnpyException, Exception { - if (atoz == null || atoz.getAToZ() == null) { - LOG.error("In pceSendingPceRPC: empty atoz path"); - } else { - GnpyServiceImpl gnpySvc = new GnpyServiceImpl(input, atoz, requestId, gnpyTopo, pceHardConstraints); - requestId++; - List pathRequestList1 = gnpySvc.getPathRequest(); - List synchronizationList1 = gnpySvc.getSynchronization(); - // Send the computed path A-to-Z to GNPY tool - String gnpyResponse1 = getGnpyResponse(elementsList, connectionsList, pathRequestList1, - synchronizationList1); - // Analyze the response - if (gnpyResponse1 != null) { - GnpyResult result = new GnpyResult(gnpyResponse1, gnpyTopo); - result.analyzeResult(); - this.gnpyAtoZ = result; - isPcePathFeasible = this.gnpyAtoZ.getPathFeasibility(); - } else { - LOG.error("No response from the GNPy server"); - } + if (atoz == null || atoz.getAToZ() == null || ztoa == null || ztoa.getZToA() == null) { + throw new GnpyException("In GnpyUtilities: the path transmitted to Gnpy is null"); } - if (ztoa == null || ztoa.getZToA() == null) { - LOG.error("In pceSendingPceRPC: empty ztoa path"); - isPcePathFeasible = false; - } else { - GnpyServiceImpl gnpySvc = new GnpyServiceImpl(input, ztoa, requestId, gnpyTopo, pceHardConstraints); - requestId++; - List pathRequestList2 = gnpySvc.getPathRequest(); - List synchronizationList2 = gnpySvc.getSynchronization(); - // Send the computed path Z-to-A to GNPY tool - String gnpyResponse2 = getGnpyResponse(elementsList, connectionsList, pathRequestList2, - synchronizationList2); - // Analyze the response - if (gnpyResponse2 != null) { - GnpyResult result = new GnpyResult(gnpyResponse2, gnpyTopo); - result.analyzeResult(); - this.gnpyZtoA = result; - isPcePathFeasible &= this.gnpyZtoA.getPathFeasibility(); - } else { - LOG.error("No response from the GNPy server"); - } - } + GnpyServiceImpl gnpySvc1 = new GnpyServiceImpl(input, atoz, requestId, gnpyTopo, pceHardConstraints); + this.gnpyAtoZ = gnpyResponseOneDirection(gnpySvc1); + boolean isPcePathFeasible = false; + isPcePathFeasible = this.gnpyAtoZ.getPathFeasibility(); + GnpyServiceImpl gnpySvc2 = new GnpyServiceImpl(input, ztoa, requestId, gnpyTopo, pceHardConstraints); + this.gnpyZtoA = gnpyResponseOneDirection(gnpySvc2); + isPcePathFeasible &= this.gnpyZtoA.getPathFeasibility(); return isPcePathFeasible; } - public HardConstraints askNewPathFromGnpy(AToZDirection atoz, ZToADirection ztoa, - HardConstraints gnpyPathAsHC, PceConstraints pceHardConstraints) throws Exception { - boolean isPcePathFeasible = false; + public GnpyResult gnpyResponseOneDirection(GnpyServiceImpl gnpySvc) throws GnpyException, Exception { + requestId++; + List pathRequestList = gnpySvc.getPathRequest(); + List synchronizationList = gnpySvc.getSynchronization(); + // Send the computed path to GNPY tool List elementsList = gnpyTopo.getElements(); List connectionsList = gnpyTopo.getConnections(); - - // Ask a new path A-to-Z - if (atoz.getAToZWavelengthNumber() == null) { - LOG.info("The wavelength is null!"); + String gnpyResponse = getGnpyResponse(elementsList, connectionsList, pathRequestList, + synchronizationList); + // Analyze the response + if (gnpyResponse == null) { + throw new GnpyException("In GnpyUtilities: no respnse from GNPy server"); } + GnpyResult result = new GnpyResult(gnpyResponse, gnpyTopo); + result.analyzeResult(); + return result; + } + + public HardConstraints askNewPathFromGnpy(HardConstraints gnpyPathAsHC, PceConstraints pceHardConstraints) + throws GnpyException, Exception { - AToZDirection atoztmp = new AToZDirectionBuilder().setRate(atoz.getRate()) - .setAToZ(null).build(); + AToZDirection atoztmp = new AToZDirectionBuilder() + .setRate(input.getServiceAEnd().getServiceRate()) + .setAToZ(null) + .build(); GnpyServiceImpl gnpySvc = new GnpyServiceImpl(input, atoztmp, requestId, gnpyTopo, pceHardConstraints); - requestId++; - List pathRequestList1 = gnpySvc.getPathRequest(); - List synchronizationList1 = gnpySvc.getSynchronization(); + GnpyResult result = gnpyResponseOneDirection(gnpySvc); - // Send the computed path A-to-Z to GNPY tool - String gnpyResponse1 = getGnpyResponse(elementsList, connectionsList, pathRequestList1, synchronizationList1); - // Analyze the response - if (gnpyResponse1 != null) { - GnpyResult result = new GnpyResult(gnpyResponse1, gnpyTopo); - LOG.debug("GNPy result created"); - isPcePathFeasible = result.getPathFeasibility(); - this.gnpyAtoZ = result; - if (isPcePathFeasible) { - List pathRouteObjectList = result.analyzeResult(); - gnpyPathAsHC = result.computeHardConstraintsFromGnpyPath(pathRouteObjectList); - } - } else { - LOG.error("No response from the GNPy server"); + if (result == null) { + throw new GnpyException("In GnpyUtilities: no response from the GNPy server"); } + + if (!result.getPathFeasibility()) { + return null; + } + List pathRouteObjectList = result.analyzeResult(); + gnpyPathAsHC = result.computeHardConstraintsFromGnpyPath(pathRouteObjectList); + return gnpyPathAsHC; } public String getGnpyResponse(List elementsList, List connectionsList, - List pathRequestList, List synchronizationList) throws Exception { + List pathRequestList, List synchronizationList) throws GnpyException, Exception { GnpyApi gnpyApi = new GnpyApiBuilder() .setTopologyFile( new TopologyFileBuilder().setElements(elementsList).setConnections(connectionsList).build()) - .setServiceFile(new ServiceFileBuilder().setPathRequest(pathRequestList).build()).build(); + .setServiceFile( + new ServiceFileBuilder().setPathRequest(pathRequestList).build()) + .build(); InstanceIdentifier idGnpyApi = InstanceIdentifier.builder(GnpyApi.class).build(); String gnpyJson; ServiceDataStoreOperationsImpl sd = new ServiceDataStoreOperationsImpl(networkTransaction); gnpyJson = sd.createJsonStringFromDataObject(idGnpyApi, gnpyApi); LOG.debug("GNPy Id: {} / json created : {}", idGnpyApi, gnpyJson); ConnectToGnpyServer connect = new ConnectToGnpyServer(); - String gnpyJsonModified = gnpyJson.replace("gnpy-eqpt-config:", "") - .replace("gnpy-path-computation-simplified:", "").replace("gnpy-network-topology:", ""); + String gnpyJsonModified = gnpyJson + .replace("gnpy-eqpt-config:", "") + .replace("gnpy-path-computation-simplified:", "") + .replace("gnpy-network-topology:", ""); + String gnpyResponse = connect.gnpyCnx(gnpyJsonModified); return gnpyResponse; } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperations.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperations.java index 11489dc90..e71ee7cbc 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperations.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperations.java @@ -15,9 +15,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; public interface ServiceDataStoreOperations { - void createXMLFromDevice(DataStoreContext dataStoreContextUtil, OrgOpenroadmDevice device, String output); + void createXMLFromDevice(DataStoreContext dataStoreContextUtil, OrgOpenroadmDevice device, String output) + throws GnpyException; - String createJsonStringFromDataObject(InstanceIdentifier id, DataObject object) throws Exception; + String createJsonStringFromDataObject(InstanceIdentifier id, DataObject object) throws GnpyException, Exception; - void writeStringFile(String jsonString, String fileName); + void writeStringFile(String jsonString, String fileName) throws GnpyException; } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java index 6d4343627..5d813a83c 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java @@ -52,14 +52,17 @@ public class ServiceDataStoreOperationsImpl implements ServiceDataStoreOperation public ServiceDataStoreOperationsImpl(NetworkTransactionService networkTransactionService) { } - public void createXMLFromDevice(DataStoreContext dataStoreContextUtil, OrgOpenroadmDevice device, String output) { + public void createXMLFromDevice(DataStoreContext dataStoreContextUtil, OrgOpenroadmDevice device, String output) + throws GnpyException { + if (device != null) { Optional> transformIntoNormalizedNode = null; XMLDataObjectConverter cwDsU = XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil); transformIntoNormalizedNode = cwDsU.toNormalizedNodes(device, OrgOpenroadmDevice.class); if (!transformIntoNormalizedNode.isPresent()) { - throw new IllegalStateException( - String.format("Could not transform the input %s into normalized nodes", device)); + throw new GnpyException(String.format( + "In ServiceDataStoreOperationsImpl: Cannot transform the device %s into normalized nodes", + device.toString())); } Writer writerFromDataObject = cwDsU.writerFromDataObject(device, OrgOpenroadmDevice.class,cwDsU.dataContainer()); @@ -68,13 +71,15 @@ public class ServiceDataStoreOperationsImpl implements ServiceDataStoreOperation writer.write(writerFromDataObject.toString()); writer.close(); } catch (IOException e) { - LOG.error("Bufferwriter error "); + throw new GnpyException( + String.format("In ServiceDataStoreOperationsImpl : Bufferwriter error"),e); } LOG.debug("GNPy: device xml : {}", writerFromDataObject.toString()); } } - public String createJsonStringFromDataObject(final InstanceIdentifier id, DataObject object) throws Exception { + public String createJsonStringFromDataObject(final InstanceIdentifier id, DataObject object) + throws GnpyException, Exception { final SchemaPath scPath = SchemaPath .create(FluentIterable.from(id.getPathArguments()).transform(new Function() { @@ -112,24 +117,20 @@ public class ServiceDataStoreOperationsImpl implements ServiceDataStoreOperation codecRegistry.getSerializer(id.getTargetType()).serialize(object, bindingWriter); domWriter.close(); writer.close(); - } catch (IOException e) { - LOG.error("GNPy: writer error "); - } catch (YangSyntaxErrorException e) { - LOG.warn("GNPy: exception {} occured during json file creation", e.getMessage(), e); - } catch (ReactorException e) { - LOG.warn("GNPy: exception {} occured during json file creation", e.getMessage(), e); + } catch (IOException | YangSyntaxErrorException | ReactorException e) { + throw new GnpyException("In ServiceDataStoreOperationsImpl: exception during json file creation",e); } return writer.toString(); } // Write the json as a string in a file - public void writeStringFile(String jsonString, String fileName) { + public void writeStringFile(String jsonString, String fileName) throws GnpyException { try { FileWriter file = new FileWriter(fileName); file.write(jsonString); file.close(); } catch (IOException e) { - LOG.error("GNPy: writer error "); + throw new GnpyException("In ServiceDataStoreOperationsImpl : exception during file writing",e); } } }