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