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