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.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;
39 * - path-computation-request
40 * - cancel-resource-reserve.
41 * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
44 public class PceSendingPceRPCs {
47 private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
48 /* define procedure success (or not ). */
49 private PceResult rc = new PceResult();
52 * define type of request<br> <code>true</code> pathcomputation <br>
53 * <code>false</code> cancelresourcereserve .
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;
64 public PceSendingPceRPCs() {
65 setPathDescription(null);
67 this.dataBroker = null;
72 public PceSendingPceRPCs(PathComputationRequestInput input, DataBroker dataBroker) {
73 setPathDescription(null);
75 // TODO compliance check to check that input is not empty
77 this.dataBroker = dataBroker;
80 public void cancelResourceReserve() {
81 LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
85 } catch (InterruptedException e) {
86 LOG.error(e.toString());
88 LOG.info("cancelResourceReserve ...");
91 public void pathComputation() throws Exception {
92 // Comput the path according to the constraints of PCE
93 rc = pathComputationPCE();
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)) {
101 LOG.warn("In PCE pathComputation: empty atoz path after description: result = {}", rc.toString());
104 // Send the computed path A-to-Z to GNPY tool
105 if (connectToGnpy.isGnpyURLExist()) {
106 ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(dataBroker, input, atoz, 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;
121 LOG.error("No response from the GNPy server");
126 if ((ztoa == null) || (ztoa.getZToA() == null)) {
128 LOG.error("In pathComputation empty ztoa path after description: result = {}", rc.toString());
131 // Send the computed path Z-to-A to GNPY tool
132 if (connectToGnpy.isGnpyURLExist()) {
133 ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(dataBroker, input, ztoa, 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;
148 LOG.info("No response from the GNPy server");
152 // Set the description of the path
153 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
154 LOG.info("In pathComputation Graph is Found");
157 public PceResult pathComputationPCE() {
158 LOG.info("PathComputation ...");
160 PceConstraintsCalc constraints = new PceConstraintsCalc(input, dataBroker);
161 pceHardConstraints = constraints.getPceHardConstraints();
162 pceSoftConstraints = constraints.getPceSoftConstraints();
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());
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);
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);
188 if (!rc.getStatus()) {
189 LOG.error("In pathComputation graph.calcPath: result = {}", rc.toString());
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());
205 private String getGnpyResponse(List<Elements> elementsList, List<Connections> connectionsList,
206 List<PathRequest> pathRequestList, List<Synchronization> synchronizationList) throws Exception {
207 GnpyApi gnpyApi = new GnpyApiBuilder()
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();
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);
223 private PceGraph patchRerunGraph(PceGraph graph) {
224 LOG.info("In pathComputation patchRerunGraph : rerun Graph with metric = PROPAGATION-DELAY ");
225 graph.setConstrains(pceHardConstraints, pceSoftConstraints);
231 public PathDescriptionBuilder getPathDescription() {
232 return pathDescription;
235 private void setPathDescription(PathDescriptionBuilder pathDescription) {
236 this.pathDescription = pathDescription;
239 public Boolean getSuccess() {
240 return rc.getStatus();
243 public String getMessage() {
244 return rc.getMessage();
247 public String getResponseCode() {
248 return rc.getResponseCode();
251 public GnpyResult getGnpy_AtoZ() {
255 public GnpyResult getGnpy_ZtoA() {