96161a249984770b75c5cb17851d4b8dd24e89da
[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 java.util.List;
12
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.ExtractTopoDataStoreImpl;
18 import org.opendaylight.transportpce.pce.gnpy.GnpyResult;
19 import org.opendaylight.transportpce.pce.gnpy.ServiceDataStoreOperationsImpl;
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.gnpy.gnpy.api.rev190103.GnpyApi;
24 import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApiBuilder;
25 import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.gnpy.api.ServiceFileBuilder;
26 import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.gnpy.api.TopologyFileBuilder;
27 import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Connections;
28 import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Elements;
29 import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.service.PathRequest;
30 import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.Synchronization;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.PathComputationRequestInput;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.service.path.rpc.result.PathDescriptionBuilder;
33 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirection;
34 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirection;
35 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.RoutingConstraintsSp.PceMetric;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /*
41  * Class for Sending
42  * PCE requests :
43  * - path-computation-request
44  * - cancel-resource-reserve.
45  * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
46  *
47  */
48 public class PceSendingPceRPCs {
49
50     /* Logging. */
51     private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
52     /* define procedure success (or not ). */
53     private PceResult rc = new PceResult();
54
55     /*
56      * define type of request<br> <code>true</code> pathcomputation <br>
57      * <code>false</code> cancelresourcereserve .
58      */
59     private PathDescriptionBuilder pathDescription;
60     private PathComputationRequestInput input;
61     private NetworkTransactionService networkTransaction;
62     private PceConstraints pceHardConstraints = new PceConstraints();
63     private PceConstraints pceSoftConstraints = new PceConstraints();
64     private Long gnpyRequestId = new Long(0);
65     private GnpyResult gnpyAtoZ;
66     private GnpyResult gnpyZtoA;
67
68     public PceSendingPceRPCs() {
69         setPathDescription(null);
70         this.input = null;
71         this.networkTransaction = null;
72         this.gnpyAtoZ = null;
73         this.gnpyZtoA = null;
74     }
75
76     public PceSendingPceRPCs(PathComputationRequestInput input,
77             NetworkTransactionService networkTransaction) {
78         setPathDescription(null);
79
80         // TODO compliance check to check that input is not empty
81         this.input = input;
82         this.networkTransaction = networkTransaction;
83     }
84
85     public void cancelResourceReserve() {
86         LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
87         try {
88             // sleep for 10s
89             Thread.sleep(10000);
90         } catch (InterruptedException e) {
91             LOG.error(e.toString());
92         }
93         LOG.info("cancelResourceReserve ...");
94     }
95
96     public void pathComputation() throws Exception {
97         LOG.info("PathComputation ...");
98
99         PceConstraintsCalc constraints = new PceConstraintsCalc(input,networkTransaction);
100         pceHardConstraints = constraints.getPceHardConstraints();
101         pceSoftConstraints = constraints.getPceSoftConstraints();
102         LOG.info("nwAnalizer ...");
103         PceCalculation nwAnalizer =
104             new PceCalculation(input,networkTransaction, pceHardConstraints, pceSoftConstraints, rc);
105         nwAnalizer.calcPath();
106         rc = nwAnalizer.getReturnStructure();
107         if (!rc.getStatus()) {
108             LOG.error("In pathComputation nwAnalizer: result = {}", rc.toString());
109             return;
110         }
111
112         LOG.info("PceGraph ...");
113         PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(),
114                 nwAnalizer.getzendPceNode(), nwAnalizer.getAllPceNodes(),
115                 pceHardConstraints, pceSoftConstraints, rc);
116         graph.calcPath();
117         rc = graph.getReturnStructure();
118         if (!rc.getStatus()) {
119             LOG.warn("In pathComputation : Graph return without Path ");
120             // TODO fix. This is quick workaround for algorithm problem
121             if ((rc.getLocalCause() == PceResult.LocalCause.TOO_HIGH_LATENCY)
122                     && (pceHardConstraints.getPceMetrics() == PceMetric.HopCount)
123                     && (pceHardConstraints.getMaxLatency() != -1)) {
124                 pceHardConstraints.setPceMetrics(PceMetric.PropagationDelay);
125                 graph = patchRerunGraph(graph);
126             }
127
128             if (!rc.getStatus()) {
129                 LOG.error("In pathComputation graph.calcPath: result = {}", rc.toString());
130                 return;
131             }
132         }
133
134         LOG.info("PcePathDescription ...");
135         PcePathDescription description = new PcePathDescription(graph.getPathAtoZ(), nwAnalizer.getAllPceLinks(), rc);
136         description.buildDescriptions();
137         rc = description.getReturnStructure();
138         if (!rc.getStatus()) {
139             LOG.error("In pathComputation description: result = {}", rc.toString());
140             return;
141         }
142
143         LOG.info("setPathDescription ...");
144         AToZDirection atoz = rc.getAtoZDirection();
145         ZToADirection ztoa = rc.getZtoADirection();
146         ConnectToGnpyServer connectToGnpy = new ConnectToGnpyServer();
147         if (atoz == null || atoz.getAToZ() == null) {
148             rc.setRC("400");
149             LOG.error("In pathComputation empty atoz path after description: result = {}", rc.toString());
150             return;
151         } else {
152             // Send the computed path A-to-Z to GNPY tool
153             if (connectToGnpy.isGnpyURLExist()) {
154                 ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(networkTransaction, input, atoz,
155                         gnpyRequestId);
156                 gnpyRequestId++;
157                 List<Elements> elementsList1 = xtrTopo.getElements();
158                 List<Connections> connectionsList1 = xtrTopo.getConnections();
159                 List<PathRequest> pathRequestList1 = xtrTopo.getPathRequest();
160                 List<Synchronization> synchronizationList1 = xtrTopo.getSynchronization();
161                 String gnpyResponse1 = getGnpyResponse(elementsList1, connectionsList1, pathRequestList1,
162                     synchronizationList1);
163                 // Analyze the response
164                 if (gnpyResponse1 != null) {
165                     GnpyResult result = new GnpyResult(gnpyResponse1);
166                     LOG.debug("GNPy result created");
167                     result.analyzeResult();
168                     this.gnpyAtoZ = result;
169                 } else {
170                     LOG.error("No response from the GNPy server");
171                 }
172             }
173         }
174
175         if (ztoa == null || ztoa.getZToA() == null) {
176             rc.setRC("400");
177             LOG.error("In pathComputation empty ztoa path after description: result = {}", rc.toString());
178             return;
179         } else {
180             // Send the computed path Z-to-A to GNPY tool
181             if (connectToGnpy.isGnpyURLExist()) {
182                 ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(networkTransaction, input, ztoa,
183                         gnpyRequestId);
184                 gnpyRequestId++;
185                 List<Elements> elementsList2 = xtrTopo.getElements();
186                 List<Connections> connectionsList2 = xtrTopo.getConnections();
187                 List<PathRequest> pathRequestList2 = xtrTopo.getPathRequest();
188                 List<Synchronization> synchronizationList2 = xtrTopo.getSynchronization();
189                 String gnpyResponse2 = getGnpyResponse(elementsList2, connectionsList2, pathRequestList2,
190                         synchronizationList2);
191                 // Analyze the response
192                 if (gnpyResponse2 != null) {
193                     GnpyResult result = new GnpyResult(gnpyResponse2);
194                     LOG.debug("GNPy result created");
195                     result.analyzeResult();
196                     this.gnpyZtoA = result;
197                 } else {
198                     LOG.info("No response from the GNPy server");
199                 }
200             }
201         }
202
203         setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
204         LOG.info("In pathComputation Graph is Found");
205     }
206
207     private String getGnpyResponse(List<Elements> elementsList, List<Connections> connectionsList,
208             List<PathRequest> pathRequestList, List<Synchronization> synchronizationList) throws Exception {
209         GnpyApi gnpyApi = new GnpyApiBuilder()
210                 .setTopologyFile(
211                         new TopologyFileBuilder().setElements(elementsList).setConnections(connectionsList).build())
212                 .setServiceFile(new ServiceFileBuilder().setPathRequest(pathRequestList).build()).build();
213         InstanceIdentifier<GnpyApi> idGnpyApi = InstanceIdentifier.builder(GnpyApi.class).build();
214         String gnpyJson;
215         ServiceDataStoreOperationsImpl sd = new ServiceDataStoreOperationsImpl(networkTransaction);
216         gnpyJson = sd.createJsonStringFromDataObject(idGnpyApi, gnpyApi);
217         LOG.debug("GNPy  Id: {} / json created : {}", idGnpyApi, gnpyJson);
218         ConnectToGnpyServer connect = new ConnectToGnpyServer();
219         String gnpyJsonModified = gnpyJson.replace("gnpy-eqpt-config:", "")
220                 .replace("gnpy-path-computation-simplified:", "").replace("gnpy-network-topology:", "");
221         String gnpyResponse = connect.gnpyCnx(gnpyJsonModified);
222         return gnpyResponse;
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 rc.getStatus();
242     }
243
244     public String getMessage() {
245         return rc.getMessage();
246     }
247
248     public String getResponseCode() {
249         return rc.getResponseCode();
250     }
251
252     public GnpyResult getGnpy_AtoZ() {
253         return gnpyAtoZ;
254     }
255
256     public GnpyResult getGnpy_ZtoA() {
257         return gnpyZtoA;
258     }
259 }