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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
16 * ============LICENSE_END==========================================================================
18 package org.onap.ccsdk.features.sdnr.wt.devicemanager.eventdatahandler;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.TimeUnit;
23 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.DataProvider;
24 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.NetconfTimeStamp;
25 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.types.NetconfTimeStampImpl;
26 import org.onap.ccsdk.features.sdnr.wt.devicemanager.dcaeconnector.impl.DcaeForwarderInternal;
27 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.InternalDateAndTime;
28 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.InternalSeverity;
29 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.NetworkElementConnectionEntitiyUtil;
30 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.ProblemNotificationXml;
31 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.WebSocketServiceClientInternal;
32 import org.onap.ccsdk.features.sdnr.wt.devicemanager.service.EventHandlingService;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.ConnectionLogStatus;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.Connectionlog;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.ConnectionlogBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.EventlogBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.NetworkElementConnectionEntity;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.NetworkElementDeviceType;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.SourceType;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.AttributeValueChangedNotification;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.AttributeValueChangedNotificationBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ObjectCreationNotification;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ObjectCreationNotificationBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ObjectDeletionNotification;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ObjectDeletionNotificationBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ProblemNotification;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ProblemNotificationBuilder;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
56 * Responsible class for documenting changes in the ODL itself. The occurence of such an event is documented in the
57 * database and to clients. Specific example here is the registration or deregistration of a netconf device. This
58 * service has an own eventcounter to apply to the ONF Coremodel netconf behaviour.
60 * Important: Websocket notification must be the last action.
65 @SuppressWarnings("deprecation")
66 public class ODLEventListenerHandler implements EventHandlingService, AutoCloseable {
68 private static final Logger LOG = LoggerFactory.getLogger(ODLEventListenerHandler.class);
70 private static final NetconfTimeStamp NETCONFTIME_CONVERTER = NetconfTimeStampImpl.getConverter();
73 * if update NE failed delay before retrying to write data into database
75 private static final long DBWRITE_RETRY_DELAY_MS = 3000;
77 private final String ownKeyName;
78 private final WebSocketServiceClientInternal webSocketService;
79 private final DataProvider databaseService;
80 private final DcaeForwarderInternal aotsDcaeForwarder;
81 private final ExecutorService executor = Executors.newFixedThreadPool(5);
82 private int eventNumber;
85 /*---------------------------------------------------------------
90 * Create a Service to document events to clients and within a database
92 * @param ownKeyName The name of this service, that is used in the database as identification key.
93 * @param webSocketService service to direct messages to clients
94 * @param databaseService service to write to the database
95 * @param dcaeForwarder to deliver problems to external service
97 public ODLEventListenerHandler(String ownKeyName, WebSocketServiceClientInternal webSocketService,
98 DataProvider databaseService, DcaeForwarderInternal dcaeForwarder) {
101 this.ownKeyName = ownKeyName;
102 this.webSocketService = webSocketService;
104 this.databaseService = databaseService;
105 this.aotsDcaeForwarder = dcaeForwarder;
107 this.eventNumber = 0;
110 /*---------------------------------------------------------------
111 * Handling of ODL Controller events
115 * (NonConnected) A registration after creation of a mountpoint occured
117 * @param registrationName of device (mountpoint name)
118 * @param nNode with mountpoint data
121 public void registration(String registrationName, NetconfNode nNode) {
123 DateAndTime ts = NETCONFTIME_CONVERTER.getTimeStamp();
124 ObjectCreationNotification notification = new ObjectCreationNotificationBuilder()
125 .setObjectIdRef(registrationName).setCounter(popEvntNumber()).setTimeStamp(ts).build();
126 Connectionlog log = new ConnectionlogBuilder().setNodeId(registrationName)
127 .setStatus(ConnectionLogStatus.Mounted).setTimestamp(ts).build();
128 NetworkElementConnectionEntity e =
129 NetworkElementConnectionEntitiyUtil.getNetworkConnection(registrationName, nNode);
130 LOG.debug("registration networkelement-connection for {} with status {}", registrationName, e.getStatus());
132 // Write first to prevent missing entries
133 databaseService.updateNetworkConnection22(e, registrationName);
134 databaseService.writeConnectionLog(log);
135 webSocketService.sendViaWebsockets(new NodeId(ownKeyName), notification, ObjectCreationNotification.QNAME,
136 NetconfTimeStampImpl.getConverter().getTimeStamp());
140 * (Connected) mountpoint state moves to connected
142 * @param mountpointNodeName uuid that is nodeId or mountpointId
143 * @param deviceType according to assessement
146 public void connectIndication(String mountpointNodeName, NetworkElementDeviceType deviceType) {
148 // Write first to prevent missing entries
149 LOG.debug("updating networkelement-connection devicetype for {} with {}", mountpointNodeName, deviceType);
150 NetworkElementConnectionEntity e =
151 NetworkElementConnectionEntitiyUtil.getNetworkConnectionDeviceTpe(deviceType);
152 //if updating db entry for ne connection fails retry later on (due elasticsearch max script executions error)
153 if (!databaseService.updateNetworkConnectionDeviceType(e, mountpointNodeName)) {
154 this.updateNeConnectionRetryWithDelay(e, mountpointNodeName);
156 DateAndTime ts = NETCONFTIME_CONVERTER.getTimeStamp();
157 AttributeValueChangedNotification notification = new AttributeValueChangedNotificationBuilder()
158 .setCounter(popEvntNumber()).setTimeStamp(ts).setObjectIdRef(mountpointNodeName)
159 .setAttributeName("deviceType").setNewValue(deviceType.name()).build();
160 webSocketService.sendViaWebsockets(new NodeId(ownKeyName), notification, AttributeValueChangedNotification.QNAME, ts);
164 * (NonConnected) mountpoint state changed.
166 * @param mountpointNodeName nodeid
167 * @param netconfNode node
169 public void onStateChangeIndication(String mountpointNodeName, NetconfNode netconfNode) {
170 LOG.debug("mountpoint state changed indication for {}", mountpointNodeName);
171 ConnectionStatus csts = netconfNode.getConnectionStatus();
172 this.updateRegistration(mountpointNodeName, ConnectionStatus.class.getSimpleName(),
173 csts != null ? csts.getName() : "null", netconfNode);
178 * (NonConnected) A deregistration after removal of a mountpoint occured.
180 * @param registrationName Name of the event that is used as key in the database.
182 @SuppressWarnings("null")
184 public void deRegistration(String registrationName) {
186 DateAndTime ts = NETCONFTIME_CONVERTER.getTimeStamp();
187 ObjectDeletionNotification notification = new ObjectDeletionNotificationBuilder().setCounter(popEvntNumber())
188 .setTimeStamp(ts).setObjectIdRef(registrationName).build();
189 Connectionlog log = new ConnectionlogBuilder().setNodeId(registrationName)
190 .setStatus(ConnectionLogStatus.Unmounted).setTimestamp(ts).build();
191 // Write first to prevent missing entries
192 databaseService.removeNetworkConnection(registrationName);
193 databaseService.writeConnectionLog(log);
194 webSocketService.sendViaWebsockets(new NodeId(registrationName), notification, ObjectDeletionNotification.QNAME, ts);
199 * Mountpoint state changed .. from connected -> connecting or unable-to-connect or vis-e-versa.
201 * @param registrationName Name of the event that is used as key in the database.
204 public void updateRegistration(String registrationName, String attribute, String attributeNewValue,
206 DateAndTime ts = NETCONFTIME_CONVERTER.getTimeStamp();
207 AttributeValueChangedNotification notification = new AttributeValueChangedNotificationBuilder()
208 .setCounter(popEvntNumber()).setTimeStamp(ts).setObjectIdRef(registrationName)
209 .setAttributeName(attribute).setNewValue(attributeNewValue).build();
210 Connectionlog log = new ConnectionlogBuilder().setNodeId(registrationName).setStatus(getStatus(attributeNewValue))
211 .setTimestamp(ts).build();
212 NetworkElementConnectionEntity e =
213 NetworkElementConnectionEntitiyUtil.getNetworkConnection(registrationName, nNode);
214 LOG.debug("updating networkelement-connection for {} with status {}", registrationName, e.getStatus());
216 //if updating db entry for ne connection fails retry later on (due elasticsearch max script executions error)
217 if (!databaseService.updateNetworkConnection22(e, registrationName)) {
218 this.updateNeConnectionRetryWithDelay(nNode, registrationName);
220 databaseService.writeConnectionLog(log);
221 webSocketService.sendViaWebsockets(new NodeId(ownKeyName), notification, AttributeValueChangedNotification.QNAME, ts);
225 private void updateNeConnectionRetryWithDelay(NetconfNode nNode, String registrationName) {
226 LOG.debug("try to rewrite networkelement-connection in {} for node {}", DBWRITE_RETRY_DELAY_MS,
228 executor.execute(new DelayedThread(DBWRITE_RETRY_DELAY_MS) {
232 databaseService.updateNetworkConnection22(
233 NetworkElementConnectionEntitiyUtil.getNetworkConnection(registrationName, nNode),
239 private void updateNeConnectionRetryWithDelay(NetworkElementConnectionEntity e, String registrationName) {
240 LOG.debug("try to rewrite networkelement-connection in {} for node {}", DBWRITE_RETRY_DELAY_MS,
242 executor.execute(new DelayedThread(DBWRITE_RETRY_DELAY_MS) {
246 databaseService.updateNetworkConnection22(e, registrationName);
252 * At a mountpoint a problem situation is indicated
254 * @param registrationName indicating object within SDN controller, normally the mountpointName
255 * @param problemName that changed
256 * @param problemSeverity of the problem according to NETCONF/YANG
259 public void onProblemNotification(String registrationName, String problemName, InternalSeverity problemSeverity) {
260 LOG.debug("Got event of {} {} {}", registrationName, problemName, problemSeverity);
263 ProblemNotificationXml notificationXml =
264 new ProblemNotificationXml(ownKeyName, registrationName, problemName, problemSeverity,
265 // popEvntNumberAsString(), InternalDateAndTime.TESTPATTERN );
266 popEvntNumber(), InternalDateAndTime.valueOf(NETCONFTIME_CONVERTER.getTimeStamp()));
267 DateAndTime ts = NETCONFTIME_CONVERTER.getTimeStamp();
268 ProblemNotification notification =
269 new ProblemNotificationBuilder().setObjectIdRef(registrationName).setCounter(popEvntNumber())
270 .setProblem(problemName).setSeverity(InternalSeverity.toYang(problemSeverity)).build();
271 databaseService.writeFaultLog(notificationXml.getFaultlog(SourceType.Controller));
272 databaseService.updateFaultCurrent(notificationXml.getFaultcurrent());
274 aotsDcaeForwarder.sendProblemNotificationUsingMaintenanceFilter(ownKeyName, notificationXml);
276 webSocketService.sendViaWebsockets(new NodeId(ownKeyName), notification, ProblemNotification.QNAME, ts);
280 public void writeEventLog(String objectId, String msg, String value) {
282 LOG.debug("Got startComplete");
283 EventlogBuilder eventlogBuilder = new EventlogBuilder();
284 eventlogBuilder.setNodeId(ownKeyName).setTimestamp(new DateAndTime(NETCONFTIME_CONVERTER.getTimeStamp()))
285 .setObjectId(objectId).setAttributeName(msg).setNewValue(value).setCounter(popEvntNumber())
286 .setSourceType(SourceType.Controller);
287 databaseService.writeEventLog(eventlogBuilder.build());
291 /*---------------------------------------------
292 * Handling of ODL Controller events
296 * Called on exit to remove everything for a node from the current list.
298 * @param nodeName to remove all problems for
299 * @return Number of deleted objects
301 public int removeAllCurrentProblemsOfNode(String nodeName) {
302 return databaseService.clearFaultsCurrentOfNodeWithObjectId(ownKeyName, nodeName);
305 /*---------------------------------------------------------------
310 * @return the ownKeyName
312 public String getOwnKeyName() {
317 public void close() throws Exception {
319 executor.awaitTermination(DBWRITE_RETRY_DELAY_MS * 3, TimeUnit.SECONDS);
322 /*---------------------------------------------------------------
325 private Integer popEvntNumber() {
326 return eventNumber++;
329 private static ConnectionLogStatus getStatus(String newValue) {
331 if (newValue.equals(ConnectionStatus.Connected.getName())) {
332 return ConnectionLogStatus.Connected;
334 } else if (newValue.equals(ConnectionStatus.Connecting.getName())) {
335 return ConnectionLogStatus.Connecting;
337 } else if (newValue.equals(ConnectionStatus.UnableToConnect.getName())) {
338 return ConnectionLogStatus.UnableToConnect;
341 return ConnectionLogStatus.Undefined;
344 private class DelayedThread extends Thread {
345 private final long delay;
347 public DelayedThread(long delayms) {
348 this.delay = delayms;
354 Thread.sleep(this.delay);
355 } catch (InterruptedException e) {
356 Thread.currentThread().interrupt();