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