Merge "Bump transportpce-models upstream dependency"
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / PceSendingPceRPCs.java
index 324b022608b51b717c0d5a5c9f6abccabf4bed87..08b46d744edc30a86cd5ff183a7b0ea1cb0421c2 100644 (file)
@@ -8,13 +8,28 @@
 
 package org.opendaylight.transportpce.pce;
 
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.transportpce.pce.PceResult.LocalCause;
-import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.PathComputationRequestInput;
-import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.service.path.rpc.result.PathDescriptionBuilder;
-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.routing.constraints.rev171017.RoutingConstraintsSp.PceMetric;
+import org.opendaylight.transportpce.common.ResponseCodes;
+import org.opendaylight.transportpce.common.mapping.PortMapping;
+import org.opendaylight.transportpce.common.network.NetworkTransactionService;
+import org.opendaylight.transportpce.pce.constraints.OperatorConstraints;
+import org.opendaylight.transportpce.pce.constraints.PceConstraints;
+import org.opendaylight.transportpce.pce.constraints.PceConstraintsCalc;
+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.gnpy.consumer.GnpyConsumer;
+import org.opendaylight.transportpce.pce.graph.PceGraph;
+import org.opendaylight.transportpce.pce.networkanalyzer.PceCalculation;
+import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PceConstraintMode;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.path.computation.reroute.request.input.Endpoints;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.service.path.rpc.result.PathDescriptionBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.HardConstraints;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.AToZDirection;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.ZToADirection;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -22,6 +37,7 @@ import org.slf4j.LoggerFactory;
  * Class for Sending
  * PCE requests :
  * - path-computation-request
+ * - path-computation-reroute
  * - cancel-resource-reserve.
  * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
  *
