Merge "Power setup gainloss failure Junit test"
[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.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;
54
55 public class PCEServiceWrapper {
56
57     private static final String NOTIFICATION_OFFER_REJECTED_MSG = "notification offer rejected : ";
58
59     private static final String PERFORMING_PCE_MSG = "performing PCE ...";
60
61     private static final Logger LOG = LoggerFactory.getLogger(PCEServiceWrapper.class);
62
63     private final PathComputationService pathComputationService;
64     private final NotificationPublishService notificationPublishService;
65     private ServiceRpcResultSh notification = null;
66     private final ListeningExecutorService executor;
67
68     public PCEServiceWrapper(PathComputationService pathComputationService,
69             NotificationPublishService notificationPublishService) {
70         this.pathComputationService = pathComputationService;
71         this.notificationPublishService = notificationPublishService;
72         executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));
73     }
74
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());
83         } else {
84             return returnPCEFailed();
85         }
86     }
87
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());
97         } else {
98             return returnPCEFailed();
99         }
100     }
101
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());
113         } else {
114             return returnPCEFailed();
115         }
116     }
117
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();
126         try {
127             notificationPublishService.putNotification(notification);
128         } catch (InterruptedException e) {
129             LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
130         }
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);
138
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")
144                 .build();
145         ResponseParameters reponseParameters = new ResponseParametersBuilder().build();
146         return new PathComputationRequestOutputBuilder()
147                 .setConfigurationResponseCommon(configurationResponseCommon)
148                 .setResponseParameters(reponseParameters)
149                 .build();
150     }
151
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);
162         try {
163             return res.get();
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")
172                             .build())
173                     .build();
174         }
175     }
176
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"
182                 + "requests");
183         ServiceHandlerHeaderBuilder serviceHandlerHeader = new ServiceHandlerHeaderBuilder();
184         if (serviceHandler != null) {
185             serviceHandlerHeader.setRequestId(serviceHandler.getRequestId());
186         }
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))
197             .build();
198     }
199
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())
214                         .build())
215                 .setServiceAEnd(ModelMappingUtils.createServiceAEndReroute(serviceAEnd))
216                 .setServiceZEnd(ModelMappingUtils.createServiceZEndReroute(serviceZEnd))
217                 .build();
218     }
219
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());
228             }
229             cancelResourceReserveInput.setServiceName(serviceName)
230                     .setServiceHandlerHeader(serviceHandlerHeader.build());
231             return cancelResourceReserveInput.build();
232         } else {
233             LOG.error("Service Name (common-id for Temp service) is not set");
234             return null;
235         }
236     }
237
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();
243         try {
244             notificationPublishService.putNotification(notification);
245         } catch (InterruptedException e) {
246             LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
247         }
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);
259             }
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();
264         } else {
265             configurationResponseCommon.setAckFinalIndicator(ResponseCodes.FINAL_ACK_YES)
266                     .setResponseCode(ResponseCodes.RESPONSE_FAILED).setResponseMessage("PCE failed !");
267             return new CancelResourceReserveOutputBuilder()
268                     .setConfigurationResponseCommon(configurationResponseCommon.build()).build();
269         }
270     }
271
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();
279     }
280
281     private Boolean validateParams(String serviceName, SdncRequestHeader sdncRequestHeader) {
282         boolean result = true;
283         if (!checkString(serviceName)) {
284             result = false;
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");
288             result = false;
289         }
290         return result;
291     }
292
293     private static boolean checkString(String value) {
294         return ((value != null) && (value.compareTo("") != 0));
295     }
296
297     private final class CancelResourceReserveOutputFutureCallback
298             implements FutureCallback<CancelResourceReserveOutput> {
299         private final ServiceNotificationTypes notifType;
300         private final String serviceName;
301         String message = "";
302         ServiceRpcResultSh notification = null;
303
304         private CancelResourceReserveOutputFutureCallback(ServiceNotificationTypes notifType, String serviceName) {
305             this.notifType = notifType;
306             this.serviceName = serviceName;
307         }
308
309         @Override
310         public void onSuccess(CancelResourceReserveOutput response) {
311             if (response != null) {
312                 /**
313                  * If PCE reply is received before timer expiration with a positive result, a
314                  * service is created with admin and operational status 'down'.
315                  */
316                 message = "PCE replied to CRR Request !";
317                 LOG.info("PCE replied to CRR Request : {}", response);
318                 notification =
319                         new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName(serviceName)
320                                 .setStatus(RpcStatusEx.Successful).setStatusMessage(message).build();
321                 try {
322                     notificationPublishService.putNotification(notification);
323                 } catch (InterruptedException e) {
324                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
325                 }
326             } else {
327                 message = "PCE failed ";
328                 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
329                         .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
330                 try {
331                     notificationPublishService.putNotification(notification);
332                 } catch (InterruptedException e) {
333                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
334                 }
335             }
336         }
337
338         @Override
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();
344             try {
345                 notificationPublishService.putNotification(notification);
346             } catch (InterruptedException e) {
347                 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
348             }
349         }
350     }
351
352     private final class PathComputationRequestOutputCallback implements FutureCallback<PathComputationRequestOutput> {
353         private final ServiceNotificationTypes notifType;
354         private final String serviceName;
355         String message = "";
356         ServiceRpcResultSh notification = null;
357
358         private PathComputationRequestOutputCallback(ServiceNotificationTypes notifType, String serviceName) {
359             this.notifType = notifType;
360             this.serviceName = serviceName;
361         }
362
363         @Override
364         public void onSuccess(PathComputationRequestOutput response) {
365             if (response != null) {
366                 /**
367                  * If PCE reply is received before timer expiration with a positive result, a
368                  * service is created with admin and operational status 'down'.
369                  */
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();
375                 try {
376                     notificationPublishService.putNotification(notification);
377                 } catch (InterruptedException e) {
378                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
379                 }
380             } else {
381                 message = "PCE failed ";
382                 notification = new ServiceRpcResultShBuilder().setNotificationType(notifType).setServiceName("")
383                         .setStatus(RpcStatusEx.Failed).setStatusMessage(message).build();
384                 try {
385                     notificationPublishService.putNotification(notification);
386                 } catch (InterruptedException e) {
387                     LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
388                 }
389             }
390         }
391
392         @Override
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())
398                     .build();
399             try {
400                 notificationPublishService.putNotification(notification);
401             } catch (InterruptedException e) {
402                 LOG.info(NOTIFICATION_OFFER_REJECTED_MSG, e);
403             }
404         }
405     }
406 }