2 * Copyright © 2017 AT&T, Inc. 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
8 package org.opendaylight.transportpce.pce.service;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import com.google.common.util.concurrent.ListeningExecutorService;
12 import com.google.common.util.concurrent.MoreExecutors;
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.concurrent.Callable;
17 import java.util.concurrent.Executors;
18 import java.util.stream.Collectors;
19 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
20 import org.opendaylight.transportpce.common.mapping.PortMapping;
21 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
22 import org.opendaylight.transportpce.pce.PceComplianceCheck;
23 import org.opendaylight.transportpce.pce.PceComplianceCheckResult;
24 import org.opendaylight.transportpce.pce.PceSendingPceRPCs;
25 import org.opendaylight.transportpce.pce.gnpy.GnpyResult;
26 import org.opendaylight.transportpce.pce.gnpy.consumer.GnpyConsumer;
27 import org.opendaylight.yang.gen.v1.gnpy.path.rev220615.result.Response;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.CancelResourceReserveInput;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.CancelResourceReserveOutput;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.CancelResourceReserveOutputBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.PathComputationRequestInput;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.PathComputationRequestOutput;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.PathComputationRequestOutputBuilder;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.ServicePathRpcResult;
35 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.ServicePathRpcResultBuilder;
36 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.gnpy.GnpyResponse;
37 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.gnpy.GnpyResponseBuilder;
38 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.gnpy.gnpy.response.response.type.NoPathCaseBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.gnpy.gnpy.response.response.type.PathCaseBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.path.performance.PathPropertiesBuilder;
41 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.path.performance.path.properties.PathMetric;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.path.performance.path.properties.PathMetricBuilder;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.service.path.rpc.result.PathDescription;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.service.path.rpc.result.PathDescriptionBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.configuration.response.common.ConfigurationResponseCommonBuilder;
46 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirection;
47 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ZToADirection;
48 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
49 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.ServicePathNotificationTypes;
50 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParametersBuilder;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
54 public class PathComputationServiceImpl implements PathComputationService {
56 private static final Logger LOG = LoggerFactory.getLogger(PathComputationServiceImpl.class);
57 private final NotificationPublishService notificationPublishService;
58 private NetworkTransactionService networkTransactionService;
59 private final ListeningExecutorService executor;
60 private ServicePathRpcResult notification = null;
61 private final GnpyConsumer gnpyConsumer;
62 private PortMapping portMapping;
64 public PathComputationServiceImpl(NetworkTransactionService networkTransactionService,
65 NotificationPublishService notificationPublishService,
66 GnpyConsumer gnpyConsumer, PortMapping portMapping) {
67 this.notificationPublishService = notificationPublishService;
68 this.networkTransactionService = networkTransactionService;
69 this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
70 this.gnpyConsumer = gnpyConsumer;
71 this.portMapping = portMapping;
83 value = "UPM_UNCALLED_PRIVATE_METHOD",
84 justification = "false positive, this method is used by public method cancelResourceReserve")
85 private void sendNotifications(
86 ServicePathNotificationTypes servicePathNotificationTypes,
88 RpcStatusEx rpcStatusEx,
90 PathDescription pathDescription) {
91 ServicePathRpcResultBuilder servicePathRpcResultBuilder =
92 new ServicePathRpcResultBuilder()
93 .setNotificationType(servicePathNotificationTypes)
94 .setServiceName(serviceName)
95 .setStatus(rpcStatusEx)
96 .setStatusMessage(message);
97 if (pathDescription != null) {
98 servicePathRpcResultBuilder.setPathDescription(pathDescription);
100 this.notification = servicePathRpcResultBuilder.build();
102 notificationPublishService.putNotification(this.notification);
103 } catch (InterruptedException e) {
104 LOG.info("notification offer rejected: ", e);
109 public ListenableFuture<CancelResourceReserveOutput> cancelResourceReserve(CancelResourceReserveInput input) {
110 LOG.info("cancelResourceReserve");
111 return executor.submit(new Callable<CancelResourceReserveOutput>() {
114 public CancelResourceReserveOutput call() throws Exception {
116 ServicePathNotificationTypes.CancelResourceReserve,
117 input.getServiceName(),
119 "Service compliant, submitting cancelResourceReserve Request ...",
121 PceSendingPceRPCs sendingPCE = new PceSendingPceRPCs(gnpyConsumer);
122 sendingPCE.cancelResourceReserve();
123 LOG.info("in PathComputationServiceImpl : {}",
124 Boolean.TRUE.equals(sendingPCE.getSuccess())
125 ? "ResourceReserve cancelled !"
126 : "Cancelling ResourceReserve failed !");
128 ServicePathNotificationTypes.CancelResourceReserve,
129 input.getServiceName(),
130 RpcStatusEx.Successful,
131 "cancel Resource Reserve successful!",
133 return new CancelResourceReserveOutputBuilder()
134 .setConfigurationResponseCommon(
135 new ConfigurationResponseCommonBuilder()
136 .setAckFinalIndicator("Yes")
137 .setRequestId(input.getServiceHandlerHeader().getRequestId())
138 .setResponseCode("200")
139 .setResponseMessage("")
147 public ListenableFuture<PathComputationRequestOutput> pathComputationRequest(PathComputationRequestInput input) {
148 LOG.info("pathComputationRequest");
149 return executor.submit(new Callable<PathComputationRequestOutput>() {
152 public PathComputationRequestOutput call() throws Exception {
153 PathComputationRequestOutputBuilder output = new PathComputationRequestOutputBuilder();
154 ConfigurationResponseCommonBuilder configurationResponseCommon =
155 new ConfigurationResponseCommonBuilder();
156 PceComplianceCheckResult check = PceComplianceCheck.check(input);
157 if (!check.hasPassed()) {
158 LOG.error("Path not calculated, service not compliant : {}", check.getMessage());
160 ServicePathNotificationTypes.PathComputationRequest,
161 input.getServiceName(),
163 "Path not calculated, service not compliant",
165 configurationResponseCommon
166 .setAckFinalIndicator("Yes")
167 .setRequestId(input.getServiceHandlerHeader().getRequestId())
168 .setResponseCode("Path not calculated")
169 .setResponseMessage(check.getMessage());
171 .setConfigurationResponseCommon(configurationResponseCommon.build())
172 .setResponseParameters(null)
176 ServicePathNotificationTypes.PathComputationRequest,
177 input.getServiceName(),
179 "Service compliant, submitting pathComputation Request ...",
181 PceSendingPceRPCs sendingPCE =
182 new PceSendingPceRPCs(input, networkTransactionService, gnpyConsumer, portMapping);
183 sendingPCE.pathComputation();
184 String message = sendingPCE.getMessage();
185 String responseCode = sendingPCE.getResponseCode();
186 LOG.info("PCE response: {} {}", message, responseCode);
188 //add the GNPy result
189 GnpyResult gnpyAtoZ = sendingPCE.getGnpyAtoZ();
190 GnpyResult gnpyZtoA = sendingPCE.getGnpyZtoA();
191 List<GnpyResponse> listResponse = new ArrayList<>();
192 if (gnpyAtoZ != null) {
193 GnpyResponse respAtoZ = generateGnpyResponse(gnpyAtoZ.getResponse(),"A-to-Z");
194 listResponse.add(respAtoZ);
196 if (gnpyZtoA != null) {
197 GnpyResponse respZtoA = generateGnpyResponse(gnpyZtoA.getResponse(),"Z-to-A");
198 listResponse.add(respZtoA);
202 listResponse.stream()
203 .collect(Collectors.toMap(GnpyResponse::key, gnpyResponse -> gnpyResponse)));
205 PathDescriptionBuilder path = sendingPCE.getPathDescription();
206 if (Boolean.FALSE.equals(sendingPCE.getSuccess()) || (path == null)) {
208 ServicePathNotificationTypes.PathComputationRequest,
209 input.getServiceName(),
211 "Path not calculated",
214 .setConfigurationResponseCommon(
215 configurationResponseCommon
216 .setAckFinalIndicator("Yes")
217 .setRequestId(input.getServiceHandlerHeader().getRequestId())
218 .setResponseCode(responseCode)
219 .setResponseMessage(message)
223 // Path calculator returned Success
224 PathDescription pathDescription =
225 new org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615
226 .service.path.rpc.result.PathDescriptionBuilder()
227 .setAToZDirection(path.getAToZDirection())
228 .setZToADirection(path.getZToADirection())
231 ServicePathNotificationTypes.PathComputationRequest,
232 input.getServiceName(),
233 RpcStatusEx.Successful,
236 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
237 .response.parameters.sp.response.parameters.PathDescription pathDescription1 =
238 new org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118
239 .response.parameters.sp.response.parameters.PathDescriptionBuilder()
240 .setAToZDirection(path.getAToZDirection())
241 .setZToADirection(path.getZToADirection())
244 .setConfigurationResponseCommon(
245 configurationResponseCommon
246 .setAckFinalIndicator("Yes")
247 .setRequestId(input.getServiceHandlerHeader().getRequestId())
248 .setResponseCode(responseCode)
249 .setResponseMessage(message)
251 .setResponseParameters(
252 new ResponseParametersBuilder().setPathDescription(pathDescription1).build());
254 AToZDirection atoz = pathDescription.getAToZDirection();
255 if ((atoz != null) && (atoz.getAToZ() != null)) {
256 LOG.debug("Impl AtoZ Notification: [{}] elements in description", atoz.getAToZ().size());
257 for (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705
258 .path.description.atoz.direction.AToZKey key : atoz.getAToZ().keySet()) {
259 LOG.debug("Impl AtoZ Notification: [{}] {}", key, atoz.getAToZ().get(key));
262 ZToADirection ztoa = pathDescription.getZToADirection();
263 if ((ztoa != null) && (ztoa.getZToA() != null)) {
264 LOG.debug("Impl ZtoA Notification: [{}] elements in description", ztoa.getZToA().size());
265 for (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705
266 .path.description.ztoa.direction.ZToAKey key : ztoa.getZToA().keySet()) {
267 LOG.debug("Impl ZtoA Notification: [{}] {}", key, ztoa.getZToA().get(key));
270 return output.build();
275 public GnpyResponse generateGnpyResponse(Response responseGnpy, String pathDir) {
276 if (responseGnpy == null) {
277 return new GnpyResponseBuilder()
279 .setResponseType(null)
280 .setFeasibility(true)
283 if (responseGnpy.getResponseType()
284 instanceof org.opendaylight.yang.gen.v1.gnpy.path.rev220615.result.response.response.type.NoPathCase) {
285 LOG.info("GNPy : path is not feasible");
286 org.opendaylight.yang.gen.v1.gnpy.path.rev220615.result.response.response.type.NoPathCase
288 (org.opendaylight.yang.gen.v1.gnpy.path.rev220615.result.response.response.type.NoPathCase)
289 responseGnpy.getResponseType();
290 return new GnpyResponseBuilder()
293 new NoPathCaseBuilder()
294 .setNoPath(noPathGnpy.getNoPath())
296 .setFeasibility(false)
299 if (responseGnpy.getResponseType()
300 instanceof org.opendaylight.yang.gen.v1.gnpy.path.rev220615.result.response.response.type.PathCase) {
301 LOG.info("GNPy : path is feasible");
302 org.opendaylight.yang.gen.v1.gnpy.path.rev220615.result.response.response.type.PathCase
304 (org.opendaylight.yang.gen.v1.gnpy.path.rev220615.result.response.response.type.PathCase)
305 responseGnpy.getResponseType();
306 List<org.opendaylight.yang.gen.v1.gnpy.path.rev220615.generic.path.properties.path.properties.PathMetric>
308 new ArrayList<>(pathCase.getPathProperties().getPathMetric().values());
309 List<PathMetric> gnpyPathMetricList = new ArrayList<>();
310 for (org.opendaylight.yang.gen.v1.gnpy.path.rev220615.generic.path.properties.path.properties.PathMetric
311 pathMetricGnpy : pathMetricList) {
312 gnpyPathMetricList.add(
313 new PathMetricBuilder()
314 .setMetricType(pathMetricGnpy.getMetricType())
315 .setAccumulativeValue(pathMetricGnpy.getAccumulativeValue())
318 return new GnpyResponseBuilder()
321 new PathCaseBuilder()
323 new PathPropertiesBuilder()
324 .setPathMetric(gnpyPathMetricList.stream()
325 .collect(Collectors.toMap(PathMetric::key, pathMetric -> pathMetric)))
328 .setFeasibility(true)
331 return new GnpyResponseBuilder()
333 .setResponseType(null)
334 .setFeasibility(true)