@@ -38,120 +54,212 @@ public class PceSendingPceRPCs {
      * <code>false</code> cancelresourcereserve .
      */
     private PathDescriptionBuilder pathDescription;
-
     private PathComputationRequestInput input;
-    private DataBroker dataBroker;
-
+    private NetworkTransactionService networkTransaction;
     private PceConstraints pceHardConstraints = new PceConstraints();
     private PceConstraints pceSoftConstraints = new PceConstraints();
+    private GnpyResult gnpyAtoZ;
+    private GnpyResult gnpyZtoA;
+    private Boolean success;
+    private String message;
+    private String responseCode;
+    private final GnpyConsumer gnpyConsumer;
+    private PortMapping portMapping;
+    // Define the termination points whose reservation status is not taken into account during the pruning process
+    private Endpoints endpoints;
 
-    public PceSendingPceRPCs() {
+    public PceSendingPceRPCs(GnpyConsumer gnpyConsumer) {
         setPathDescription(null);
-
         this.input = null;
-        this.dataBroker = null;
+        this.networkTransaction = null;
+        this.gnpyConsumer = gnpyConsumer;
     }
 
-    public PceSendingPceRPCs(PathComputationRequestInput input, DataBroker dataBroker) {
+    public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
+                             GnpyConsumer gnpyConsumer, PortMapping portMapping) {
+        this.gnpyConsumer = gnpyConsumer;
         setPathDescription(null);
-
         // TODO compliance check to check that input is not empty
         this.input = input;
-        this.dataBroker = dataBroker;
+        this.networkTransaction = networkTransaction;
+        this.portMapping = portMapping;
+        this.endpoints = null;
+    }
+
+    public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
+                             GnpyConsumer gnpyConsumer, PortMapping portMapping,
+                             Endpoints endpoints) {
+        this.gnpyConsumer = gnpyConsumer;
+        setPathDescription(null);
+        this.input = input;
+        this.networkTransaction = networkTransaction;
+        this.portMapping = portMapping;
+        this.endpoints = endpoints;
     }
 
     public void cancelResourceReserve() {
+        success = false;
         LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
         try {
-            Thread.sleep(10000); // sleep for 10s
+            // sleep for 10s
+            Thread.sleep(10000);
         } catch (InterruptedException e) {
-            LOG.error(e.toString());
+            LOG.error("in PCESendingPceRPC: ",e);
         }
+        success = true;
         LOG.info("cancelResourceReserve ...");
     }
 
-    public void pathComputation() {
-        LOG.info("PathComputation ...");
-
-        PceConstraintsCalc constraints = new PceConstraintsCalc(input, dataBroker);
-        pceHardConstraints = constraints.getPceHardConstraints();
-        pceSoftConstraints = constraints.getPceSoftConstraints();
-
+    private void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints,
+            PceConstraintMode mode) {
 
-        LOG.info("nwAnalizer ...");
-        PceCalculation nwAnalizer = new PceCalculation(input, dataBroker,
-                pceHardConstraints, pceSoftConstraints, rc);
-        nwAnalizer.calcPath();
+        PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc,
+                portMapping, endpoints);
+        nwAnalizer.retrievePceNetwork();
         rc = nwAnalizer.getReturnStructure();
+        String serviceType = nwAnalizer.getServiceType();
         if (!rc.getStatus()) {
-            LOG.error("In pathComputation nwAnalizer: result = {}", rc.toString());
+            LOG.error("In pathComputationWithConstraints, nwAnalizer: result = {}", rc);
             return;
         }
-
+        OperatorConstraints opConstraints = new OperatorConstraints(networkTransaction);
         LOG.info("PceGraph ...");
-        LOG.warn("PathComputation: aPceNode '{}' - zPceNode '{}'", nwAnalizer.getaPceNode(), nwAnalizer.getzPceNode());
-        PceGraph graph = new PceGraph(
-                nwAnalizer.getaPceNode(),
-                nwAnalizer.getzPceNode(),
-                nwAnalizer.getAllPceNodes(),
-                pceHardConstraints, pceSoftConstraints, rc);
+        PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(), nwAnalizer.getzendPceNode(),
+                nwAnalizer.getAllPceNodes(), nwAnalizer.getAllPceLinks(), hardConstraints,
+                rc, serviceType, networkTransaction, mode, opConstraints.getBitMapConstraint(input.getCustomerName()));
         graph.calcPath();
         rc = graph.getReturnStructure();
         if (!rc.getStatus()) {
-
-            LOG.warn("In pathComputation : Graph return without Path ");
-
+            LOG.warn("In pathComputationWithConstraints : Graph return without Path ");
             // TODO fix. This is quick workaround for algorithm problem
-            if ((rc.getLocalCause() == LocalCause.TOO_HIGH_LATENCY)
-                && (pceHardConstraints.getPceMetrics() == PceMetric.HopCount)
-                && (pceHardConstraints.getMaxLatency() != -1)) {
+            if ((rc.getLocalCause() == PceResult.LocalCause.TOO_HIGH_LATENCY)
+                && (hardConstraints.getPceMetrics() == PceMetric.HopCount)
+                && (hardConstraints.getMaxLatency() != -1)) {
+                hardConstraints.setPceMetrics(PceMetric.PropagationDelay);
+                graph = patchRerunGraph(graph);
+            }
 
-                pceHardConstraints.setPceMetrics(PceMetric.PropagationDelay);
+            if (rc.getLocalCause() == PceResult.LocalCause.HD_NODE_INCLUDE) {
+                graph.setKpathsToBring(graph.getKpathsToBring() * 10);
                 graph = patchRerunGraph(graph);
             }
 
             if (!rc.getStatus()) {
-                LOG.error("In pathComputation graph.calcPath: result = {}", rc.toString());
+                LOG.error("In pathComputationWithConstraints, graph.calcPath: result = {}", rc);
                 return;
             }
         }
-
         LOG.info("PcePathDescription ...");
-        PcePathDescription description = new PcePathDescription(
-                graph.getPathAtoZ(),
-                nwAnalizer.getAllPceLinks(), rc);
+        PcePathDescription description = new PcePathDescription(graph.getPathAtoZ(), nwAnalizer.getAllPceLinks(), rc);
         description.buildDescriptions();
         rc = description.getReturnStructure();
         if (!rc.getStatus()) {
-            LOG.error("In pathComputation description: result = {}", rc.toString());
+            LOG.error("In pathComputationWithConstraints, description: result = {}", rc);
+        }
+    }
+
+    public void pathComputation() throws Exception {
+
+        PceConstraintsCalc constraints = new PceConstraintsCalc(input, networkTransaction);
+        pceHardConstraints = constraints.getPceHardConstraints();
+        pceSoftConstraints = constraints.getPceSoftConstraints();
+        pathComputationWithConstraints(pceHardConstraints, pceSoftConstraints, PceConstraintMode.Loose);
+        this.success = rc.getStatus();
+        this.message = rc.getMessage();
+        this.responseCode = rc.getResponseCode();
+
+        AToZDirection atoz = null;
+        ZToADirection ztoa = null;
+        if (rc.getStatus()) {
+            atoz = rc.getAtoZDirection();
+            ztoa = rc.getZtoADirection();
+        }
+
+        //Connect to Gnpy to check path feasibility and recompute another path in case of path non-feasibility
+        try {
+            if (gnpyConsumer.isAvailable()) {
+                GnpyUtilitiesImpl gnpy = new GnpyUtilitiesImpl(networkTransaction, input,
+                        gnpyConsumer);
+                if (rc.getStatus() && gnpyToCheckFeasiblity(atoz,ztoa,gnpy)) {
+                    setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
+                    return;
+                }
+                callGnpyToComputeNewPath(gnpy);
+            } else {
+                setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
+            }
+        }
+        catch (GnpyException e) {
+            LOG.error("Exception raised by GNPy {}",e.getMessage());
+            setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
+        }
+    }
+
+    private boolean gnpyToCheckFeasiblity(AToZDirection atoz, ZToADirection ztoa, GnpyUtilitiesImpl gnpy)
+            throws GnpyException {
+
+        //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();
+            return true;
+        }
+        return false;
+    }
+
+    private void callGnpyToComputeNewPath(GnpyUtilitiesImpl gnpy) throws GnpyException {
+
+        //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(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("setPathDescription ...");
+        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())
+            .setPceRoutingMetric(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, PceConstraintMode.Strict);
         AToZDirection atoz = rc.getAtoZDirection();
         ZToADirection ztoa = rc.getZtoADirection();
