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,
82 serviceCreateInput.getCustomer());
84 return returnPCEFailed();
88 public PathComputationRequestOutput performPCE(TempServiceCreateInput tempServiceCreateInput,
89 boolean reserveResource) {
90 LOG.info(PERFORMING_PCE_MSG);
91 if (validateParams(tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader())) {
92 return performPCE(tempServiceCreateInput.getHardConstraints(), tempServiceCreateInput.getSoftConstraints(),
93 tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader(),
94 tempServiceCreateInput.getServiceAEnd(), tempServiceCreateInput.getServiceZEnd(),
95 ServiceNotificationTypes.ServiceCreateResult, reserveResource,
96 tempServiceCreateInput.getCustomer());
98 return returnPCEFailed();
102 public PathComputationRequestOutput performPCE(ServiceFeasibilityCheckInput serviceFeasibilityCheckInput,
103 boolean reserveResource) {
104 LOG.info(PERFORMING_PCE_MSG);
105 if (validateParams(serviceFeasibilityCheckInput.getCommonId(),
106 serviceFeasibilityCheckInput.getSdncRequestHeader())) {
107 return performPCE(serviceFeasibilityCheckInput.getHardConstraints(),
108 serviceFeasibilityCheckInput.getSoftConstraints(), serviceFeasibilityCheckInput.getCommonId(),
109 serviceFeasibilityCheckInput.getSdncRequestHeader(), serviceFeasibilityCheckInput.getServiceAEnd(),
110 serviceFeasibilityCheckInput.getServiceZEnd(),
111 ServiceNotificationTypes.ServiceCreateResult, reserveResource,
112 serviceFeasibilityCheckInput.getCustomer());
114 return returnPCEFailed();
118 private PathComputationRequestOutput performPCE(HardConstraints hardConstraints, SoftConstraints softConstraints,
119 String serviceName, SdncRequestHeader sdncRequestHeader, ServiceEndpoint serviceAEnd,
120 ServiceEndpoint serviceZEnd, ServiceNotificationTypes notifType, boolean reserveResource,
121 String customerName) {
122 LOG.info("Calling path computation.");
123 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
124 .setStatus(RpcStatusEx.Pending)
125 .setStatusMessage("Service compliant, submitting PathComputation Request ...").build();
127 notificationPublishService.putNotification(notification);
128 } catch (InterruptedException e) {
129 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
131 FutureCallback<PathComputationRequestOutput> pceCallback =
132 new PathComputationRequestOutputCallback(notifType, serviceName);
133 PathComputationRequestInput pathComputationRequestInput = createPceRequestInput(serviceName, sdncRequestHeader,
134 hardConstraints, softConstraints, reserveResource, serviceAEnd, serviceZEnd, customerName);
135 ListenableFuture<PathComputationRequestOutput> pce = this.pathComputationService
136 .pathComputationRequest(pathComputationRequestInput);
137 Futures.addCallback(pce, pceCallback, executor);
139 ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
140 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
141 .setRequestId(sdncRequestHeader.getRequestId())
142 .setResponseCode(ResponseCodes.RESPONSE_OK)
143 .setResponseMessage("PCE calculation in progress")
145 ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
146 return new PathComputationRequestOutputBuilder()
147 .setConfigurationResponseCommon(configurationResponseCommon)
148 .setResponseParameters(reponseParameters)
152 public PathComputationRerouteRequestOutput performPCEReroute(HardConstraints hardConstraints,
153 SoftConstraints softConstraints, SdncRequestHeader serviceHandler, ServiceEndpoint serviceAEnd,
154 ServiceEndpoint serviceZEnd,
155 Endpoints endpoints) {
156 // TODO: Make it asynchronous
157 LOG.info("Calling path computation reroute");
158 PathComputationRerouteRequestInput inputPCE = createPceRerouteRequestInput(hardConstraints, softConstraints,
159 serviceHandler, serviceAEnd, serviceZEnd, endpoints);
160 ListenableFuture<PathComputationRerouteRequestOutput> res =
161 pathComputationService.pathComputationRerouteRequest(inputPCE);
164 } catch (ExecutionException | InterruptedException e) {
165 LOG.warn("PerformPCEReroute FAILED ! ", e);
166 return new PathComputationRerouteRequestOutputBuilder()
167 .setConfigurationResponseCommon(new ConfigurationResponseCommonBuilder()
168 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES)
169 .setRequestId("None")
170 .setResponseCode(ResponseCodes.RESPONSE_OK)
171 .setResponseMessage("PCE calculation FAILED")
177 private PathComputationRequestInput createPceRequestInput(String serviceName,
178 SdncRequestHeader serviceHandler, HardConstraints hardConstraints,
179 SoftConstraints softConstraints, Boolean reserveResource, ServiceEndpoint serviceAEnd,
180 ServiceEndpoint serviceZEnd, String customerName) {
181 LOG.info("Mapping ServiceCreateInput or ServiceFeasibilityCheckInput or serviceReconfigureInput to PCE"
183 ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
184 if (serviceHandler != null) {
185 serviceHandlerHeader.setRequestId(serviceHandler.getRequestId());
187 return new PathComputationRequestInputBuilder()
188 .setServiceName(serviceName)
189 .setResourceReserve(reserveResource)
190 .setServiceHandlerHeader(serviceHandlerHeader.build())
191 .setHardConstraints(hardConstraints)
192 .setSoftConstraints(softConstraints)
193 .setPceRoutingMetric(PceMetric.TEMetric)
194 .setCustomerName(customerName)
195 .setServiceAEnd(ModelMappingUtils.createServiceAEnd(serviceAEnd))
196 .setServiceZEnd(ModelMappingUtils.createServiceZEnd(serviceZEnd))
200 private PathComputationRerouteRequestInput createPceRerouteRequestInput(HardConstraints hardConstraints,
201 SoftConstraints softConstraints, SdncRequestHeader serviceHandler, ServiceEndpoint serviceAEnd,
202 ServiceEndpoint serviceZEnd, Endpoints endpoints) {
203 LOG.info("Mapping Service-reroute to PCE requests");
204 return new PathComputationRerouteRequestInputBuilder()
205 .setServiceHandlerHeader(serviceHandler == null
206 ? new ServiceHandlerHeaderBuilder().build()
207 : new ServiceHandlerHeaderBuilder().setRequestId(serviceHandler.getRequestId()).build())
208 .setHardConstraints(hardConstraints)
209 .setSoftConstraints(softConstraints)
210 .setPceRoutingMetric(PceMetric.TEMetric)
211 .setEndpoints(new EndpointsBuilder()
212 .setAEndTp(endpoints.getAEndTp())
213 .setZEndTp(endpoints.getZEndTp())
215 .setServiceAEnd(ModelMappingUtils.createServiceAEndReroute(serviceAEnd))
216 .setServiceZEnd(ModelMappingUtils.createServiceZEndReroute(serviceZEnd))
220 private CancelResourceReserveInput mappingCancelResourceReserve(String serviceName,
221 SdncRequestHeader sdncRequestHeader) {
222 LOG.info("Mapping to PCE Cancel resource request input");
223 CancelResourceReserveInputBuilder cancelResourceReserveInput = new CancelResourceReserveInputBuilder();
224 if (serviceName != null) {
225 ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
226 if (sdncRequestHeader != null) {
227 serviceHandlerHeader.setRequestId(sdncRequestHeader.getRequestId());
229 cancelResourceReserveInput.setServiceName(serviceName)
230 .setServiceHandlerHeader(serviceHandlerHeader.build());
231 return cancelResourceReserveInput.build();
233 LOG.error("Service Name (common-id for Temp service) is not set");
238 public CancelResourceReserveOutput cancelPCEResource(String serviceName, ServiceNotificationTypes notifType) {
239 LOG.info("Calling cancel resource reserve computation.");
240 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
241 .setStatus(RpcStatusEx.Pending)
242 .setStatusMessage("submitting Cancel resource reserve Request ...").build();
244 notificationPublishService.putNotification(notification);
245 } catch (InterruptedException e) {
246 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
248 FutureCallback<CancelResourceReserveOutput> pceCallback =
249 new CancelResourceReserveOutputFutureCallback(notifType, serviceName);
250 CancelResourceReserveInput cancelResourceReserveInput = mappingCancelResourceReserve(serviceName, null);
251 ConfigurationResponseCommonBuilder configurationResponseCommon = new ConfigurationResponseCommonBuilder();
252 if (cancelResourceReserveInput != null) {
253 String requestId = cancelResourceReserveInput.getServiceHandlerHeader().getRequestId();
254 ListenableFuture<CancelResourceReserveOutput> pce =
255 this.pathComputationService.cancelResourceReserve(cancelResourceReserveInput);
256 Futures.addCallback(pce, pceCallback, executor);
257 if (requestId != null) {
258 configurationResponseCommon.setRequestId(requestId);
260 configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
261 .setResponseCode(ResponseCodes.RESPONSE_OK).setResponseMessage("PCE calculation in progress");
262 return new CancelResourceReserveOutputBuilder()
263 .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
265 configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES)
266 .setResponseCode(ResponseCodes.RESPONSE_FAILED).setResponseMessage("PCE failed !");
267 return new CancelResourceReserveOutputBuilder()
268 .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
272 private static PathComputationRequestOutput returnPCEFailed() {
273 ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
274 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES).setResponseCode(ResponseCodes.RESPONSE_FAILED)
275 .setResponseMessage("PCE calculation failed").build();
276 ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
277 return new PathComputationRequestOutputBuilder().setConfigurationResponseCommon(configurationResponseCommon)
278 .setResponseParameters(reponseParameters).build();
281 private Boolean validateParams(String serviceName, SdncRequestHeader sdncRequestHeader) {
282 boolean result = true;
283 if (!checkString(serviceName)) {
285 LOG.error("Service Name (common-id for Temp service) is not set");
286 } else if (sdncRequestHeader == null) {
287 LOG.error("Service sdncRequestHeader 'request-id' is not set");
293 private static boolean checkString(String value) {
294 return ((value != null) && (value.compareTo("") != 0));
297 private final class CancelResourceReserveOutputFutureCallback
298 implements FutureCallback<CancelResourceReserveOutput> {
299 private final ServiceNotificationTypes notifType;
300 private final String serviceName;
302 ServiceRpcResultSh notification = null;
304 private CancelResourceReserveOutputFutureCallback(ServiceNotificationTypes notifType, String serviceName) {
305 this.notifType = notifType;
306 this.serviceName = serviceName;
310 public void onSuccess(CancelResourceReserveOutput response) {
311 if (response != null) {
313 * If PCE reply is received before timer expiration with a positive result, a
314 * service is created with admin and operational status 'down'.
316 message = "PCE replied to CRR Request !";
317 LOG.info("PCE replied to CRR Request : {}", response);
319 new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
320 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
322 notificationPublishService.putNotification(notification);
323 } catch (InterruptedException e) {
324 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
327 message = "PCE failed ";
328 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
329 .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
331 notificationPublishService.putNotification(notification);
332 } catch (InterruptedException e) {
333 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
339 public void onFailure(Throwable arg0) {
340 LOG.error("Cancel resource failed !");
341 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
342 .setServiceName(serviceName).setStatus(RpcStatusEx.Failed)
343 .setStatusMessage("CRR Request failed : " + arg0.getMessage()).build();
345 notificationPublishService.putNotification(notification);
346 } catch (InterruptedException e) {
347 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
352 private final class PathComputationRequestOutputCallback implements FutureCallback<PathComputationRequestOutput> {
353 private final ServiceNotificationTypes notifType;
354 private final String serviceName;
356 ServiceRpcResultSh notification = null;
358 private PathComputationRequestOutputCallback(ServiceNotificationTypes notifType, String serviceName) {
359 this.notifType = notifType;
360 this.serviceName = serviceName;
364 public void onSuccess(PathComputationRequestOutput response) {
365 if (response != null) {
367 * If PCE reply is received before timer expiration with a positive result, a
368 * service is created with admin and operational status 'down'.
370 message = "PCE replied to PCR Request !";
371 LOG.info("PCE replied to PCR Request : {}", response);
372 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
373 .setServiceName(serviceName)
374 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
376 notificationPublishService.putNotification(notification);
377 } catch (InterruptedException e) {
378 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
381 message = "PCE failed ";
382 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
383 .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
385 notificationPublishService.putNotification(notification);
386 } catch (InterruptedException e) {
387 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
393 public void onFailure(Throwable arg0) {
394 LOG.error("Path not calculated..");
395 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
396 .setServiceName(serviceName)
397 .setStatus(RpcStatusEx.Failed).setStatusMessage("PCR Request failed : " + arg0.getMessage())
400 notificationPublishService.putNotification(notification);
401 } catch (InterruptedException e) {
402 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);