Remove softConstraints from PceGraph
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / PceSendingPceRPCs.java
1 /*
2  * Copyright © 2017 AT&T and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.transportpce.pce;
10
11 import org.opendaylight.transportpce.common.ResponseCodes;
12 import org.opendaylight.transportpce.common.mapping.PortMapping;
13 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
14 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
15 import org.opendaylight.transportpce.pce.constraints.PceConstraintsCalc;
16 import org.opendaylight.transportpce.pce.gnpy.GnpyException;
17 import org.opendaylight.transportpce.pce.gnpy.GnpyResult;
18 import org.opendaylight.transportpce.pce.gnpy.GnpyUtilitiesImpl;
19 import org.opendaylight.transportpce.pce.gnpy.consumer.GnpyConsumer;
20 import org.opendaylight.transportpce.pce.graph.PceGraph;
21 import org.opendaylight.transportpce.pce.networkanalyzer.PceCalculation;
22 import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInput;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInputBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PceConstraintMode;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.reroute.request.input.Endpoints;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.service.path.rpc.result.PathDescriptionBuilder;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.HardConstraints;
29 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.AToZDirection;
30 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.ZToADirection;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /*
36  * Class for Sending
37  * PCE requests :
38  * - path-computation-request
39  * - path-computation-reroute
40  * - cancel-resource-reserve.
41  * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
42  *
43  */
44 public class PceSendingPceRPCs {
45
46     /* Logging. */
47     private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
48     /* define procedure success (or not ). */
49     private PceResult rc = new PceResult();
50
51     /*
52      * define type of request<br> <code>true</code> pathcomputation <br>
53      * <code>false</code> cancelresourcereserve .
54      */
55     private PathDescriptionBuilder pathDescription;
56     private PathComputationRequestInput input;
57     private NetworkTransactionService networkTransaction;
58     private PceConstraints pceHardConstraints = new PceConstraints();
59     private PceConstraints pceSoftConstraints = new PceConstraints();
60     private GnpyResult gnpyAtoZ;
61     private GnpyResult gnpyZtoA;
62     private Boolean success;
63     private String message;
64     private String responseCode;
65     private final GnpyConsumer gnpyConsumer;
66     private PortMapping portMapping;
67     // Define the termination points whose reservation status is not taken into account during the pruning process
68     private Endpoints endpoints;
69
70     public PceSendingPceRPCs(GnpyConsumer gnpyConsumer) {
71         setPathDescription(null);
72         this.input = null;
73         this.networkTransaction = null;
74         this.gnpyConsumer = gnpyConsumer;
75     }
76
77     public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
78                              GnpyConsumer gnpyConsumer, PortMapping portMapping) {
79         this.gnpyConsumer = gnpyConsumer;
80         setPathDescription(null);
81         // TODO compliance check to check that input is not empty
82         this.input = input;
83         this.networkTransaction = networkTransaction;
84         this.portMapping = portMapping;
85         this.endpoints = null;
86     }
87
88     public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
89                              GnpyConsumer gnpyConsumer, PortMapping portMapping,
90                              Endpoints endpoints) {
91         this.gnpyConsumer = gnpyConsumer;
92         setPathDescription(null);
93         this.input = input;
94         this.networkTransaction = networkTransaction;
95         this.portMapping = portMapping;
96         this.endpoints = endpoints;
97     }
98
99     public void cancelResourceReserve() {
100         success = false;
101         LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
102         try {
103             // sleep for 10s
104             Thread.sleep(10000);
105         } catch (InterruptedException e) {
106             LOG.error("in PCESendingPceRPC: ",e);
107         }
108         success = true;
109         LOG.info("cancelResourceReserve ...");
110     }
111
112     private void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints,
113             PceConstraintMode mode) {
114
115         PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc,
116                 portMapping, endpoints);
117         nwAnalizer.retrievePceNetwork();
118         rc = nwAnalizer.getReturnStructure();
119         String serviceType = nwAnalizer.getServiceType();
120         if (!rc.getStatus()) {
121             LOG.error("In pathComputationWithConstraints, nwAnalizer: result = {}", rc);
122             return;
123         }
124         LOG.info("PceGraph ...");
125         PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(), nwAnalizer.getzendPceNode(),
126                 nwAnalizer.getAllPceNodes(), nwAnalizer.getAllPceLinks(), hardConstraints,
127                 rc, serviceType, networkTransaction, mode);
128         graph.calcPath();
129         rc = graph.getReturnStructure();
130         if (!rc.getStatus()) {
131             LOG.warn("In pathComputationWithConstraints : Graph return without Path ");
132             // TODO fix. This is quick workaround for algorithm problem
133             if ((rc.getLocalCause() == PceResult.LocalCause.TOO_HIGH_LATENCY)
134                 && (hardConstraints.getPceMetrics() == PceMetric.HopCount)
135                 && (hardConstraints.getMaxLatency() != -1)) {
136                 hardConstraints.setPceMetrics(PceMetric.PropagationDelay);
137                 graph = patchRerunGraph(graph);
138             }
139
140             if (rc.getLocalCause() == PceResult.LocalCause.HD_NODE_INCLUDE) {
141                 graph.setKpathsToBring(graph.getKpathsToBring() * 10);
142                 graph = patchRerunGraph(graph);
143             }
144
145             if (!rc.getStatus()) {
146                 LOG.error("In pathComputationWithConstraints, graph.calcPath: result = {}", rc);
147                 return;
148             }
149         }
150         LOG.info("PcePathDescription ...");
151         PcePathDescription description = new PcePathDescription(graph.getPathAtoZ(), nwAnalizer.getAllPceLinks(), rc);
152         description.buildDescriptions();
153         rc = description.getReturnStructure();
154         if (!rc.getStatus()) {
155             LOG.error("In pathComputationWithConstraints, description: result = {}", rc);
156         }
157     }
158
159     public void pathComputation() throws Exception {
160
161         PceConstraintsCalc constraints = new PceConstraintsCalc(input, networkTransaction);
162         pceHardConstraints = constraints.getPceHardConstraints();
163         pceSoftConstraints = constraints.getPceSoftConstraints();
164         pathComputationWithConstraints(pceHardConstraints, pceSoftConstraints, PceConstraintMode.Loose);
165         this.success = rc.getStatus();
166         this.message = rc.getMessage();
167         this.responseCode = rc.getResponseCode();
168
169         AToZDirection atoz = null;
170         ZToADirection ztoa = null;
171         if (rc.getStatus()) {
172             atoz = rc.getAtoZDirection();
173             ztoa = rc.getZtoADirection();
174         }
175
176         //Connect to Gnpy to check path feasibility and recompute another path in case of path non-feasibility
177         try {
178             if (gnpyConsumer.isAvailable()) {
179                 GnpyUtilitiesImpl gnpy = new GnpyUtilitiesImpl(networkTransaction, input,
180                         gnpyConsumer);
181                 if (rc.getStatus() && gnpyToCheckFeasiblity(atoz,ztoa,gnpy)) {
182                     setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
183                     return;
184                 }
185                 callGnpyToComputeNewPath(gnpy);
186             } else {
187                 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
188             }
189         }
190         catch (GnpyException e) {
191             LOG.error("Exception raised by GNPy {}",e.getMessage());
192             setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
193         }
194     }
195
196     private boolean gnpyToCheckFeasiblity(AToZDirection atoz, ZToADirection ztoa, GnpyUtilitiesImpl gnpy)
197             throws GnpyException {
198
199         //Call GNPy for path verification
200         if (gnpy.verifyComputationByGnpy(atoz, ztoa, pceHardConstraints)) {
201             LOG.info("In pceSendingPceRPC: the path is feasible according to Gnpy");
202             gnpyAtoZ = gnpy.getGnpyAtoZ();
203             gnpyZtoA = gnpy.getGnpyZtoA();
204             return true;
205         }
206         return false;
207     }
208
209     private void callGnpyToComputeNewPath(GnpyUtilitiesImpl gnpy) throws GnpyException {
210
211         //Call GNPy in the case of non feasibility
212         LOG.info("In pceSendingPceRPC: the path is not feasible according to Gnpy");
213         HardConstraints gnpyPathAsHC = null;
214         gnpyPathAsHC = gnpy.askNewPathFromGnpy(pceHardConstraints);
215         if (gnpyPathAsHC == null) {
216             LOG.info("In pceSendingPceRPC: GNPy failed to find another path");
217             this.success = false;
218             this.message = "No path available by PCE and GNPy ";
219             this.responseCode = ResponseCodes.RESPONSE_FAILED;
220             gnpyAtoZ = gnpy.getGnpyAtoZ();
221             gnpyZtoA = gnpy.getGnpyZtoA();
222             return;
223         }
224
225         LOG.info("In pceSendingPceRPC: GNPy succeed to find another path");
226         // Compute the path
227         PathComputationRequestInput inputFromGnpy = new PathComputationRequestInputBuilder()
228             .setServiceName(input.getServiceName())
229             .setHardConstraints(gnpyPathAsHC)
230             .setSoftConstraints(input.getSoftConstraints())
231             .setPceRoutingMetric(PceMetric.HopCount)
232             .setServiceAEnd(input.getServiceAEnd())
233             .setServiceZEnd(input.getServiceZEnd())
234             .build();
235         PceConstraintsCalc constraintsGnpy = new PceConstraintsCalc(inputFromGnpy, networkTransaction);
236         PceConstraints gnpyHardConstraints = constraintsGnpy.getPceHardConstraints();
237         PceConstraints gnpySoftConstraints = constraintsGnpy.getPceSoftConstraints();
238         pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints, PceConstraintMode.Strict);
239         AToZDirection atoz = rc.getAtoZDirection();
240         ZToADirection ztoa = rc.getZtoADirection();
241         if (gnpyToCheckFeasiblity(atoz, ztoa,gnpy)) {
242             LOG.info("In pceSendingPceRPC: the new path computed by GNPy is valid");
243             this.success = true;
244             this.message = "Path is calculated by GNPy";
245             this.responseCode = ResponseCodes.RESPONSE_OK;
246             setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
247         } else {
248             LOG.info("In pceSendingPceRPC: the new path computed by GNPy is not valid");
249             this.success = false;
250             this.message = "No path available";
251             this.responseCode = ResponseCodes.RESPONSE_FAILED;
252             setPathDescription(new PathDescriptionBuilder().setAToZDirection(null).setZToADirection(null));
253         }
254     }
255
256     private PceGraph patchRerunGraph(PceGraph graph) {
257         LOG.info("In pathComputation patchRerunGraph : rerun Graph with metric = PROPAGATION-DELAY ");
258         graph.setConstrains(pceHardConstraints);
259         graph.calcPath();
260         return graph;
261     }
262
263     public PathDescriptionBuilder getPathDescription() {
264         return pathDescription;
265     }
266
267     private void setPathDescription(PathDescriptionBuilder pathDescription) {
268         this.pathDescription = pathDescription;
269     }
270
271     public Boolean getSuccess() {
272         return this.success;
273     }
274
275     public String getMessage() {
276         return this.message;
277     }
278
279     public String getResponseCode() {
280         return this.responseCode;
281     }
282
283     public GnpyResult getGnpyAtoZ() {
284         return gnpyAtoZ;
285     }
286
287     public GnpyResult getGnpyZtoA() {
288         return gnpyZtoA;
289     }
290 }