Move otn link update from renderer to SH
[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.common.StringConstants;
14 import org.opendaylight.transportpce.networkmodel.service.NetworkModelService;
15 import org.opendaylight.transportpce.pce.service.PathComputationService;
16 import org.opendaylight.transportpce.servicehandler.ServiceInput;
17 import org.opendaylight.transportpce.servicehandler.service.PCEServiceWrapper;
18 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
19 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.RendererRpcResultSp;
20 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.TransportpceRendererListener;
21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.renderer.rpc.result.sp.Link;
22 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultSh;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.servicehandler.rev201125.ServiceRpcResultShBuilder;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ServiceNotificationTypes;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
28 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev210511.OtnLinkType;
29 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.PublishNotificationService;
30 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.PublishNotificationServiceBuilder;
31 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.notification.service.ServiceAEndBuilder;
32 import org.opendaylight.yang.gen.v1.nbi.notifications.rev201130.notification.service.ServiceZEndBuilder;
33 import org.opendaylight.yangtools.yang.common.Uint32;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * Calls to listen to Renderer notifications.
39  *
40  * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
41  *
42  */
43 public class RendererListenerImpl implements TransportpceRendererListener {
44
45     private static final String TOPIC = "RendererListener";
46     private static final Logger LOG = LoggerFactory.getLogger(RendererListenerImpl.class);
47     private RendererRpcResultSp serviceRpcResultSp;
48     private ServiceDataStoreOperations serviceDataStoreOperations;
49     private ServiceInput input;
50     private PCEServiceWrapper pceServiceWrapper;
51     private Boolean tempService;
52     private NotificationPublishService notificationPublishService;
53     private final NetworkModelService networkModelService;
54
55
56     public RendererListenerImpl(PathComputationService pathComputationService,
57             NotificationPublishService notificationPublishService, NetworkModelService networkModelService) {
58         this.pceServiceWrapper = new PCEServiceWrapper(pathComputationService, notificationPublishService);
59         setServiceInput(null);
60         setTempService(false);
61         this.notificationPublishService = notificationPublishService;
62         this.networkModelService = networkModelService;
63     }
64
65     @Override
66     public void onRendererRpcResultSp(RendererRpcResultSp notification) {
67         if (compareServiceRpcResultSp(notification)) {
68             LOG.warn("ServiceRpcResultSp already wired !");
69             return;
70         }
71         serviceRpcResultSp = notification;
72         int notifType = serviceRpcResultSp.getNotificationType().getIntValue();
73         LOG.info("Renderer '{}' Notification received : {}", serviceRpcResultSp.getNotificationType().getName(),
74                 notification);
75         switch (notifType) {
76             /* service-implementation-request. */
77             case 3:
78                 onServiceImplementationResult(notification);
79                 break;
80             /* service-delete. */
81             case 4:
82                 onServiceDeleteResult(notification);
83                 break;
84             default:
85                 break;
86         }
87     }
88
89     /**
90      * Process service delete result for serviceName.
91      * @param notification RendererRpcResultSp
92      */
93     private void onServiceDeleteResult(RendererRpcResultSp notification) {
94         switch (serviceRpcResultSp.getStatus()) {
95             case Successful:
96                 LOG.info("Service '{}' deleted !", notification.getServiceName());
97                 String serviceType = notification.getServiceType();
98                 switch (serviceType) {
99                     case StringConstants.SERVICE_TYPE_1GE:
100                     case StringConstants.SERVICE_TYPE_10GE:
101                     case StringConstants.SERVICE_TYPE_100GE_M:
102                         Short tribPort = Short.valueOf(notification.getAToZDirection().getMinTribSlot().getValue()
103                                 .split("\\.")[0]);
104                         Short minTribSlot = Short.valueOf(notification.getAToZDirection().getMinTribSlot().getValue()
105                                 .split("\\.")[1]);
106                         updateOtnTopology(notification.getLink(), true, notification.getServiceType(),
107                             notification.getAToZDirection().getRate(), tribPort, minTribSlot);
108                         break;
109                     case StringConstants.SERVICE_TYPE_OTU4:
110                     case StringConstants.SERVICE_TYPE_OTUC4:
111                     case StringConstants.SERVICE_TYPE_ODU4:
112                     case StringConstants.SERVICE_TYPE_ODUC4:
113                         updateOtnTopology(notification.getLink(), true, notification.getServiceType(), null, null,
114                             null);
115                         break;
116                     default:
117                         break;
118                 }
119                 break;
120             case Failed:
121                 LOG.error("Renderer service delete failed !");
122                 Services service = serviceDataStoreOperations.getService(input.getServiceName()).get();
123                 sendNbiNotification(new PublishNotificationServiceBuilder()
124                         .setServiceName(service.getServiceName())
125                         .setServiceAEnd(new ServiceAEndBuilder(service.getServiceAEnd()).build())
126                         .setServiceZEnd(new ServiceZEndBuilder(service.getServiceZEnd()).build())
127                         .setCommonId(service.getCommonId())
128                         .setConnectionType(service.getConnectionType())
129                         .setResponseFailed("Renderer service delete failed !")
130                         .setMessage("ServiceDelete request failed ...")
131                         .setOperationalState(service.getOperationalState())
132                         .setTopic(TOPIC)
133                         .build());
134                 return;
135             case Pending:
136                 LOG.warn("Renderer service delete returned a Pending RpcStatusEx code!");
137                 return;
138             default:
139                 LOG.error("Renderer service delete returned an unknown RpcStatusEx code!");
140                 return;
141         }
142         LOG.info("Service '{}' deleted !", notification.getServiceName());
143         if (this.input == null) {
144             LOG.error("ServiceInput parameter is null !");
145             return;
146         }
147         LOG.info("sending PCE cancel resource reserve for '{}'", this.input.getServiceName());
148         this.pceServiceWrapper.cancelPCEResource(this.input.getServiceName(),
149                 ServiceNotificationTypes.ServiceDeleteResult);
150         sendServiceHandlerNotification(notification, ServiceNotificationTypes.ServiceDeleteResult);
151     }
152
153     /**
154      * Process service implementation result for serviceName.
155      * @param notification RendererRpcResultSp
156      */
157     private void onServiceImplementationResult(RendererRpcResultSp notification) {
158         switch (serviceRpcResultSp.getStatus()) {
159             case Successful:
160                 onSuccededServiceImplementation(notification);
161                 break;
162             case Failed:
163                 onFailedServiceImplementation(notification.getServiceName());
164                 break;
165             case Pending:
166                 LOG.warn("Service Implementation still pending according to RpcStatusEx");
167                 break;
168             default:
169                 LOG.warn("Service Implementation has an unknown RpcStatusEx code");
170                 break;
171         }
172     }
173
174     /**
175      * Process succeeded service implementation for service.
176      * @param notification RendererRpcResultSp
177      */
178     private void onSuccededServiceImplementation(RendererRpcResultSp notification) {
179         LOG.info("Service implemented !");
180         if (serviceDataStoreOperations == null) {
181             LOG.debug("serviceDataStoreOperations is null");
182             return;
183         }
184         String serviceType = notification.getServiceType();
185         switch (serviceType) {
186             case StringConstants.SERVICE_TYPE_1GE:
187             case StringConstants.SERVICE_TYPE_10GE:
188             case StringConstants.SERVICE_TYPE_100GE_M:
189                 Short tribPort = Short.valueOf(notification.getAToZDirection().getMinTribSlot().getValue()
190                         .split("\\.")[0]);
191                 Short minTribSlot = Short.valueOf(notification.getAToZDirection().getMinTribSlot().getValue()
192                         .split("\\.")[1]);
193                 updateOtnTopology(notification.getLink(), false, notification.getServiceType(),
194                     notification.getAToZDirection().getRate(), tribPort, minTribSlot);
195                 break;
196             case StringConstants.SERVICE_TYPE_OTU4:
197             case StringConstants.SERVICE_TYPE_OTUC4:
198             case StringConstants.SERVICE_TYPE_ODU4:
199             case StringConstants.SERVICE_TYPE_ODUC4:
200                 updateOtnTopology(notification.getLink(), false, notification.getServiceType(), null, null, null);
201                 break;
202             default:
203                 break;
204         }
205         PublishNotificationServiceBuilder nbiNotificationBuilder = new PublishNotificationServiceBuilder()
206                 .setServiceName(input.getServiceName())
207                 .setServiceAEnd(new ServiceAEndBuilder(input.getServiceAEnd()).build())
208                 .setServiceZEnd(new ServiceZEndBuilder(input.getServiceZEnd()).build())
209                 .setCommonId(input.getCommonId()).setConnectionType(input.getConnectionType())
210                 .setTopic(TOPIC);
211         OperationResult operationResult;
212         String serviceTemp = "";
213         if (tempService) {
214             operationResult = this.serviceDataStoreOperations.modifyTempService(
215                     serviceRpcResultSp.getServiceName(), State.InService, AdminStates.InService);
216             serviceTemp = "Temp ";
217         } else {
218             operationResult = this.serviceDataStoreOperations.modifyService(
219                     serviceRpcResultSp.getServiceName(), State.InService, AdminStates.InService);
220         }
221         if (operationResult.isSuccess()) {
222             sendNbiNotification(nbiNotificationBuilder
223                     .setResponseFailed("")
224                     .setMessage("Service implemented !")
225                     .setOperationalState(org.opendaylight.yang.gen.v1.http
226                             .org.openroadm.common.state.types.rev181130.State.InService)
227                     .build());
228             if (!tempService) {
229                 sendServiceHandlerNotification(notification, ServiceNotificationTypes.ServiceCreateResult);
230             }
231         } else {
232             LOG.warn("{}Service status not updated in datastore !", serviceTemp);
233             sendNbiNotification(nbiNotificationBuilder
234                     .setResponseFailed(serviceTemp + "Service status not updated in datastore !")
235                     .setMessage("ServiceCreate request failed ...")
236                     .setOperationalState(org.opendaylight.yang.gen.v1.http
237                             .org.openroadm.common.state.types.rev181130.State.OutOfService)
238                     .build());
239         }
240     }
241
242     /**
243      * Create and send service handler notification.
244      * @param notification RendererRpcResultSp
245      * @param type ServiceNotificationTypes
246      */
247     private void sendServiceHandlerNotification(RendererRpcResultSp notification, ServiceNotificationTypes type) {
248         try {
249             ServiceRpcResultSh serviceHandlerNotification = new ServiceRpcResultShBuilder()
250                     .setAToZDirection(notification.getAToZDirection())
251                     .setZToADirection(notification.getZToADirection())
252                     .setServiceName(notification.getServiceName())
253                     .setStatus(notification.getStatus())
254                     .setStatusMessage(notification.getStatusMessage())
255                     .setNotificationType(type)
256                     .build();
257             LOG.debug("Service update in datastore OK, sending notification {}", serviceHandlerNotification);
258             notificationPublishService.putNotification(
259                     serviceHandlerNotification);
260         } catch (InterruptedException e) {
261             LOG.warn("Something went wrong while sending notification for service {}",
262                     serviceRpcResultSp.getServiceName(), e);
263             Thread.currentThread().interrupt();
264         }
265     }
266
267     /**
268      * Process failed service implementation for serviceName.
269      * @param serviceName String
270      */
271     private void onFailedServiceImplementation(String serviceName) {
272         LOG.error("Renderer implementation failed !");
273         Services service = serviceDataStoreOperations.getService(input.getServiceName()).get();
274         sendNbiNotification(new PublishNotificationServiceBuilder()
275                 .setServiceName(service.getServiceName())
276                 .setServiceAEnd(new ServiceAEndBuilder(service.getServiceAEnd()).build())
277                 .setServiceZEnd(new ServiceZEndBuilder(service.getServiceZEnd()).build())
278                 .setCommonId(service.getCommonId())
279                 .setConnectionType(service.getConnectionType())
280                 .setResponseFailed("Renderer implementation failed !")
281                 .setMessage("ServiceCreate request failed ...")
282                 .setOperationalState(service.getOperationalState())
283                 .setTopic(TOPIC)
284                 .build());
285         OperationResult deleteServicePathOperationResult =
286                 this.serviceDataStoreOperations.deleteServicePath(serviceName);
287         if (!deleteServicePathOperationResult.isSuccess()) {
288             LOG.warn("Service path was not removed from datastore!");
289         }
290         OperationResult deleteServiceOperationResult;
291         String serviceType = "";
292         if (tempService) {
293             deleteServiceOperationResult = this.serviceDataStoreOperations.deleteTempService(serviceName);
294             serviceType = "Temp ";
295         } else {
296             deleteServiceOperationResult = this.serviceDataStoreOperations.deleteService(serviceName);
297         }
298         if (deleteServiceOperationResult.isSuccess()) {
299             LOG.warn("{}Service was not removed from datastore!", serviceType);
300         }
301     }
302
303     @SuppressFBWarnings(
304         value = "ES_COMPARING_STRINGS_WITH_EQ",
305         justification = "false positives, not strings but real object references comparisons")
306     private Boolean compareServiceRpcResultSp(RendererRpcResultSp notification) {
307         if (serviceRpcResultSp == null) {
308             return false;
309         }
310         if (serviceRpcResultSp.getNotificationType() != notification.getNotificationType()) {
311             return false;
312         }
313         if (serviceRpcResultSp.getServiceName() != notification.getServiceName()) {
314             return false;
315         }
316         if (serviceRpcResultSp.getStatus() != notification.getStatus()) {
317             return false;
318         }
319         if (serviceRpcResultSp.getStatusMessage() != notification.getStatusMessage()) {
320             return false;
321         }
322         return true;
323     }
324
325     public void setServiceInput(ServiceInput serviceInput) {
326         this.input = serviceInput;
327     }
328
329     public void setserviceDataStoreOperations(ServiceDataStoreOperations serviceData) {
330         this.serviceDataStoreOperations = serviceData;
331     }
332
333     public void setTempService(Boolean tempService) {
334         this.tempService = tempService;
335     }
336
337     /**
338      * Send notification to NBI notification in order to publish message.
339      * @param service PublishNotificationService
340      */
341     private void sendNbiNotification(PublishNotificationService service) {
342         try {
343             notificationPublishService.putNotification(service);
344         } catch (InterruptedException e) {
345             LOG.warn("Cannot send notification to nbi", e);
346             Thread.currentThread().interrupt();
347         }
348     }
349
350     private void updateOtnTopology(Link link, boolean isDeletion, String serviceType, Uint32 rate, Short portNb,
351             Short slotNb) {
352         if (link == null) {
353             return;
354         }
355         OtnLinkType otnLinkType;
356         switch (serviceType) {
357             case StringConstants.SERVICE_TYPE_OTU4:
358                 otnLinkType = OtnLinkType.OTU4;
359                 break;
360             case StringConstants.SERVICE_TYPE_OTUC4:
361                 otnLinkType = OtnLinkType.OTUC4;
362                 break;
363             case StringConstants.SERVICE_TYPE_ODU4:
364                 otnLinkType = OtnLinkType.ODTU4;
365                 break;
366             case StringConstants.SERVICE_TYPE_ODUC4:
367                 otnLinkType = OtnLinkType.ODUC4;
368                 break;
369             default:
370                 otnLinkType = null;
371                 LOG.warn("No otn-link-type corresponds to service-type {}", serviceType);
372                 break;
373         }
374         switch (serviceType) {
375             case StringConstants.SERVICE_TYPE_OTU4:
376             case StringConstants.SERVICE_TYPE_OTUC4:
377             case StringConstants.SERVICE_TYPE_ODU4:
378             case StringConstants.SERVICE_TYPE_ODUC4:
379                 if (isDeletion) {
380                     LOG.info("updating otn-topology removing links");
381                     this.networkModelService.deleteOtnLinks(link.getATermination().getNodeId(),
382                         link.getATermination().getTpId(), link.getZTermination().getNodeId(),
383                         link.getZTermination().getTpId(), otnLinkType);
384                 } else {
385                     LOG.info("updating otn-topology adding links");
386                     this.networkModelService.createOtnLinks(link.getATermination().getNodeId(),
387                         link.getATermination().getTpId(), link.getZTermination().getNodeId(),
388                         link.getZTermination().getTpId(), otnLinkType);
389                 }
390                 break;
391             case StringConstants.SERVICE_TYPE_1GE:
392             case StringConstants.SERVICE_TYPE_10GE:
393             case StringConstants.SERVICE_TYPE_100GE_M:
394                 LOG.info("updating otn-topology node tps -tps and tpn pools");
395                 this.networkModelService.updateOtnLinks(link, rate, portNb, slotNb, isDeletion);
396                 break;
397             default:
398                 break;
399         }
400     }
401
402 }