Merge "YANG Model update for A1 Adapter"
[ccsdk/features.git] / sdnr / wt / devicemanager / provider / src / main / java / org / onap / ccsdk / features / sdnr / wt / devicemanager / devicemonitor / impl / DeviceMonitorTask.java
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 /**
19  * @author herbert
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.devicemanager.devicemonitor.impl;
23
24 import java.util.Collections;
25 import java.util.EnumSet;
26 import java.util.Set;
27 import java.util.concurrent.ScheduledExecutorService;
28 import java.util.concurrent.ScheduledFuture;
29 import java.util.concurrent.TimeUnit;
30 import org.eclipse.jdt.annotation.NonNull;
31 import org.eclipse.jdt.annotation.Nullable;
32 import org.onap.ccsdk.features.sdnr.wt.base.netconf.util.NetconfTimeStamp;
33 import org.onap.ccsdk.features.sdnr.wt.devicemanager.DeviceMonitoredNe;
34 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.handler.ODLEventListenerHandler;
35 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.InternalSeverity;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public class DeviceMonitorTask implements Runnable {
40
41     private static final Logger LOG = LoggerFactory.getLogger(DeviceMonitorTask.class);
42     private static final String LOGMARKER = "DMTick";
43     private static final NetconfTimeStamp NETCONFTIME_CONVERTER = NetconfTimeStamp.getConverter();
44
45     private final String mountPointName;
46     private final ODLEventListenerHandler odlEventListener;
47     private final Checker checkConnectionToMediator;
48     private final Checker checkConnectionToNe;
49
50     private int tickCounter; //Added for each tick. Not relevant for internal status
51
52     private ScheduledFuture<?> taskHandle;
53     private final Object lockNe = new Object();    //USe top lock access to member ne
54     private @Nullable DeviceMonitoredNe ne; //Indication if in status connect or disconnect
55     private @NonNull Boolean mountpointConnectingStateSupervision; //Indication of mountpoint supervision
56
57     private final Object lockDisconnectSupervisionTickout = new Object();
58     private Integer disconnectSupervisionTickout; //Tickcounter of task ticks for "not connected indication"
59     private Set<DeviceMonitorProblems> currentProblems; //List with actual problems. Synchronized by itself
60
61     /*------------------------------------------------------------
62      * Construction
63      */
64
65     /**
66      * Setup monitoring task
67      * @param mountPointName to monitor
68      * @param odlEventListener to forward problems to
69      */
70     public DeviceMonitorTask(String mountPointName, ODLEventListenerHandler odlEventListener) {
71         LOG.debug("Init task {}", DeviceMonitorTask.class.getSimpleName());
72
73         //Setup finals
74         this.mountPointName = mountPointName;
75         this.odlEventListener = odlEventListener;
76         this.checkConnectionToMediator = new Checker() {
77             @Override
78             boolean isReachableOnce() {
79                 synchronized(lockNe) {
80                     //mountpoint state "Connected"
81                     //If for any reason the mountpoint is Connected, but Notconf messages are not received
82                     return ne == null ? true : ne.checkIfConnectionToMediatorIsOk();
83                 }
84             }
85         };
86         this.checkConnectionToNe = new Checker() {
87             @Override
88             boolean isReachableOnce() {
89                 synchronized(lockNe) {
90                     //mountpoint state "Connected"
91                     //If netconf mediator (netconf application software for NE) has connection loss to managed device.
92                     //The networkelement object is available, but there is no interfacepack available.
93                     return ne == null ? true : ne.checkIfConnectionToNeIsOk();
94                 }
95             }
96         };
97
98         //Setup parameters
99         this.taskHandle = null;
100         this.tickCounter = 0;
101         this.ne = null;
102         this.mountpointConnectingStateSupervision = false;
103         this.currentProblems = Collections.synchronizedSet(EnumSet.noneOf(DeviceMonitorProblems.class));
104         this.disconnectSupervisionTickout = 0;
105
106         int removed = odlEventListener.removeAllCurrentProblemsOfNode(mountPointName);
107         LOG.debug("{} Init task removed fault entries {}", LOGMARKER, removed);
108
109     }
110
111     /**
112      * Start for each object an own instance of the thread.
113      * @param scheduler for all the threads.
114      */
115     public void start(ScheduledExecutorService scheduler) {
116         LOG.info("{} {} DeviceMonitor task to create", LOGMARKER, tickCounter);
117         if (taskHandle == null) {
118             startDisconnectSupervision();
119             taskHandle = scheduler.scheduleAtFixedRate(this, 0, 120, TimeUnit.SECONDS);
120             LOG.info("DeviceMonitor task scheduled");
121         } else {
122             LOG.error("{} {} Task already running.", LOGMARKER, tickCounter);
123         }
124     }
125
126     /**
127      * Call after NE change state to connected.
128      * Mountpoint exists. Status is Connecting.
129      * @param neParam that connected
130      */
131
132     public void deviceConnectIndication(DeviceMonitoredNe neParam) {
133         LOG.info("{} {} Connect {} and stop.", LOGMARKER, tickCounter, mountPointName);
134         clear(DeviceMonitorProblems.connectionLossOAM);
135         synchronized(lockNe) {
136             this.ne = neParam;
137             this.mountpointConnectingStateSupervision = false;
138         }
139         stopDisconnectSupervision();
140     }
141
142     /**
143      * If ne is disconnected do the related actions.
144      * - Mountpoint exists. Status is Connecting or UnableToConnect
145      */
146
147     public void deviceDisconnectIndication() {
148         LOG.info("{} {} Disconnect {} and start.", LOGMARKER, tickCounter, mountPointName);
149         clear(DeviceMonitorProblems.connectionLossOAM);
150         synchronized(lockNe) {
151             this.ne = null;
152             this.mountpointConnectingStateSupervision = true;
153         }
154         startDisconnectSupervision();
155     }
156
157     /**
158      * Do all actions to clean up the log if mountpoint has been deleted.
159      * - Mountpoint removed
160      * Prepare cancellation of the task and cancel task
161      */
162
163     public void removeMountpointIndication() {
164          for (DeviceMonitorProblems problem : DeviceMonitorProblems.values()) {
165             clear(problem);
166         }
167          //Cancel the task
168          if (this.taskHandle != null) {
169              this.taskHandle.cancel(false);
170              LOG.info("{} {} DeviceMonitor task canceled for {}", LOGMARKER, tickCounter, mountPointName);
171          } else {
172              LOG.error("{} {} Task already stopped", LOGMARKER, tickCounter);
173          }
174     }
175
176     /**
177      * Referesh Alarms
178      */
179     public void refreshAlarms() {
180         LOG.debug("{} Start refresh of all problems",LOGMARKER);
181         synchronized(currentProblems) {
182             for (DeviceMonitorProblems problem :    currentProblems) {
183                 LOG.debug("{} Refresh problem {} Raised-status {}",LOGMARKER, problem.name(), currentProblems.contains(problem));
184                 odlEventListener.onProblemNotification(mountPointName, problem.name(), problem.getSeverity());
185             }
186         }
187         LOG.debug("{} Finish refresh of all problems",LOGMARKER);
188     }
189
190     /*------------------------------------------------------------
191      * Functions to clear/raise alarm
192      */
193
194     /**
195      * Raise a problem, but only once
196      * @param problem
197      */
198     private void raise(DeviceMonitorProblems problem) {
199         LOG.debug("{} Raise problem {} Raised-status {}",LOGMARKER, problem.name(), currentProblems.contains(problem));
200         synchronized(currentProblems) {
201             if (! currentProblems.contains(problem)) {
202                 currentProblems.add(problem);
203                 odlEventListener.onProblemNotification(mountPointName, problem.name(), problem.getSeverity());
204             }
205         }
206     }
207
208     /**
209      * Raise a problem, but only once
210      * @param problem
211      */
212     private void clear(DeviceMonitorProblems problem) {
213         LOG.debug("{} Clear problem {} Raised-status {}",LOGMARKER, problem.name(), currentProblems.contains(problem));
214         synchronized(currentProblems) {
215             if (currentProblems.contains(problem)) {
216                 currentProblems.remove(problem);
217                 odlEventListener.onProblemNotification(mountPointName, problem.name(), InternalSeverity.NonAlarmed);
218             }
219         }
220     }
221
222     /**
223      * Process problem notification cascade
224      * @param isReachable
225      * @param problem
226      */
227     private void clearRaiseIfConnected(Checker checker, DeviceMonitorProblems problem) {
228         LOG.debug("{} check start {} problem {} Raised-status {}",LOGMARKER, tickCounter, problem.name(), currentProblems.contains(problem));
229         if (checker.isConnected()) {
230             clear(problem);
231         } else {
232             raise(problem);
233         }
234         LOG.debug("{} check end {} problem {} Raised-status {}",LOGMARKER, tickCounter, problem.name(), currentProblems.contains(problem));
235     }
236
237     /*------------------------------------------------------------
238      * Functions to start/stop
239      */
240
241     private void startDisconnectSupervision() {
242         synchronized(lockDisconnectSupervisionTickout) {
243             this.disconnectSupervisionTickout = 2;
244         }
245     }
246
247     private void stopDisconnectSupervision() {
248         synchronized(lockDisconnectSupervisionTickout) {
249             this.disconnectSupervisionTickout = 0;
250         }
251     }
252
253     private boolean processDisconnectSupervisionAndCheckExceeded() {
254         synchronized(lockDisconnectSupervisionTickout) {
255             if (disconnectSupervisionTickout == 0) {
256                 return true;
257             } else if (disconnectSupervisionTickout > 0) {
258                 disconnectSupervisionTickout--;
259             }
260             return false;
261         }
262     }
263
264     /*------------------------------------------------------------
265      * TASK
266      */
267
268     /**
269      * Task to monitor connectivity to Network Elements.
270      * Connectivity problems lead to alarm indication.
271      */
272     @Override
273     public void run() {
274
275         try {
276             LOG.debug("{} UTCTime {} START mountpoint {} tick {} connecting supervision {} tickout {}",
277                     LOGMARKER,
278                     NETCONFTIME_CONVERTER.getTimeStamp(),
279                     mountPointName,
280                     tickCounter,
281                     mountpointConnectingStateSupervision,
282                     disconnectSupervisionTickout);
283
284                if (mountpointConnectingStateSupervision) {
285                    LOG.debug("{} {} Mountpoint supervision {}", LOGMARKER, tickCounter, mountPointName);
286                    if (processDisconnectSupervisionAndCheckExceeded()) {
287                        raise(DeviceMonitorProblems.connectionLossOAM);
288                    }
289
290                } else {
291                 synchronized (lockNe) {
292                        if (ne != null) {
293                            //checks during "Connected"
294                            clear(DeviceMonitorProblems.connectionLossOAM); //Always cleared never raised
295                            LOG.debug("{} {} Prepare check", LOGMARKER, tickCounter);
296                            ne.prepareCheck();  // Prepare ne check
297                            // Mediator check
298                            LOG.debug("{} {} Mediator check", LOGMARKER, tickCounter);
299                            clearRaiseIfConnected(checkConnectionToMediator, DeviceMonitorProblems.connectionLossMediator);
300
301                            // NE check
302                            LOG.debug("{} {} Ne check", LOGMARKER, tickCounter);
303                            clearRaiseIfConnected(checkConnectionToNe, DeviceMonitorProblems.connectionLossNeOAM);
304                        } else {
305                            //Monitor switch off.
306                            LOG.debug("{} {} Monitor switch off state", LOGMARKER, tickCounter);
307                            clear(DeviceMonitorProblems.connectionLossOAM); //Always cleared never raised
308                            clear(DeviceMonitorProblems.connectionLossMediator); //Always cleared never raised
309                            clear(DeviceMonitorProblems.connectionLossNeOAM); //Always cleared never raised
310                        }
311                    }
312             }
313         } catch (Exception e) {
314             //Prevent stopping the task
315             LOG.warn("{} {} During DeviceMontoring task",LOGMARKER, tickCounter, e);
316         }
317         LOG.debug("{} {} END", LOGMARKER, tickCounter++);
318
319     }
320 }