2 * Copyright © 2017 Orange, 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.servicehandler.service;
10 import com.google.common.util.concurrent.FutureCallback;
11 import com.google.common.util.concurrent.Futures;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import com.google.common.util.concurrent.ListeningExecutorService;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.Executors;
17 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
18 import org.opendaylight.transportpce.common.ResponseCodes;
19 import org.opendaylight.transportpce.pce.service.PathComputationService;
20 import org.opendaylight.transportpce.servicehandler.ModelMappingUtils;
21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.CancelResourceReserveInput;
22 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.CancelResourceReserveInputBuilder;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.CancelResourceReserveOutput;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.CancelResourceReserveOutputBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInput;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInputBuilder;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestOutput;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestOutputBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRerouteRequestInput;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRerouteRequestInputBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRerouteRequestOutput;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRerouteRequestOutputBuilder;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.path.computation.reroute.request.input.Endpoints;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.path.computation.reroute.request.input.EndpointsBuilder;
35 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultSh;
36 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultShBuilder;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.ServiceEndpoint;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.ServiceNotificationTypes;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.configuration.response.common.ConfigurationResponseCommon;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.configuration.response.common.ConfigurationResponseCommonBuilder;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.sdnc.request.header.SdncRequestHeader;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.HardConstraints;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.SoftConstraints;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceCreateInput;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceFeasibilityCheckInput;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.TempServiceCreateInput;
47 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
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.response.parameters.sp.ResponseParameters;
50 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParametersBuilder;
51 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.handler.header.ServiceHandlerHeaderBuilder;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 public class PCEServiceWrapper {
57 private static final String NOTIFICATION_OFFER_REJECTED_MSG = "notification offer rejected : ";
59 private static final String PERFORMING_PCE_MSG = "performing PCE ...";
61 private static final Logger LOG = LoggerFactory.getLogger(PCEServiceWrapper.class);
63 private final PathComputationService pathComputationService;
64 private final NotificationPublishService notificationPublishService;
65 private ServiceRpcResultSh notification = null;
66 private final ListeningExecutorService executor;
68 public PCEServiceWrapper(PathComputationService pathComputationService,
69 NotificationPublishService notificationPublishService) {
70 this.pathComputationService = pathComputationService;
71 this.notificationPublishService = notificationPublishService;
72 executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
75 public PathComputationRequestOutput performPCE(ServiceCreateInput serviceCreateInput, boolean reserveResource) {
76 LOG.info(PERFORMING_PCE_MSG);
77 if (validateParams(serviceCreateInput.getServiceName(), serviceCreateInput.getSdncRequestHeader())) {
78 return performPCE(serviceCreateInput.getHardConstraints(), serviceCreateInput.getSoftConstraints(),
79 serviceCreateInput.getServiceName(), serviceCreateInput.getSdncRequestHeader(),
80 serviceCreateInput.getServiceAEnd(), serviceCreateInput.getServiceZEnd(),
81 ServiceNotificationTypes.ServiceCreateResult, reserveResource);
83 return returnPCEFailed();
87 public PathComputationRequestOutput performPCE(TempServiceCreateInput tempServiceCreateInput,
88 boolean reserveResource) {
89 LOG.info(PERFORMING_PCE_MSG);
90 if (validateParams(tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader())) {
91 return performPCE(tempServiceCreateInput.getHardConstraints(), tempServiceCreateInput.getSoftConstraints(),
92 tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader(),
93 tempServiceCreateInput.getServiceAEnd(), tempServiceCreateInput.getServiceZEnd(),
94 ServiceNotificationTypes.ServiceCreateResult, reserveResource);
96 return returnPCEFailed();
100 public PathComputationRequestOutput performPCE(ServiceFeasibilityCheckInput serviceFeasibilityCheckInput,
101 boolean reserveResource) {
102 LOG.info(PERFORMING_PCE_MSG);
103 if (validateParams(serviceFeasibilityCheckInput.getCommonId(),
104 serviceFeasibilityCheckInput.getSdncRequestHeader())) {
105 return performPCE(serviceFeasibilityCheckInput.getHardConstraints(),
106 serviceFeasibilityCheckInput.getSoftConstraints(), serviceFeasibilityCheckInput.getCommonId(),
107 serviceFeasibilityCheckInput.getSdncRequestHeader(), serviceFeasibilityCheckInput.getServiceAEnd(),
108 serviceFeasibilityCheckInput.getServiceZEnd(),
109 ServiceNotificationTypes.ServiceCreateResult, reserveResource);
111 return returnPCEFailed();
115 private PathComputationRequestOutput performPCE(HardConstraints hardConstraints, SoftConstraints softConstraints,
116 String serviceName, SdncRequestHeader sdncRequestHeader, ServiceEndpoint serviceAEnd,
117 ServiceEndpoint serviceZEnd, ServiceNotificationTypes notifType, boolean reserveResource) {
118 LOG.info("Calling path computation.");
119 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
120 .setStatus(RpcStatusEx.Pending)
121 .setStatusMessage("Service compliant, submitting PathComputation Request ...").build();
123 notificationPublishService.putNotification(notification);
124 } catch (InterruptedException e) {
125 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
127 FutureCallback<PathComputationRequestOutput> pceCallback =
128 new PathComputationRequestOutputCallback(notifType, serviceName);
129 PathComputationRequestInput pathComputationRequestInput = createPceRequestInput(serviceName, sdncRequestHeader,
130 hardConstraints, softConstraints, reserveResource, serviceAEnd, serviceZEnd);
131 ListenableFuture<PathComputationRequestOutput> pce = this.pathComputationService
132 .pathComputationRequest(pathComputationRequestInput);
133 Futures.addCallback(pce, pceCallback, executor);
135 ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
136 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
137 .setRequestId(sdncRequestHeader.getRequestId())
138 .setResponseCode(ResponseCodes.RESPONSE_OK)
139 .setResponseMessage("PCE calculation in progress")
141 ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
142 return new PathComputationRequestOutputBuilder()
143 .setConfigurationResponseCommon(configurationResponseCommon)
144 .setResponseParameters(reponseParameters)
148 public PathComputationRerouteRequestOutput performPCEReroute(HardConstraints hardConstraints,
149 SoftConstraints softConstraints, SdncRequestHeader serviceHandler, ServiceEndpoint serviceAEnd,
150 ServiceEndpoint serviceZEnd,
151 Endpoints endpoints) {
152 // TODO: Make it asynchronous
153 LOG.info("Calling path computation reroute");
154 PathComputationRerouteRequestInput inputPCE = createPceRerouteRequestInput(hardConstraints, softConstraints,
155 serviceHandler, serviceAEnd, serviceZEnd, endpoints);
156 ListenableFuture<PathComputationRerouteRequestOutput> res =
157 pathComputationService.pathComputationRerouteRequest(inputPCE);
160 } catch (ExecutionException | InterruptedException e) {
161 LOG.warn("PerformPCEReroute FAILED ! ", e);
162 return new PathComputationRerouteRequestOutputBuilder()
163 .setConfigurationResponseCommon(new ConfigurationResponseCommonBuilder()
164 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES)
165 .setRequestId("None")
166 .setResponseCode(ResponseCodes.RESPONSE_OK)
167 .setResponseMessage("PCE calculation FAILED")
173 private PathComputationRequestInput createPceRequestInput(String serviceName,
174 SdncRequestHeader serviceHandler, HardConstraints hardConstraints,
175 SoftConstraints softConstraints, Boolean reserveResource, ServiceEndpoint serviceAEnd,
176 ServiceEndpoint serviceZEnd) {
177 LOG.info("Mapping ServiceCreateInput or ServiceFeasibilityCheckInput or serviceReconfigureInput to PCE"
179 ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
180 if (serviceHandler != null) {
181 serviceHandlerHeader.setRequestId(serviceHandler.getRequestId());
183 return new PathComputationRequestInputBuilder()
184 .setServiceName(serviceName)
185 .setResourceReserve(reserveResource)
186 .setServiceHandlerHeader(serviceHandlerHeader.build())
187 .setHardConstraints(hardConstraints)
188 .setSoftConstraints(softConstraints)
189 .setPceRoutingMetric(PceMetric.TEMetric)
190 .setServiceAEnd(ModelMappingUtils.createServiceAEnd(serviceAEnd))
191 .setServiceZEnd(ModelMappingUtils.createServiceZEnd(serviceZEnd))
195 private PathComputationRerouteRequestInput createPceRerouteRequestInput(HardConstraints hardConstraints,
196 SoftConstraints softConstraints, SdncRequestHeader serviceHandler, ServiceEndpoint serviceAEnd,
197 ServiceEndpoint serviceZEnd, Endpoints endpoints) {
198 LOG.info("Mapping Service-reroute to PCE requests");
199 return new PathComputationRerouteRequestInputBuilder()
200 .setServiceHandlerHeader(serviceHandler == null
201 ? new ServiceHandlerHeaderBuilder().build()
202 : new ServiceHandlerHeaderBuilder().setRequestId(serviceHandler.getRequestId()).build())
203 .setHardConstraints(hardConstraints)
204 .setSoftConstraints(softConstraints)
205 .setPceRoutingMetric(PceMetric.TEMetric)
206 .setEndpoints(new EndpointsBuilder()
207 .setAEndTp(endpoints.getAEndTp())
208 .setZEndTp(endpoints.getZEndTp())
210 .setServiceAEnd(ModelMappingUtils.createServiceAEndReroute(serviceAEnd))
211 .setServiceZEnd(ModelMappingUtils.createServiceZEndReroute(serviceZEnd))
215 private CancelResourceReserveInput mappingCancelResourceReserve(String serviceName,
216 SdncRequestHeader sdncRequestHeader) {
217 LOG.info("Mapping to PCE Cancel resource request input");
218 CancelResourceReserveInputBuilder cancelResourceReserveInput = new CancelResourceReserveInputBuilder();
219 if (serviceName != null) {
220 ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
221 if (sdncRequestHeader != null) {
222 serviceHandlerHeader.setRequestId(sdncRequestHeader.getRequestId());
224 cancelResourceReserveInput.setServiceName(serviceName)
225 .setServiceHandlerHeader(serviceHandlerHeader.build());
226 return cancelResourceReserveInput.build();
228 LOG.error("Service Name (common-id for Temp service) is not set");
233 public CancelResourceReserveOutput cancelPCEResource(String serviceName, ServiceNotificationTypes notifType) {
234 LOG.info("Calling cancel resource reserve computation.");
235 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
236 .setStatus(RpcStatusEx.Pending)
237 .setStatusMessage("submitting Cancel resource reserve Request ...").build();
239 notificationPublishService.putNotification(notification);
240 } catch (InterruptedException e) {
241 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
243 FutureCallback<CancelResourceReserveOutput> pceCallback =
244 new CancelResourceReserveOutputFutureCallback(notifType, serviceName);
245 CancelResourceReserveInput cancelResourceReserveInput = mappingCancelResourceReserve(serviceName, null);
246 ConfigurationResponseCommonBuilder configurationResponseCommon = new ConfigurationResponseCommonBuilder();
247 if (cancelResourceReserveInput != null) {
248 String requestId = cancelResourceReserveInput.getServiceHandlerHeader().getRequestId();
249 ListenableFuture<CancelResourceReserveOutput> pce =
250 this.pathComputationService.cancelResourceReserve(cancelResourceReserveInput);
251 Futures.addCallback(pce, pceCallback, executor);
252 if (requestId != null) {
253 configurationResponseCommon.setRequestId(requestId);
255 configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
256 .setResponseCode(ResponseCodes.RESPONSE_OK).setResponseMessage("PCE calculation in progress");
257 return new CancelResourceReserveOutputBuilder()
258 .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
260 configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES)
261 .setResponseCode(ResponseCodes.RESPONSE_FAILED).setResponseMessage("PCE failed !");
262 return new CancelResourceReserveOutputBuilder()
263 .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
267 private static PathComputationRequestOutput returnPCEFailed() {
268 ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
269 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES).setResponseCode(ResponseCodes.RESPONSE_FAILED)
270 .setResponseMessage("PCE calculation failed").build();
271 ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
272 return new PathComputationRequestOutputBuilder().setConfigurationResponseCommon(configurationResponseCommon)
273 .setResponseParameters(reponseParameters).build();
276 private Boolean validateParams(String serviceName, SdncRequestHeader sdncRequestHeader) {
277 boolean result = true;
278 if (!checkString(serviceName)) {
280 LOG.error("Service Name (common-id for Temp service) is not set");
281 } else if (sdncRequestHeader == null) {
282 LOG.error("Service sdncRequestHeader 'request-id' is not set");
288 private static boolean checkString(String value) {
289 return ((value != null) && (value.compareTo("") != 0));
292 private final class CancelResourceReserveOutputFutureCallback
293 implements FutureCallback<CancelResourceReserveOutput> {
294 private final ServiceNotificationTypes notifType;
295 private final String serviceName;
297 ServiceRpcResultSh notification = null;
299 private CancelResourceReserveOutputFutureCallback(ServiceNotificationTypes notifType, String serviceName) {
300 this.notifType = notifType;
301 this.serviceName = serviceName;
305 public void onSuccess(CancelResourceReserveOutput response) {
306 if (response != null) {
308 * If PCE reply is received before timer expiration with a positive result, a
309 * service is created with admin and operational status 'down'.
311 message = "PCE replied to CRR Request !";
312 LOG.info("PCE replied to CRR Request : {}", response);
314 new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
315 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
317 notificationPublishService.putNotification(notification);
318 } catch (InterruptedException e) {
319 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
322 message = "PCE failed ";
323 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
324 .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
326 notificationPublishService.putNotification(notification);
327 } catch (InterruptedException e) {
328 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
334 public void onFailure(Throwable arg0) {
335 LOG.error("Cancel resource failed !");
336 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
337 .setServiceName(serviceName).setStatus(RpcStatusEx.Failed)
338 .setStatusMessage("CRR Request failed : " + arg0.getMessage()).build();
340 notificationPublishService.putNotification(notification);
341 } catch (InterruptedException e) {
342 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
347 private final class PathComputationRequestOutputCallback implements FutureCallback<PathComputationRequestOutput> {
348 private final ServiceNotificationTypes notifType;
349 private final String serviceName;
351 ServiceRpcResultSh notification = null;
353 private PathComputationRequestOutputCallback(ServiceNotificationTypes notifType, String serviceName) {
354 this.notifType = notifType;
355 this.serviceName = serviceName;
359 public void onSuccess(PathComputationRequestOutput response) {
360 if (response != null) {
362 * If PCE reply is received before timer expiration with a positive result, a
363 * service is created with admin and operational status 'down'.
365 message = "PCE replied to PCR Request !";
366 LOG.info("PCE replied to PCR Request : {}", response);
367 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
368 .setServiceName(serviceName)
369 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
371 notificationPublishService.putNotification(notification);
372 } catch (InterruptedException e) {
373 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
376 message = "PCE failed ";
377 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
378 .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
380 notificationPublishService.putNotification(notification);
381 } catch (InterruptedException e) {
382 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
388 public void onFailure(Throwable arg0) {
389 LOG.error("Path not calculated..");
390 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
391 .setServiceName(serviceName)
392 .setStatus(RpcStatusEx.Failed).setStatusMessage("PCR Request failed : " + arg0.getMessage())
395 notificationPublishService.putNotification(notification);
396 } catch (InterruptedException e) {
397 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);