Merge "Consolidation of the GNPy module"
[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.network.NetworkTransactionService;
13 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
14 import org.opendaylight.transportpce.pce.constraints.PceConstraintsCalc;
15 import org.opendaylight.transportpce.pce.gnpy.ConnectToGnpyServer;
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.graph.PceGraph;
20 import org.opendaylight.transportpce.pce.networkanalyzer.PceCalculation;
21 import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
22 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.PathComputationRequestInput;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.PathComputationRequestInputBuilder;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.service.path.rpc.result.PathDescriptionBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirection;
26 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirection;
27 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.RoutingConstraintsSp.PceMetric;
28 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.routing.constraints.sp.HardConstraints;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /*
33  * Class for Sending
34  * PCE requests :
35  * - path-computation-request
36  * - cancel-resource-reserve.
37  * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
38  *
39  */
40 public class PceSendingPceRPCs {
41
42     /* Logging. */
43     private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
44     /* define procedure success (or not ). */
45     private PceResult rc = new PceResult();
46
47     /*
48      * define type of request<br> <code>true</code> pathcomputation <br>
49      * <code>false</code> cancelresourcereserve .
50      */
51     private PathDescriptionBuilder pathDescription;
52     private PathComputationRequestInput input;
53     private NetworkTransactionService networkTransaction;
54     private PceConstraints pceHardConstraints = new PceConstraints();
55     private PceConstraints pceSoftConstraints = new PceConstraints();
56     private GnpyResult gnpyAtoZ;
57     private GnpyResult gnpyZtoA;
58     private Boolean success;
59     private String message;
60     private String responseCode;
61
62     public PceSendingPceRPCs() {
63         setPathDescription(null);
64         this.input = null;
65         this.networkTransaction = null;
66     }
67
68     public PceSendingPceRPCs(PathComputationRequestInput input,
69         NetworkTransactionService networkTransaction) {
70         setPathDescription(null);
71
72         // TODO compliance check to check that input is not empty
73         this.input = input;
74         this.networkTransaction = networkTransaction;
75     }
76
77     public void cancelResourceReserve() {
78         success = false;
79         LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
80         try {
81             // sleep for 10s
82             Thread.sleep(10000);
83         } catch (InterruptedException e) {
84             LOG.error(e.toString());
85         }
86         success = true;
87         LOG.info("cancelResourceReserve ...");
88     }
89
90     public void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints) {
91
92         PceCalculation nwAnalizer =
93             new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc);
94         nwAnalizer.calcPath();
95         rc = nwAnalizer.getReturnStructure();
96         if (!rc.getStatus()) {
97             LOG.error("In pathComputationWithConstraints, nwAnalizer: result = {}", rc.toString());
98             return;
99         }
100         LOG.info("PceGraph ...");
101         PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(),
102             nwAnalizer.getzendPceNode(), nwAnalizer.getAllPceNodes(),
103             hardConstraints, softConstraints, rc);
104         graph.calcPath();
105         rc = graph.getReturnStructure();
106         if (!rc.getStatus()) {
107             LOG.warn("In pathComputation : Graph return without Path ");
108             // TODO fix. This is quick workaround for algorithm problem
109             if ((rc.getLocalCause() == PceResult.LocalCause.TOO_HIGH_LATENCY)
110                 && (hardConstraints.getPceMetrics() == PceMetric.HopCount)
111                 && (hardConstraints.getMaxLatency() != -1)) {
112                 hardConstraints.setPceMetrics(PceMetric.PropagationDelay);
113                 graph = patchRerunGraph(graph);
114             }
115             if (!rc.getStatus()) {
116                 LOG.error("In pathComputationWithConstraints, graph.calcPath: result = {}", rc.toString());
117                 return;
118             }
119         }
120         LOG.info("PcePathDescription ...");
121         PcePathDescription description = new PcePathDescription(graph.getPathAtoZ(), nwAnalizer.getAllPceLinks(), rc);
122         description.buildDescriptions();
123         rc = description.getReturnStructure();
124         if (!rc.getStatus()) {
125             LOG.error("In pathComputationWithConstraints, description: result = {}", rc.toString());
126             return;
127         }
128     }
129
130     public void pathComputation() throws Exception {
131
132         PceConstraintsCalc constraints = new PceConstraintsCalc(input, networkTransaction);
133         pceHardConstraints = constraints.getPceHardConstraints();
134         pceSoftConstraints = constraints.getPceSoftConstraints();
135         pathComputationWithConstraints(pceHardConstraints, pceSoftConstraints);
136         this.success = rc.getStatus();
137         this.message = rc.getMessage();
138         this.responseCode = rc.getResponseCode();
139
140         AToZDirection atoz = null;
141         ZToADirection ztoa = null;
142         if (rc.getStatus()) {
143             atoz = rc.getAtoZDirection();
144             ztoa = rc.getZtoADirection();
145         }
146
147         try {
148             ConnectToGnpyServer connectToGnpy = new ConnectToGnpyServer();
149             if (connectToGnpy.isGnpyURLExist()) {
150                 GnpyUtilitiesImpl gnpy = new GnpyUtilitiesImpl(networkTransaction, input);
151                 if (rc.getStatus() && gnpyToCheckFeasiblity(atoz,ztoa,gnpy)) {
152                     setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
153                     return;
154                 }
155                 callGnpyToComputeNewPath(gnpy);
156             } else {
157                 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
158                 return;
159             }
160         }
161         catch (GnpyException e) {
162             LOG.error("Exception raised by GNPy {}",e.getMessage());
163             setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
164             return;
165         }
166         return;
167     }
168
169     private boolean gnpyToCheckFeasiblity(AToZDirection atoz, ZToADirection ztoa, GnpyUtilitiesImpl gnpy)
170             throws GnpyException, Exception {
171
172         //Call GNPy for path verification
173         if (gnpy.verifyComputationByGnpy(atoz, ztoa, pceHardConstraints)) {
174             LOG.info("In pceSendingPceRPC: the path is feasible according to Gnpy");
175             gnpyAtoZ = gnpy.getGnpyAtoZ();
176             gnpyZtoA = gnpy.getGnpyZtoA();
177             return true;
178         }
179         return false;
180     }
181
182     private void callGnpyToComputeNewPath(GnpyUtilitiesImpl gnpy) throws GnpyException, Exception {
183
184         //Call GNPy in the case of non feasibility
185         LOG.info("In pceSendingPceRPC: the path is not feasible according to Gnpy");
186         HardConstraints gnpyPathAsHC = null;
187         gnpyPathAsHC = gnpy.askNewPathFromGnpy(gnpyPathAsHC, pceHardConstraints);
188         if (gnpyPathAsHC == null) {
189             LOG.info("In pceSendingPceRPC: GNPy failed to find another path");
190             this.success = false;
191             this.message = "No path available by PCE and GNPy ";
192             this.responseCode = ResponseCodes.RESPONSE_FAILED;
193             gnpyAtoZ = gnpy.getGnpyAtoZ();
194             gnpyZtoA = gnpy.getGnpyZtoA();
195             return;
196         }
197
198         LOG.info("In pceSendingPceRPC: GNPy succeed to find another path");
199         // Compute the path
200         PathComputationRequestInput inputFromGnpy = new PathComputationRequestInputBuilder()
201             .setServiceName(input.getServiceName()).setHardConstraints(gnpyPathAsHC)
202             .setSoftConstraints(input.getSoftConstraints()).setPceMetric(PceMetric.HopCount)
203             .setServiceAEnd(input.getServiceAEnd()).setServiceZEnd(input.getServiceZEnd()).build();
204         PceConstraintsCalc constraintsGnpy = new PceConstraintsCalc(inputFromGnpy, networkTransaction);
205         PceConstraints gnpyHardConstraints = constraintsGnpy.getPceHardConstraints();
206         PceConstraints gnpySoftConstraints = constraintsGnpy.getPceSoftConstraints();
207         pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints);
208         AToZDirection atoz = rc.getAtoZDirection();
209         ZToADirection ztoa = rc.getZtoADirection();
210         if (gnpyToCheckFeasiblity(atoz, ztoa,gnpy)) {
211             LOG.info("In pceSendingPceRPC: the new path computed by GNPy is valid");
212             this.success = true;
213             this.message = "Path is calculated by GNPy";
214             this.responseCode = ResponseCodes.RESPONSE_OK;
215             setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
216         } else {
217             LOG.info("In pceSendingPceRPC: the new path computed by GNPy is not valid");
218             this.success = false;
219             this.message = "No path available";
220             this.responseCode = ResponseCodes.RESPONSE_FAILED;
221             setPathDescription(new PathDescriptionBuilder().setAToZDirection(null).setZToADirection(null));
222         }
223     }
224
225     private PceGraph patchRerunGraph(PceGraph graph) {
226         LOG.info("In pathComputation patchRerunGraph : rerun Graph with metric = PROPAGATION-DELAY ");
227         graph.setConstrains(pceHardConstraints, pceSoftConstraints);
228         graph.calcPath();
229         return graph;
230     }
231
232     public PathDescriptionBuilder getPathDescription() {
233         return pathDescription;
234     }
235
236     private void setPathDescription(PathDescriptionBuilder pathDescription) {
237         this.pathDescription = pathDescription;
238     }
239
240     public Boolean getSuccess() {
241         return this.success;
242     }
243
244     public String getMessage() {
245         return this.message;
246     }
247
248     public String getResponseCode() {
249         return this.responseCode;
250     }
251
252     public GnpyResult getGnpyAtoZ() {
253         return gnpyAtoZ;
254     }
255
256     public GnpyResult getGnpyZtoA() {
257         return gnpyZtoA;
258     }
259 }