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