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