2 * Copyright © 2017 AT&T and others. All rights reserved.
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
9 package org.opendaylight.transportpce.pce;
11 import java.util.List;
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;
43 * - path-computation-request
44 * - cancel-resource-reserve.
45 * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
48 public class PceSendingPceRPCs {
51 private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
52 /* define procedure success (or not ). */
53 private PceResult rc = new PceResult();
56 * define type of request<br> <code>true</code> pathcomputation <br>
57 * <code>false</code> cancelresourcereserve .
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;
68 public PceSendingPceRPCs() {
69 setPathDescription(null);
71 this.networkTransaction = null;
76 public PceSendingPceRPCs(PathComputationRequestInput input,
77 NetworkTransactionService networkTransaction) {
78 setPathDescription(null);
80 // TODO compliance check to check that input is not empty
82 this.networkTransaction = networkTransaction;
85 public void cancelResourceReserve() {
86 LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
90 } catch (InterruptedException e) {
91 LOG.error(e.toString());
93 LOG.info("cancelResourceReserve ...");
96 public void pathComputation() throws Exception {
97 LOG.info("PathComputation ...");
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());
112 LOG.info("PceGraph ...");
113 PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(),
114 nwAnalizer.getzendPceNode(), nwAnalizer.getAllPceNodes(),
115 pceHardConstraints, pceSoftConstraints, rc);
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);
128 if (!rc.getStatus()) {
129 LOG.error("In pathComputation graph.calcPath: result = {}", rc.toString());
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());
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) {
149 LOG.error("In pathComputation empty atoz path after description: result = {}", rc.toString());
152 // Send the computed path A-to-Z to GNPY tool
153 if (connectToGnpy.isGnpyURLExist()) {
154 ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(networkTransaction, input, atoz,
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;
170 LOG.error("No response from the GNPy server");
175 if (ztoa == null || ztoa.getZToA() == null) {
177 LOG.error("In pathComputation empty ztoa path after description: result = {}", rc.toString());
180 // Send the computed path Z-to-A to GNPY tool
181 if (connectToGnpy.isGnpyURLExist()) {
182 ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(networkTransaction, input, ztoa,
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;
198 LOG.info("No response from the GNPy server");
203 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
204 LOG.info("In pathComputation Graph is Found");
207 private String getGnpyResponse(List<Elements> elementsList, List<Connections> connectionsList,
208 List<PathRequest> pathRequestList, List<Synchronization> synchronizationList) throws Exception {
209 GnpyApi gnpyApi = new GnpyApiBuilder()
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();
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);
225 private PceGraph patchRerunGraph(PceGraph graph) {
226 LOG.info("In pathComputation patchRerunGraph : rerun Graph with metric = PROPAGATION-DELAY ");
227 graph.setConstrains(pceHardConstraints, pceSoftConstraints);
232 public PathDescriptionBuilder getPathDescription() {
233 return pathDescription;
236 private void setPathDescription(PathDescriptionBuilder pathDescription) {
237 this.pathDescription = pathDescription;
240 public Boolean getSuccess() {
241 return rc.getStatus();
244 public String getMessage() {
245 return rc.getMessage();
248 public String getResponseCode() {
249 return rc.getResponseCode();
252 public GnpyResult getGnpy_AtoZ() {
256 public GnpyResult getGnpy_ZtoA() {