Remove transportpce-routing-constraint model
[transportpce.git] / servicehandler / src / main / java / org / opendaylight / transportpce / servicehandler / service / PCEServiceWrapper.java
1 /*
2  * Copyright © 2017 Orange, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.transportpce.servicehandler.service;
9
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.ModelMappingUtils;
20 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveInput;
21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveInputBuilder;
22 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveOutput;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.CancelResourceReserveOutputBuilder;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestInput;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestInputBuilder;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestOutput;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220118.PathComputationRequestOutputBuilder;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultSh;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultShBuilder;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ServiceEndpoint;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ServiceNotificationTypes;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.configuration.response.common.ConfigurationResponseCommon;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.configuration.response.common.ConfigurationResponseCommonBuilder;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.sdnc.request.header.SdncRequestHeader;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constrains.rev190329.routing.constraints.HardConstraints;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constrains.rev190329.routing.constraints.SoftConstraints;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceCreateInput;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.ServiceFeasibilityCheckInput;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.TempServiceCreateInput;
40 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
41 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
42 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParameters;
43 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParametersBuilder;
44 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.handler.header.ServiceHandlerHeaderBuilder;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 public class PCEServiceWrapper {
49
50     private static final String NOTIFICATION_OFFER_REJECTED_MSG = "notification offer rejected : ";
51
52     private static final String PERFORMING_PCE_MSG = "performing PCE ...";
53
54     private static final Logger LOG = LoggerFactory.getLogger(PCEServiceWrapper.class);
55
56     private final PathComputationService pathComputationService;
57     private final NotificationPublishService notificationPublishService;
58     private ServiceRpcResultSh notification = null;
59     private final ListeningExecutorService executor;
60
61     public PCEServiceWrapper(PathComputationService pathComputationService,
62             NotificationPublishService notificationPublishService) {
63         this.pathComputationService = pathComputationService;
64         this.notificationPublishService = notificationPublishService;
65         executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
66     }
67
68     public PathComputationRequestOutput performPCE(ServiceCreateInput serviceCreateInput, boolean reserveResource) {
69         LOG.info(PERFORMING_PCE_MSG);
70         if (validateParams(serviceCreateInput.getServiceName(), serviceCreateInput.getSdncRequestHeader())) {
71             return performPCE(serviceCreateInput.getHardConstraints(), serviceCreateInput.getSoftConstraints(),
72                     serviceCreateInput.getServiceName(), serviceCreateInput.getSdncRequestHeader(),
73                     serviceCreateInput.getServiceAEnd(), serviceCreateInput.getServiceZEnd(),
74                     ServiceNotificationTypes.ServiceCreateResult, reserveResource);
75         } else {
76             return returnPCEFailed();
77         }
78     }
79
80     public PathComputationRequestOutput performPCE(TempServiceCreateInput tempServiceCreateInput,
81             boolean reserveResource) {
82         LOG.info(PERFORMING_PCE_MSG);
83         if (validateParams(tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader())) {
84             return performPCE(tempServiceCreateInput.getHardConstraints(), tempServiceCreateInput.getSoftConstraints(),
85                     tempServiceCreateInput.getCommonId(), tempServiceCreateInput.getSdncRequestHeader(),
86                     tempServiceCreateInput.getServiceAEnd(), tempServiceCreateInput.getServiceZEnd(),
87                     ServiceNotificationTypes.ServiceCreateResult, reserveResource);
88         } else {
89             return returnPCEFailed();
90         }
91     }
92
93     public PathComputationRequestOutput performPCE(ServiceFeasibilityCheckInput serviceFeasibilityCheckInput,
94             boolean reserveResource) {
95         LOG.info(PERFORMING_PCE_MSG);
96         if (validateParams(serviceFeasibilityCheckInput.getCommonId(),
97                 serviceFeasibilityCheckInput.getSdncRequestHeader())) {
98             return performPCE(serviceFeasibilityCheckInput.getHardConstraints(),
99                     serviceFeasibilityCheckInput.getSoftConstraints(), serviceFeasibilityCheckInput.getCommonId(),
100                     serviceFeasibilityCheckInput.getSdncRequestHeader(), serviceFeasibilityCheckInput.getServiceAEnd(),
101                     serviceFeasibilityCheckInput.getServiceZEnd(),
102                     ServiceNotificationTypes.ServiceCreateResult, reserveResource);
103         } else {
104             return returnPCEFailed();
105         }
106     }
107
108     private PathComputationRequestOutput performPCE(HardConstraints hardConstraints, SoftConstraints softConstraints,
109             String serviceName, SdncRequestHeader sdncRequestHeader, ServiceEndpoint serviceAEnd,
110             ServiceEndpoint serviceZEnd, ServiceNotificationTypes notifType, boolean reserveResource) {
111         LOG.info("Calling path computation.");
112         notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
113                 .setStatus(RpcStatusEx.Pending)
114                 .setStatusMessage("Service compliant, submitting PathComputation Request ...").build();
115         try {
116             notificationPublishService.putNotification(notification);
117         } catch (InterruptedException e) {
118             LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
119         }
120         FutureCallback<PathComputationRequestOutput> pceCallback =
121                 new PathComputationRequestOutputCallback(notifType, serviceName);
122         PathComputationRequestInput pathComputationRequestInput = createPceRequestInput(serviceName, sdncRequestHeader,
123                 hardConstraints, softConstraints, reserveResource, serviceAEnd, serviceZEnd);
124         ListenableFuture<PathComputationRequestOutput> pce = this.pathComputationService
125                 .pathComputationRequest(pathComputationRequestInput);
126         Futures.addCallback(pce, pceCallback, executor);
127
128         ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
129                 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
130                 .setRequestId(sdncRequestHeader.getRequestId())
131                 .setResponseCode(ResponseCodes.RESPONSE_OK)
132                 .setResponseMessage("PCE calculation in progress")
133                 .build();
134         ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
135         return new PathComputationRequestOutputBuilder()
136                 .setConfigurationResponseCommon(configurationResponseCommon)
137                 .setResponseParameters(reponseParameters)
138                 .build();
139     }
140
141     private PathComputationRequestInput createPceRequestInput(String serviceName,
142             SdncRequestHeader serviceHandler, HardConstraints hardConstraints,
143             SoftConstraints softConstraints, Boolean reserveResource, ServiceEndpoint serviceAEnd,
144             ServiceEndpoint serviceZEnd) {
145         LOG.info("Mapping ServiceCreateInput or ServiceFeasibilityCheckInput or serviceReconfigureInput to PCE"
146                 + "requests");
147         ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
148         if (serviceHandler != null) {
149             serviceHandlerHeader.setRequestId(serviceHandler.getRequestId());
150         }
151         return new PathComputationRequestInputBuilder()
152             .setServiceName(serviceName)
153             .setResourceReserve(reserveResource)
154             .setServiceHandlerHeader(serviceHandlerHeader.build())
155             .setHardConstraints(hardConstraints)
156             .setSoftConstraints(softConstraints)
157             .setPceRoutingMetric(PceMetric.TEMetric)
158             .setServiceAEnd(ModelMappingUtils.createServiceAEnd(serviceAEnd))
159             .setServiceZEnd(ModelMappingUtils.createServiceZEnd(serviceZEnd))
160             .build();
161     }
162
163     private CancelResourceReserveInput mappingCancelResourceReserve(String serviceName,
164                                                                     SdncRequestHeader sdncRequestHeader) {
165         LOG.info("Mapping to PCE Cancel resource request input");
166         CancelResourceReserveInputBuilder cancelResourceReserveInput = new CancelResourceReserveInputBuilder();
167         if (serviceName != null) {
168             ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
169             if (sdncRequestHeader != null) {
170                 serviceHandlerHeader.setRequestId(sdncRequestHeader.getRequestId());
171             }
172             cancelResourceReserveInput.setServiceName(serviceName)
173                     .setServiceHandlerHeader(serviceHandlerHeader.build());
174             return cancelResourceReserveInput.build();
175         } else {
176             LOG.error("Service Name (common-id for Temp service) is not set");
177             return null;
178         }
179     }
180
181     public CancelResourceReserveOutput cancelPCEResource(String serviceName, ServiceNotificationTypes notifType) {
182         LOG.info("Calling cancel resource reserve computation.");
183         notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
184                 .setStatus(RpcStatusEx.Pending)
185                 .setStatusMessage("submitting Cancel resource reserve Request ...").build();
186         try {
187             notificationPublishService.putNotification(notification);
188         } catch (InterruptedException e) {
189             LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
190         }
191         FutureCallback<CancelResourceReserveOutput> pceCallback =
192                 new CancelResourceReserveOutputFutureCallback(notifType, serviceName);
193         CancelResourceReserveInput cancelResourceReserveInput = mappingCancelResourceReserve(serviceName, null);
194         ConfigurationResponseCommonBuilder configurationResponseCommon = new ConfigurationResponseCommonBuilder();
195         if (cancelResourceReserveInput != null) {
196             String requestId = cancelResourceReserveInput.getServiceHandlerHeader().getRequestId();
197             ListenableFuture<CancelResourceReserveOutput> pce =
198                     this.pathComputationService.cancelResourceReserve(cancelResourceReserveInput);
199             Futures.addCallback(pce, pceCallback, executor);
200             if (requestId != null) {
201                 configurationResponseCommon.setRequestId(requestId);
202             }
203             configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
204                     .setResponseCode(ResponseCodes.RESPONSE_OK).setResponseMessage("PCE calculation in progress");
205             return new CancelResourceReserveOutputBuilder()
206                     .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
207         } else {
208             configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES)
209                     .setResponseCode(ResponseCodes.RESPONSE_FAILED).setResponseMessage("PCE failed !");
210             return new CancelResourceReserveOutputBuilder()
211                     .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
212         }
213     }
214
215     private static PathComputationRequestOutput returnPCEFailed() {
216         ConfigurationResponseCommon configurationResponseCommon = new ConfigurationResponseCommonBuilder()
217                 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES).setResponseCode(ResponseCodes.RESPONSE_FAILED)
218                 .setResponseMessage("PCE calculation failed").build();
219         ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
220         return new PathComputationRequestOutputBuilder().setConfigurationResponseCommon(configurationResponseCommon)
221                 .setResponseParameters(reponseParameters).build();
222     }
223
224     private Boolean validateParams(String serviceName, SdncRequestHeader sdncRequestHeader) {
225         boolean result = true;
226         if (!checkString(serviceName)) {
227             result = false;
228             LOG.error("Service Name (common-id for Temp service) is not set");
229         } else if (sdncRequestHeader == null) {
230             LOG.error("Service sdncRequestHeader 'request-id' is not set");
231             result = false;
232         }
233         return result;
234     }
235
236     private static boolean checkString(String value) {
237         return ((value != null) && (value.compareTo("") != 0));
238     }
239
240     private final class CancelResourceReserveOutputFutureCallback
241             implements FutureCallback<CancelResourceReserveOutput> {
242         private final ServiceNotificationTypes notifType;
243         private final String serviceName;
244         String message = "";
245         ServiceRpcResultSh notification = null;
246
247         private CancelResourceReserveOutputFutureCallback(ServiceNotificationTypes notifType, String serviceName) {
248             this.notifType = notifType;
249             this.serviceName = serviceName;
250         }
251
252         @Override
253         public void onSuccess(CancelResourceReserveOutput response) {
254             if (response != null) {
255                 /**
256                  * If PCE reply is received before timer expiration with a positive result, a
257                  * service is created with admin and operational status 'down'.
258                  */
259                 message = "PCE replied to CRR Request !";
260                 LOG.info("PCE replied to CRR Request : {}", response);
261                 notification =
262                         new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
263                                 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
264                 try {
265                     notificationPublishService.putNotification(notification);
266                 } catch (InterruptedException e) {
267                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
268                 }
269             } else {
270                 message = "PCE failed ";
271                 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
272                         .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
273                 try {
274                     notificationPublishService.putNotification(notification);
275                 } catch (InterruptedException e) {
276                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
277                 }
278             }
279         }
280
281         @Override
282         public void onFailure(Throwable arg0) {
283             LOG.error("Cancel resource failed !");
284             notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
285                     .setServiceName(serviceName).setStatus(RpcStatusEx.Failed)
286                     .setStatusMessage("CRR Request failed  : " + arg0.getMessage()).build();
287             try {
288                 notificationPublishService.putNotification(notification);
289             } catch (InterruptedException e) {
290                 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
291             }
292         }
293     }
294
295     private final class PathComputationRequestOutputCallback implements FutureCallback<PathComputationRequestOutput> {
296         private final ServiceNotificationTypes notifType;
297         private final String serviceName;
298         String message = "";
299         ServiceRpcResultSh notification = null;
300
301         private PathComputationRequestOutputCallback(ServiceNotificationTypes notifType, String serviceName) {
302             this.notifType = notifType;
303             this.serviceName = serviceName;
304         }
305
306         @Override
307         public void onSuccess(PathComputationRequestOutput response) {
308             if (response != null) {
309                 /**
310                  * If PCE reply is received before timer expiration with a positive result, a
311                  * service is created with admin and operational status 'down'.
312                  */
313                 message = "PCE replied to PCR Request !";
314                 LOG.info("PCE replied to PCR Request : {}", response);
315                 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
316                         .setServiceName(serviceName)
317                         .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
318                 try {
319                     notificationPublishService.putNotification(notification);
320                 } catch (InterruptedException e) {
321                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
322                 }
323             } else {
324                 message = "PCE failed ";
325                 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
326                         .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
327                 try {
328                     notificationPublishService.putNotification(notification);
329                 } catch (InterruptedException e) {
330                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
331                 }
332             }
333         }
334
335         @Override
336         public void onFailure(Throwable arg0) {
337             LOG.error("Path not calculated..");
338             notification = new ServiceRpcResultShBuilder().setNotificationType(notifType)
339                     .setServiceName(serviceName)
340                     .setStatus(RpcStatusEx.Failed).setStatusMessage("PCR Request failed  : " + arg0.getMessage())
341                     .build();
342             try {
343                 notificationPublishService.putNotification(notification);
344             } catch (InterruptedException e) {
345                 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
346             }
347         }
348     }
349 }