1ac66d413ba0a4928535cb6b31bda340f72358f4
[transportpce.git] / servicehandler / src / main / java / org / opendaylight / transportpce / servicehandler / listeners / RendererListenerImpl.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.listeners;
9
10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
11 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
12 import org.opendaylight.transportpce.common.OperationResult;
13 import org.opendaylight.transportpce.pce.service.PathComputationService;
14 import org.opendaylight.transportpce.servicehandler.ServiceInput;
15 import org.opendaylight.transportpce.servicehandler.service.PCEServiceWrapper;
16 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
17 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.RendererRpcResultSp;
18 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.TransportpceRendererListener;
19 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultSh;
20 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultShBuilder;
21 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ServiceNotificationTypes;
22 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
25 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.PublishNotificationService;
26 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.PublishNotificationServiceBuilder;
27 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.notification.service.ServiceAEndBuilder;
28 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.notification.service.ServiceZEndBuilder;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * Calls to listen to Renderer notifications.
34  *
35  * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
36  *
37  */
38 public class RendererListenerImpl implements TransportpceRendererListener {
39
40     private static final String TOPIC = "RendererListener";
41     private static final Logger LOG = LoggerFactory.getLogger(RendererListenerImpl.class);
42     private RendererRpcResultSp serviceRpcResultSp;
43     private ServiceDataStoreOperations serviceDataStoreOperations;
44     private ServiceInput input;
45     private PCEServiceWrapper pceServiceWrapper;
46     private Boolean tempService;
47     private NotificationPublishService notificationPublishService;
48
49     public RendererListenerImpl(PathComputationService pathComputationService,
50             NotificationPublishService notificationPublishService) {
51         this.pceServiceWrapper = new PCEServiceWrapper(pathComputationService, notificationPublishService);
52         setServiceInput(null);
53         setTempService(false);
54         this.notificationPublishService = notificationPublishService;
55     }
56
57     @Override
58     public void onRendererRpcResultSp(RendererRpcResultSp notification) {
59         if (compareServiceRpcResultSp(notification)) {
60             LOG.warn("ServiceRpcResultSp already wired !");
61             return;
62         }
63         serviceRpcResultSp = notification;
64         int notifType = serviceRpcResultSp.getNotificationType().getIntValue();
65         LOG.info("Renderer '{}' Notification received : {}", serviceRpcResultSp.getNotificationType().getName(),
66                 notification);
67         switch (notifType) {
68             /* service-implementation-request. */
69             case 3:
70                 onServiceImplementationResult(notification);
71                 break;
72             /* service-delete. */
73             case 4:
74                 onServiceDeleteResult(notification);
75                 break;
76             default:
77                 break;
78         }
79     }
80
81     /**
82      * Process service delete result for serviceName.
83      * @param notification RendererRpcResultSp
84      */
85     private void onServiceDeleteResult(RendererRpcResultSp notification) {
86         switch (serviceRpcResultSp.getStatus()) {
87             case Successful:
88                 LOG.info("Service '{}' deleted !", notification.getServiceName());
89                 break;
90             case Failed:
91                 LOG.error("Renderer service delete failed !");
92                 Services service = serviceDataStoreOperations.getService(input.getServiceName()).get();
93                 sendNbiNotification(new PublishNotificationServiceBuilder()
94                         .setServiceName(service.getServiceName())
95                         .setServiceAEnd(new ServiceAEndBuilder(service.getServiceAEnd()).build())
96                         .setServiceZEnd(new ServiceZEndBuilder(service.getServiceZEnd()).build())
97                         .setCommonId(service.getCommonId())
98                         .setConnectionType(service.getConnectionType())
99                         .setResponseFailed("Renderer service delete failed !")
100                         .setMessage("ServiceDelete request failed ...")
101                         .setOperationalState(service.getOperationalState())
102                         .setTopic(TOPIC)
103                         .build());
104                 return;
105             case Pending:
106                 LOG.warn("Renderer service delete returned a Pending RpcStatusEx code!");
107                 return;
108             default:
109                 LOG.error("Renderer service delete returned an unknown RpcStatusEx code!");
110                 return;
111         }
112         LOG.info("Service '{}' deleted !", notification.getServiceName());
113         if (this.input == null) {
114             LOG.error("ServiceInput parameter is null !");
115             return;
116         }
117         LOG.info("sending PCE cancel resource reserve for '{}'", this.input.getServiceName());
118         this.pceServiceWrapper.cancelPCEResource(this.input.getServiceName(),
119                 ServiceNotificationTypes.ServiceDeleteResult);
120         sendServiceHandlerNotification(notification, ServiceNotificationTypes.ServiceDeleteResult);
121     }
122
123     /**
124      * Process service implementation result for serviceName.
125      * @param notification RendererRpcResultSp
126      */
127     private void onServiceImplementationResult(RendererRpcResultSp notification) {
128         switch (serviceRpcResultSp.getStatus()) {
129             case Successful:
130                 onSuccededServiceImplementation(notification);
131                 break;
132             case Failed:
133                 onFailedServiceImplementation(notification.getServiceName());
134                 break;
135             case Pending:
136                 LOG.warn("Service Implementation still pending according to RpcStatusEx");
137                 break;
138             default:
139                 LOG.warn("Service Implementation has an unknown RpcStatusEx code");
140                 break;
141         }
142     }
143
144     /**
145      * Process succeeded service implementation for service.
146      * @param notification RendererRpcResultSp
147      */
148     private void onSuccededServiceImplementation(RendererRpcResultSp notification) {
149         LOG.info("Service implemented !");
150         if (serviceDataStoreOperations == null) {
151             LOG.debug("serviceDataStoreOperations is null");
152             return;
153         }
154         PublishNotificationServiceBuilder nbiNotificationBuilder = new PublishNotificationServiceBuilder()
155                 .setServiceName(input.getServiceName())
156                 .setServiceAEnd(new ServiceAEndBuilder(input.getServiceAEnd()).build())
157                 .setServiceZEnd(new ServiceZEndBuilder(input.getServiceZEnd()).build())
158                 .setCommonId(input.getCommonId()).setConnectionType(input.getConnectionType())
159                 .setTopic(TOPIC);
160         OperationResult operationResult;
161         String serviceType = "";
162         if (tempService) {
163             operationResult = this.serviceDataStoreOperations.modifyTempService(
164                     serviceRpcResultSp.getServiceName(), State.InService, AdminStates.InService);
165             serviceType = "Temp ";
166         } else {
167             operationResult = this.serviceDataStoreOperations.modifyService(
168                     serviceRpcResultSp.getServiceName(), State.InService, AdminStates.InService);
169         }
170         if (operationResult.isSuccess()) {
171             sendNbiNotification(nbiNotificationBuilder
172                     .setResponseFailed("")
173                     .setMessage("Service implemented !")
174                     .setOperationalState(org.opendaylight.yang.gen.v1.http
175                             .org.openroadm.common.state.types.rev181130.State.InService)
176                     .build());
177             if (!tempService) {
178                 sendServiceHandlerNotification(notification, ServiceNotificationTypes.ServiceCreateResult);
179             }
180         } else {
181             LOG.warn("{}Service status not updated in datastore !", serviceType);
182             sendNbiNotification(nbiNotificationBuilder
183                     .setResponseFailed(serviceType + "Service status not updated in datastore !")
184                     .setMessage("ServiceCreate request failed ...")
185                     .setOperationalState(org.opendaylight.yang.gen.v1.http
186                             .org.openroadm.common.state.types.rev181130.State.OutOfService)
187                     .build());
188         }
189     }
190
191     /**
192      * Create and send service handler notification.
193      * @param notification RendererRpcResultSp
194      * @param type ServiceNotificationTypes
195      */
196     private void sendServiceHandlerNotification(RendererRpcResultSp notification, ServiceNotificationTypes type) {
197         try {
198             ServiceRpcResultSh serviceHandlerNotification = new ServiceRpcResultShBuilder()
199                     .setAToZDirection(notification.getAToZDirection())
200                     .setZToADirection(notification.getZToADirection())
201                     .setServiceName(notification.getServiceName())
202                     .setStatus(notification.getStatus())
203                     .setStatusMessage(notification.getStatusMessage())
204                     .setNotificationType(type)
205                     .build();
206             LOG.debug("Service update in datastore OK, sending notification {}", serviceHandlerNotification);
207             notificationPublishService.putNotification(
208                     serviceHandlerNotification);
209         } catch (InterruptedException e) {
210             LOG.warn("Something went wrong while sending notification for service {}",
211                     serviceRpcResultSp.getServiceName(), e);
212             Thread.currentThread().interrupt();
213         }
214     }
215
216     /**
217      * Process failed service implementation for serviceName.
218      * @param serviceName String
219      */
220     private void onFailedServiceImplementation(String serviceName) {
221         LOG.error("Renderer implementation failed !");
222         Services service = serviceDataStoreOperations.getService(input.getServiceName()).get();
223         sendNbiNotification(new PublishNotificationServiceBuilder()
224                 .setServiceName(service.getServiceName())
225                 .setServiceAEnd(new ServiceAEndBuilder(service.getServiceAEnd()).build())
226                 .setServiceZEnd(new ServiceZEndBuilder(service.getServiceZEnd()).build())
227                 .setCommonId(service.getCommonId())
228                 .setConnectionType(service.getConnectionType())
229                 .setResponseFailed("Renderer implementation failed !")
230                 .setMessage("ServiceCreate request failed ...")
231                 .setOperationalState(service.getOperationalState())
232                 .setTopic(TOPIC)
233                 .build());
234         OperationResult deleteServicePathOperationResult =
235                 this.serviceDataStoreOperations.deleteServicePath(serviceName);
236         if (!deleteServicePathOperationResult.isSuccess()) {
237             LOG.warn("Service path was not removed from datastore!");
238         }
239         OperationResult deleteServiceOperationResult;
240         String serviceType = "";
241         if (tempService) {
242             deleteServiceOperationResult = this.serviceDataStoreOperations.deleteTempService(serviceName);
243             serviceType = "Temp ";
244         } else {
245             deleteServiceOperationResult = this.serviceDataStoreOperations.deleteService(serviceName);
246         }
247         if (deleteServiceOperationResult.isSuccess()) {
248             LOG.warn("{}Service was not removed from datastore!", serviceType);
249         }
250     }
251
252     @SuppressFBWarnings(
253         value = "ES_COMPARING_STRINGS_WITH_EQ",
254         justification = "false positives, not strings but real object references comparisons")
255     private Boolean compareServiceRpcResultSp(RendererRpcResultSp notification) {
256         if (serviceRpcResultSp == null) {
257             return false;
258         }
259         if (serviceRpcResultSp.getNotificationType() != notification.getNotificationType()) {
260             return false;
261         }
262         if (serviceRpcResultSp.getServiceName() != notification.getServiceName()) {
263             return false;
264         }
265         if (serviceRpcResultSp.getStatus() != notification.getStatus()) {
266             return false;
267         }
268         if (serviceRpcResultSp.getStatusMessage() != notification.getStatusMessage()) {
269             return false;
270         }
271         return true;
272     }
273
274     public void setServiceInput(ServiceInput serviceInput) {
275         this.input = serviceInput;
276     }
277
278     public void setserviceDataStoreOperations(ServiceDataStoreOperations serviceData) {
279         this.serviceDataStoreOperations = serviceData;
280     }
281
282     public void setTempService(Boolean tempService) {
283         this.tempService = tempService;
284     }
285
286     /**
287      * Send notification to NBI notification in order to publish message.
288      * @param service PublishNotificationService
289      */
290     private void sendNbiNotification(PublishNotificationService service) {
291         try {
292             notificationPublishService.putNotification(service);
293         } catch (InterruptedException e) {
294             LOG.warn("Cannot send notification to nbi", e);
295             Thread.currentThread().interrupt();
296         }
297     }
298 }