fb84bfc1bf24603e91c40e1f6f92a0c8a1934c8d
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 package org.onap.ccsdk.features.sdnr.wt.devicemanager.eventdatahandler;
19
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.TimeUnit;
23
24 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.DataProvider;
25 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.NetconfTimeStamp;
26 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.types.NetconfTimeStampImpl;
27 import org.onap.ccsdk.features.sdnr.wt.devicemanager.dcaeconnector.impl.DcaeForwarderInternal;
28 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.InternalDateAndTime;
29 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.InternalSeverity;
30 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.NetworkElementConnectionEntitiyUtil;
31 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.AttributeValueChangedNotificationXml;
32 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.ObjectCreationNotificationXml;
33 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.ObjectDeletionNotificationXml;
34 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.ProblemNotificationXml;
35 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.WebSocketServiceClientInternal;
36 import org.onap.ccsdk.features.sdnr.wt.devicemanager.service.EventHandlingService;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.EventlogBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.NetworkElementConnectionEntity;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.NetworkElementDeviceType;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.SourceType;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * Responsible class for documenting changes in the ODL itself. The occurence of such an event is documented in the
49  * database and to clients. Specific example here is the registration or deregistration of a netconf device. This
50  * service has an own eventcounter to apply to the ONF Coremodel netconf behaviour.
51  *
52  * Important: Websocket notification must be the last action.
53  *
54  * @author herbert
55  */
56
57 @SuppressWarnings("deprecation")
58 public class ODLEventListenerHandler implements EventHandlingService, AutoCloseable {
59
60     private static final Logger LOG = LoggerFactory.getLogger(ODLEventListenerHandler.class);
61
62     private static final NetconfTimeStamp NETCONFTIME_CONVERTER = NetconfTimeStampImpl.getConverter();
63
64     /**
65      * if update NE failed delay before retrying to write data into database
66      */
67     private static final long DBWRITE_RETRY_DELAY_MS = 3000;
68
69     private final String ownKeyName;
70     private final WebSocketServiceClientInternal webSocketService;
71     private final DataProvider databaseService;
72     private final DcaeForwarderInternal aotsDcaeForwarder;
73     private final ExecutorService executor = Executors.newFixedThreadPool(5);
74     private int eventNumber;
75
76
77     /*---------------------------------------------------------------
78      * Construct
79      */
80
81     /**
82      * Create a Service to document events to clients and within a database
83      *
84      * @param ownKeyName The name of this service, that is used in the database as identification key.
85      * @param webSocketService service to direct messages to clients
86      * @param databaseService service to write to the database
87      * @param dcaeForwarder to deliver problems to external service
88      */
89     public ODLEventListenerHandler(String ownKeyName, WebSocketServiceClientInternal webSocketService,
90             DataProvider databaseService, DcaeForwarderInternal dcaeForwarder) {
91         super();
92
93         this.ownKeyName = ownKeyName;
94         this.webSocketService = webSocketService;
95
96         this.databaseService = databaseService;
97         this.aotsDcaeForwarder = dcaeForwarder;
98
99         this.eventNumber = 0;
100     }
101
102     /*---------------------------------------------------------------
103      * Handling of ODL Controller events
104      */
105
106     /**
107      * (NonConnected) A registration after creation of a mountpoint occured
108      * 
109      * @param registrationName of device (mountpoint name)
110      * @param nNode with mountpoint data
111      */
112     @Override
113     public void registration(String registrationName, NetconfNode nNode) {
114
115         ObjectCreationNotificationXml cNotificationXml = new ObjectCreationNotificationXml(ownKeyName, popEvntNumber(),
116                 InternalDateAndTime.valueOf(NETCONFTIME_CONVERTER.getTimeStamp()), registrationName);
117         NetworkElementConnectionEntity e =
118                 NetworkElementConnectionEntitiyUtil.getNetworkConnection(registrationName, nNode);
119         LOG.debug("registration networkelement-connection for {} with status {}", registrationName, e.getStatus());
120
121         // Write first to prevent missing entries
122         databaseService.updateNetworkConnection22(e, registrationName);
123         databaseService.writeConnectionLog(cNotificationXml.getConnectionlogEntity());
124         webSocketService.sendViaWebsockets(registrationName, cNotificationXml);
125     }
126
127     /**
128      * (Connected) mountpoint state moves to connected
129      * 
130      * @param mountpointNodeName uuid that is nodeId or mountpointId
131      * @param deviceType according to assessement
132      */
133     @Override
134     public void connectIndication(String mountpointNodeName, NetworkElementDeviceType deviceType) {
135
136         // Write first to prevent missing entries
137         LOG.debug("updating networkelement-connection devicetype for {} with {}", mountpointNodeName, deviceType);
138         NetworkElementConnectionEntity e =
139                 NetworkElementConnectionEntitiyUtil.getNetworkConnectionDeviceTpe(deviceType);
140         //if updating db entry for ne connection fails retry later on (due elasticsearch max script executions error)
141         if (!databaseService.updateNetworkConnectionDeviceType(e, mountpointNodeName)) {
142             this.updateNeConnectionRetryWithDelay(e, mountpointNodeName);
143         }
144
145         AttributeValueChangedNotificationXml notificationXml = new AttributeValueChangedNotificationXml(ownKeyName,
146                 popEvntNumber(), InternalDateAndTime.valueOf(NETCONFTIME_CONVERTER.getTimeStamp()), mountpointNodeName,
147                 "deviceType", deviceType.name());
148         webSocketService.sendViaWebsockets(mountpointNodeName, notificationXml);
149     }
150
151     /**
152      * (NonConnected) mountpoint state changed.
153      * 
154      * @param mountpointNodeName nodeid
155      * @param netconfNode node
156      */
157     public void onStateChangeIndication(String mountpointNodeName, NetconfNode netconfNode) {
158         LOG.debug("mountpoint state changed indication for {}", mountpointNodeName);
159         ConnectionStatus csts = netconfNode.getConnectionStatus();
160         this.updateRegistration(mountpointNodeName, ConnectionStatus.class.getSimpleName(),
161                 csts != null ? csts.getName() : "null", netconfNode);
162
163     }
164
165     /**
166      * (NonConnected) A deregistration after removal of a mountpoint occured.
167      * 
168      * @param registrationName Name of the event that is used as key in the database.
169      */
170     @SuppressWarnings("null")
171     @Override
172     public void deRegistration(String registrationName) {
173
174         ObjectDeletionNotificationXml dNotificationXml = new ObjectDeletionNotificationXml(ownKeyName, popEvntNumber(),
175                 InternalDateAndTime.valueOf(NETCONFTIME_CONVERTER.getTimeStamp()), registrationName);
176
177         // Write first to prevent missing entries
178         databaseService.removeNetworkConnection(registrationName);
179         databaseService.writeConnectionLog(dNotificationXml.getConnectionlogEntity());
180         webSocketService.sendViaWebsockets(registrationName, dNotificationXml);
181
182     }
183
184     /**
185      * Mountpoint state changed .. from connected -> connecting or unable-to-connect or vis-e-versa.
186      * 
187      * @param registrationName Name of the event that is used as key in the database.
188      */
189     @Override
190     public void updateRegistration(String registrationName, String attribute, String attributeNewValue,
191             NetconfNode nNode) {
192         AttributeValueChangedNotificationXml notificationXml = new AttributeValueChangedNotificationXml(ownKeyName,
193                 popEvntNumber(), InternalDateAndTime.valueOf(NETCONFTIME_CONVERTER.getTimeStamp()), registrationName,
194                 attribute, attributeNewValue);
195         NetworkElementConnectionEntity e =
196                 NetworkElementConnectionEntitiyUtil.getNetworkConnection(registrationName, nNode);
197         LOG.debug("updating networkelement-connection for {} with status {}", registrationName, e.getStatus());
198
199         //if updating db entry for ne connection fails retry later on (due elasticsearch max script executions error)
200         if (!databaseService.updateNetworkConnection22(e, registrationName)) {
201             this.updateNeConnectionRetryWithDelay(nNode, registrationName);
202         }
203         databaseService.writeConnectionLog(notificationXml.getConnectionlogEntity());
204         webSocketService.sendViaWebsockets(registrationName, notificationXml);
205     }
206
207     private void updateNeConnectionRetryWithDelay(NetconfNode nNode, String registrationName) {
208         LOG.debug("try to rewrite networkelement-connection in {} for node {}", DBWRITE_RETRY_DELAY_MS,
209                 registrationName);
210         executor.execute(new DelayedThread(DBWRITE_RETRY_DELAY_MS) {
211             @Override
212             public void run() {
213                 super.run();
214                 databaseService.updateNetworkConnection22(
215                         NetworkElementConnectionEntitiyUtil.getNetworkConnection(registrationName, nNode),
216                         registrationName);
217             }
218         });
219     }
220
221     private void updateNeConnectionRetryWithDelay(NetworkElementConnectionEntity e, String registrationName) {
222         LOG.debug("try to rewrite networkelement-connection in {} for node {}", DBWRITE_RETRY_DELAY_MS,
223                 registrationName);
224         executor.execute(new DelayedThread(DBWRITE_RETRY_DELAY_MS) {
225             @Override
226             public void run() {
227                 super.run();
228                 databaseService.updateNetworkConnection22(e, registrationName);
229             }
230         });
231     }
232
233     /**
234      * At a mountpoint a problem situation is indicated
235      *
236      * @param registrationName indicating object within SDN controller, normally the mountpointName
237      * @param problemName that changed
238      * @param problemSeverity of the problem according to NETCONF/YANG
239      */
240
241     public void onProblemNotification(String registrationName, String problemName, InternalSeverity problemSeverity) {
242         LOG.debug("Got event of {} {} {}", registrationName, problemName, problemSeverity);
243         // notification
244
245         ProblemNotificationXml notificationXml =
246                 new ProblemNotificationXml(ownKeyName, registrationName, problemName, problemSeverity,
247                         // popEvntNumberAsString(), InternalDateAndTime.TESTPATTERN );
248                         popEvntNumber(), InternalDateAndTime.valueOf(NETCONFTIME_CONVERTER.getTimeStamp()));
249
250         databaseService.writeFaultLog(notificationXml.getFaultlog(SourceType.Controller));
251         databaseService.updateFaultCurrent(notificationXml.getFaultcurrent());
252
253         aotsDcaeForwarder.sendProblemNotificationUsingMaintenanceFilter(ownKeyName, notificationXml);
254
255         webSocketService.sendViaWebsockets(registrationName, notificationXml);
256     }
257
258     @Override
259     public void writeEventLog(String objectId, String msg, String value) {
260
261         LOG.debug("Got startComplete");
262         EventlogBuilder eventlogBuilder = new EventlogBuilder();
263         eventlogBuilder.setNodeId(ownKeyName).setTimestamp(new DateAndTime(NETCONFTIME_CONVERTER.getTimeStamp()))
264                 .setObjectId(objectId).setAttributeName(msg).setNewValue(value).setCounter(popEvntNumber())
265                 .setSourceType(SourceType.Controller);
266         databaseService.writeEventLog(eventlogBuilder.build());
267
268     }
269
270     /*---------------------------------------------
271      * Handling of ODL Controller events
272      */
273
274     /**
275      * Called on exit to remove everything for a node from the current list.
276      *
277      * @param nodeName to remove all problems for
278      * @return Number of deleted objects
279      */
280     public int removeAllCurrentProblemsOfNode(String nodeName) {
281         return databaseService.clearFaultsCurrentOfNodeWithObjectId(ownKeyName, nodeName);
282     }
283
284     /*---------------------------------------------------------------
285      * Get/Set
286      */
287
288     /**
289      * @return the ownKeyName
290      */
291     public String getOwnKeyName() {
292         return ownKeyName;
293     }
294
295     @Override
296     public void close() throws Exception {
297         executor.shutdown();
298         executor.awaitTermination(DBWRITE_RETRY_DELAY_MS * 3, TimeUnit.SECONDS);
299     }
300
301     /*---------------------------------------------------------------
302      * Private
303      */
304     private Integer popEvntNumber() {
305         return eventNumber++;
306     }
307
308     private class DelayedThread extends Thread {
309         private final long delay;
310
311         public DelayedThread(long delayms) {
312             this.delay = delayms;
313         }
314
315         @Override
316         public void run() {
317             try {
318                 Thread.sleep(this.delay);
319             } catch (InterruptedException e) {
320                 Thread.currentThread().interrupt();
321             }
322         }
323     }
324 }