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