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.Executors;
16 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
17 import org.opendaylight.transportpce.common.ResponseCodes;
18 import org.opendaylight.transportpce.pce.service.PathComputationService;
19 import org.opendaylight.transportpce.servicehandler.MappingConstraints;
20 import org.opendaylight.transportpce.servicehandler.ModelMappingUtils;
21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveInput;
22 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveInputBuilder;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveOutput;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveOutputBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestInput;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestInputBuilder;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestOutput;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestOutputBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultSh;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultShBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ServiceEndpoint;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ServiceNotificationTypes;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.configuration.response.common.ConfigurationResponseCommon;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.configuration.response.common.ConfigurationResponseCommonBuilder;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.sdnc.request.header.SdncRequestHeader;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateInput;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceFeasibilityCheckInput;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.TempServiceCreateInput;
39 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev220118.routing.constraints.sp.HardConstraints;
40 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev220118.routing.constraints.sp.SoftConstraints;
41 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
42 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
43 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParameters;
44 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParametersBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.handler.header.ServiceHandlerHeaderBuilder;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 public class PCEServiceWrapper {
51 private static final String NOTIFICATION_OFFER_REJECTED_MSG = "notification offer rejected : ";
53 private static final String PERFORMING_PCE_MSG = "performing PCE ...";
55 private static final Logger LOG = LoggerFactory.getLogger(PCEServiceWrapper.class);
57 private final PathComputationService pathComputationService;
58 private final NotificationPublishService notificationPublishService;
59 private ServiceRpcResultSh notification = null;
60 private final ListeningExecutorService executor;
62 public PCEServiceWrapper(PathComputationService pathComputationService,
63 NotificationPublishService notificationPublishService) {
64 this.pathComputationService = pathComputationService;
65 this.notificationPublishService = notificationPublishService;
66 executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
69 public PathComputationRequestOutput performPCE(ServiceCreateInput serviceCreateInput, boolean reserveResource) {
70 LOG.info(PERFORMING_PCE_MSG);
71 if (validateParams(serviceCreateInput.getServiceName(), serviceCreateInput.getSdncRequestHeader())) {
72 return performPCE(serviceCreateInput.getHardConstraints(), serviceCreateInput.getSoftConstraints(),
73 serviceCreateInput.getServiceName(), serviceCreateInput.getSdncRequestHeader(),
74 serviceCreateInput.getServiceAEnd(), serviceCreateInput.getServiceZEnd(),
75 ServiceNotificationTypes.ServiceCreateResult, reserveResource);
77 return returnPCEFailed();
81 public PathComputationRequestOutput performPCE(TempServiceCreateInput tempServiceCreateInput,
82 boolean reserveResource) {
83 LOG.info(PERFORMING_PCE_MSG);
84 if (validateParams(tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader())) {
85 return performPCE(tempServiceCreateInput.getHardConstraints(), tempServiceCreateInput.getSoftConstraints(),
86 tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader(),
87 tempServiceCreateInput.getServiceAEnd(), tempServiceCreateInput.getServiceZEnd(),
88 ServiceNotificationTypes.ServiceCreateResult, reserveResource);
90 return returnPCEFailed();
94 public PathComputationRequestOutput performPCE(ServiceFeasibilityCheckInput serviceFeasibilityCheckInput,
95 boolean reserveResource) {
96 LOG.info(PERFORMING_PCE_MSG);
97 if (validateParams(serviceFeasibilityCheckInput.getCommonId(),
98 serviceFeasibilityCheckInput.getSdncRequestHeader())) {
99 return performPCE(serviceFeasibilityCheckInput.getHardConstraints(),
100 serviceFeasibilityCheckInput.getSoftConstraints(), serviceFeasibilityCheckInput.getCommonId(),
101 serviceFeasibilityCheckInput.getSdncRequestHeader(), serviceFeasibilityCheckInput.getServiceAEnd(),
102 serviceFeasibilityCheckInput.getServiceZEnd(),
103 ServiceNotificationTypes.ServiceCreateResult, reserveResource);
105 return returnPCEFailed();
109 private PathComputationRequestOutput performPCE(org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constrains
110 .rev190329.routing.constraints.HardConstraints hardConstraints, org.opendaylight.yang.gen.v1.http.org
111 .openroadm.routing.constrains.rev190329.routing.constraints.SoftConstraints softConstraints,
112 String serviceName, SdncRequestHeader sdncRequestHeader, ServiceEndpoint serviceAEnd,
113 ServiceEndpoint serviceZEnd, ServiceNotificationTypes notifType, boolean reserveResource) {
114 MappingConstraints mappingConstraints = new MappingConstraints(hardConstraints, softConstraints);
115 mappingConstraints.serviceToServicePathConstarints();
116 LOG.info("Calling path computation.");
117 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
118 .setStatus(RpcStatusEx.Pending)
119 .setStatusMessage("Service compliant, submitting PathComputation Request ...").build();
121 notificationPublishService.putNotification(notification);
122 } catch (InterruptedException e) {
123 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
125 FutureCallback<PathComputationRequestOutput> pceCallback =
126 new PathComputationRequestOutputCallback(notifType, serviceName);
127 PathComputationRequestInput pathComputationRequestInput = createPceRequestInput(serviceName, sdncRequestHeader,
128 mappingConstraints.getServicePathHardConstraints(), mappingConstraints.getServicePathSoftConstraints(),
129 reserveResource, serviceAEnd, serviceZEnd);
130 ListenableFuture<PathComputationRequestOutput> pce = this.pathComputationService
131 .pathComputationRequest(pathComputationRequestInput);
132 Futures.addCallback(pce, pceCallback, executor);
134 ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
135 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
136 .setRequestId(sdncRequestHeader.getRequestId())
137 .setResponseCode(ResponseCodes.RESPONSE_OK)
138 .setResponseMessage("PCE calculation in progress")
140 ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
141 return new PathComputationRequestOutputBuilder()
142 .setConfigurationResponseCommon(configurationResponseCommon)
143 .setResponseParameters(reponseParameters)
147 private PathComputationRequestInput createPceRequestInput(String serviceName,
148 SdncRequestHeader serviceHandler, HardConstraints hardConstraints,
149 SoftConstraints softConstraints, Boolean reserveResource, ServiceEndpoint serviceAEnd,
150 ServiceEndpoint serviceZEnd) {
151 LOG.info("Mapping ServiceCreateInput or ServiceFeasibilityCheckInput or serviceReconfigureInput to PCE"
153 ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
154 if (serviceHandler != null) {
155 serviceHandlerHeader.setRequestId(serviceHandler.getRequestId());
157 return new PathComputationRequestInputBuilder()
158 .setServiceName(serviceName)
159 .setResourceReserve(reserveResource)
160 .setServiceHandlerHeader(serviceHandlerHeader.build())
161 .setHardConstraints(hardConstraints)
162 .setSoftConstraints(softConstraints)
163 .setPceRoutingMetric(PceMetric.TEMetric)
164 .setServiceAEnd(ModelMappingUtils.createServiceAEnd(serviceAEnd))
165 .setServiceZEnd(ModelMappingUtils.createServiceZEnd(serviceZEnd))
169 private CancelResourceReserveInput mappingCancelResourceReserve(String serviceName,
170 SdncRequestHeader sdncRequestHeader) {
171 LOG.info("Mapping to PCE Cancel resource request input");
172 CancelResourceReserveInputBuilder cancelResourceReserveInput = new CancelResourceReserveInputBuilder();
173 if (serviceName != null) {
174 ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
175 if (sdncRequestHeader != null) {
176 serviceHandlerHeader.setRequestId(sdncRequestHeader.getRequestId());
178 cancelResourceReserveInput.setServiceName(serviceName)
179 .setServiceHandlerHeader(serviceHandlerHeader.build());
180 return cancelResourceReserveInput.build();
182 LOG.error("Service Name (common-id for Temp service) is not set");
187 public CancelResourceReserveOutput cancelPCEResource(String serviceName, ServiceNotificationTypes notifType) {
188 LOG.info("Calling cancel resource reserve computation.");
189 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
190 .setStatus(RpcStatusEx.Pending)
191 .setStatusMessage("submitting Cancel resource reserve Request ...").build();
193 notificationPublishService.putNotification(notification);
194 } catch (InterruptedException e) {
195 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
197 FutureCallback<CancelResourceReserveOutput> pceCallback =
198 new CancelResourceReserveOutputFutureCallback(notifType, serviceName);
199 CancelResourceReserveInput cancelResourceReserveInput = mappingCancelResourceReserve(serviceName, null);
200 ConfigurationResponseCommonBuilder configurationResponseCommon = new ConfigurationResponseCommonBuilder();
201 if (cancelResourceReserveInput != null) {
202 String requestId = cancelResourceReserveInput.getServiceHandlerHeader().getRequestId();
203 ListenableFuture<CancelResourceReserveOutput> pce =
204 this.pathComputationService.cancelResourceReserve(cancelResourceReserveInput);
205 Futures.addCallback(pce, pceCallback, executor);
206 if (requestId != null) {
207 configurationResponseCommon.setRequestId(requestId);
209 configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
210 .setResponseCode(ResponseCodes.RESPONSE_OK).setResponseMessage("PCE calculation in progress");
211 return new CancelResourceReserveOutputBuilder()
212 .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
214 configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES)
215 .setResponseCode(ResponseCodes.RESPONSE_FAILED).setResponseMessage("PCE failed !");
216 return new CancelResourceReserveOutputBuilder()
217 .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
221 private static PathComputationRequestOutput returnPCEFailed() {
222 ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
223 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES).setResponseCode(ResponseCodes.RESPONSE_FAILED)
224 .setResponseMessage("PCE calculation failed").build();
225 ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
226 return new PathComputationRequestOutputBuilder().setConfigurationResponseCommon(configurationResponseCommon)
227 .setResponseParameters(reponseParameters).build();
230 private Boolean validateParams(String serviceName, SdncRequestHeader sdncRequestHeader) {
231 boolean result = true;
232 if (!checkString(serviceName)) {
234 LOG.error("Service Name (common-id for Temp service) is not set");
235 } else if (sdncRequestHeader == null) {
236 LOG.error("Service sdncRequestHeader 'request-id' is not set");
242 private static boolean checkString(String value) {
243 return ((value != null) && (value.compareTo("") != 0));
246 private final class CancelResourceReserveOutputFutureCallback
247 implements FutureCallback<CancelResourceReserveOutput> {
248 private final ServiceNotificationTypes notifType;
249 private final String serviceName;
251 ServiceRpcResultSh notification = null;
253 private CancelResourceReserveOutputFutureCallback(ServiceNotificationTypes notifType, String serviceName) {
254 this.notifType = notifType;
255 this.serviceName = serviceName;
259 public void onSuccess(CancelResourceReserveOutput response) {
260 if (response != null) {
262 * If PCE reply is received before timer expiration with a positive result, a
263 * service is created with admin and operational status 'down'.
265 message = "PCE replied to CRR Request !";
266 LOG.info("PCE replied to CRR Request : {}", response);
268 new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
269 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
271 notificationPublishService.putNotification(notification);
272 } catch (InterruptedException e) {
273 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
276 message = "PCE failed ";
277 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
278 .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
280 notificationPublishService.putNotification(notification);
281 } catch (InterruptedException e) {
282 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
288 public void onFailure(Throwable arg0) {
289 LOG.error("Cancel resource failed !");
290 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
291 .setServiceName(serviceName).setStatus(RpcStatusEx.Failed)
292 .setStatusMessage("CRR Request failed : " + arg0.getMessage()).build();
294 notificationPublishService.putNotification(notification);
295 } catch (InterruptedException e) {
296 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
301 private final class PathComputationRequestOutputCallback implements FutureCallback<PathComputationRequestOutput> {
302 private final ServiceNotificationTypes notifType;
303 private final String serviceName;
305 ServiceRpcResultSh notification = null;
307 private PathComputationRequestOutputCallback(ServiceNotificationTypes notifType, String serviceName) {
308 this.notifType = notifType;
309 this.serviceName = serviceName;
313 public void onSuccess(PathComputationRequestOutput response) {
314 if (response != null) {
316 * If PCE reply is received before timer expiration with a positive result, a
317 * service is created with admin and operational status 'down'.
319 message = "PCE replied to PCR Request !";
320 LOG.info("PCE replied to PCR Request : {}", response);
321 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
322 .setServiceName(serviceName)
323 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
325 notificationPublishService.putNotification(notification);
326 } catch (InterruptedException e) {
327 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
330 message = "PCE failed ";
331 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
332 .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
334 notificationPublishService.putNotification(notification);
335 } catch (InterruptedException e) {
336 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
342 public void onFailure(Throwable arg0) {
343 LOG.error("Path not calculated..");
344 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
345 .setServiceName(serviceName)
346 .setStatus(RpcStatusEx.Failed).setStatusMessage("PCR Request failed : " + arg0.getMessage())
349 notificationPublishService.putNotification(notification);
350 } catch (InterruptedException e) {
351 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);