-        if ((atoz == null) || (atoz.getAToZ() == null)) {
-            rc.setRC("400");
-            LOG.error("In pathComputation empty atoz path after description: result = {}", rc.toString());
-            return;
+        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));
+        } 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));
         }
-        if ((ztoa == null) || (ztoa.getZToA() == null)) {
-            rc.setRC("400");
-            LOG.error("In pathComputation empty ztoa path after description: result = {}", rc.toString());
-            return;
-        }
-        setPathDescription(new PathDescriptionBuilder()
-                .setAToZDirection(atoz)
-                .setZToADirection(ztoa));
-        LOG.info("In pathComputation Graph is Found");
     }
 
     private PceGraph patchRerunGraph(PceGraph graph) {
         LOG.info("In pathComputation patchRerunGraph : rerun Graph with metric = PROPAGATION-DELAY ");
-        graph.setConstrains(pceHardConstraints, pceSoftConstraints);
+        graph.setConstrains(pceHardConstraints);
         graph.calcPath();
         return graph;
-
     }
 
     public PathDescriptionBuilder getPathDescription() {
@@ -163,15 +271,22 @@ public class PceSendingPceRPCs {
     }
 
     public Boolean getSuccess() {
-        return rc.getStatus();
+        return this.success;
     }
 
     public String getMessage() {
-        return rc.getMessage();
+        return this.message;
     }
 
     public String getResponseCode() {
-        return rc.getResponseCode();
+        return this.responseCode;
     }
 
+    public GnpyResult getGnpyAtoZ() {
+        return gnpyAtoZ;
+    }
+
+    public GnpyResult getGnpyZtoA() {
+        return gnpyZtoA;
+    }
 }