SDN-R add updated devicemanager
[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.impl.handler.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      * @param mountPointName to monitor
69      * @param odlEventListener to forward problems to
70      */
71     public DeviceMonitorTask(String mountPointName, ODLEventListenerHandler odlEventListener) {
72         LOG.debug("Init task {}", DeviceMonitorTask.class.getSimpleName());
73
74         //Setup finals
75         this.mountPointName = mountPointName;
76         this.odlEventListener = odlEventListener;
77         this.checkConnectionToMediator = new Checker() {
78             @Override
79             boolean isReachableOnce() {
80                 synchronized(lockNe) {
81                     //mountpoint state "Connected"
82                     //If for any reason the mountpoint is Connected, but Notconf messages are not received
83                     return ne == null ? true : ne.checkIfConnectionToMediatorIsOk();
84                 }
85             }
86         };
87         this.checkConnectionToNe = new Checker() {
88             @Override
89             boolean isReachableOnce() {
90                 synchronized(lockNe) {
91                     //mountpoint state "Connected"
92                     //If netconf mediator (netconf application software for NE) has connection loss to managed device.
93                     //The networkelement object is available, but there is no interfacepack available.
94                     return ne == null ? true : ne.checkIfConnectionToNeIsOk();
95                 }
96             }
97         };
98
99         //Setup parameters
100         this.taskHandle = null;
101         this.tickCounter = 0;
102         this.ne = null;
103         this.mountpointConnectingStateSupervision = false;
104         this.currentProblems = Collections.synchronizedSet(EnumSet.noneOf(DeviceMonitorProblems.class));
105         this.disconnectSupervisionTickout = 0;
106
107         int removed = odlEventListener.removeAllCurrentProblemsOfNode(mountPointName);
108         LOG.debug("{} Init task removed fault entries {}", LOGMARKER, removed);
109
110     }
111
112     /**
113      * Start for each object an own instance of the thread.
114      * @param scheduler for all the threads.
115      */
116     public void start(ScheduledExecutorService scheduler) {
117         LOG.info("{} {} DeviceMonitor task to create", LOGMARKER, tickCounter);
118         if (taskHandle == null) {
119             startDisconnectSupervision();
120             taskHandle = scheduler.scheduleAtFixedRate(this, 0, 120, TimeUnit.SECONDS);
121             LOG.info("DeviceMonitor task scheduled");
122         } else {
123             LOG.error("{} {} Task already running.", LOGMARKER, tickCounter);
124         }
125     }
126
127     /**
128      * Call after NE change state to connected.
129      * Mountpoint exists. Status is Connecting.
130      * @param neParam that connected
131      */
132
133     public void deviceConnectIndication(DeviceMonitoredNe neParam) {
134         LOG.info("{} {} Connect {} and stop.", LOGMARKER, tickCounter, mountPointName);
135         clear(DeviceMonitorProblems.connectionLossOAM);
136         synchronized(lockNe) {
137             this.ne = neParam;
138             this.mountpointConnectingStateSupervision = false;
139         }
140         stopDisconnectSupervision();
141     }
142
143     /**
144      * If ne is disconnected do the related actions.
145      * - Mountpoint exists. Status is Connecting or UnableToConnect
146      */
147
148     public void deviceDisconnectIndication() {
149         LOG.info("{} {} Disconnect {} and start.", LOGMARKER, tickCounter, mountPointName);
150         clear(DeviceMonitorProblems.connectionLossOAM);
151         synchronized(lockNe) {
152             this.ne = null;
153             this.mountpointConnectingStateSupervision = true;
154         }
155         startDisconnectSupervision();
156     }
157
158     /**
159      * Do all actions to clean up the log if mountpoint has been deleted.
160      * - Mountpoint removed
161      * Prepare cancellation of 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(), currentProblems.contains(problem));
185                 odlEventListener.onProblemNotification(mountPointName, problem.name(), problem.getSeverity());
186             }
187         }
188         LOG.debug("{} Finish refresh of all problems",LOGMARKER);
189     }
190
191     /*------------------------------------------------------------
192      * Functions to clear/raise alarm
193      */
194
195     /**
196      * Raise a problem, but only once
197      * @param problem
198      */
199     private void raise(DeviceMonitorProblems problem) {
200         LOG.debug("{} Raise problem {} Raised-status {}",LOGMARKER, problem.name(), currentProblems.contains(problem));
201         synchronized(currentProblems) {
202             if (! currentProblems.contains(problem)) {
203                 currentProblems.add(problem);
204                 odlEventListener.onProblemNotification(mountPointName, problem.name(), problem.getSeverity());
205             }
206         }
207     }
208
209     /**
210      * Raise a problem, but only once
211      * @param problem
212      */
213     private void clear(DeviceMonitorProblems problem) {
214         LOG.debug("{} Clear problem {} Raised-status {}",LOGMARKER, problem.name(), currentProblems.contains(problem));
215         synchronized(currentProblems) {
216             if (currentProblems.contains(problem)) {
217                 currentProblems.remove(problem);
218                 odlEventListener.onProblemNotification(mountPointName, problem.name(), InternalSeverity.NonAlarmed);
219             }
220         }
221     }
222
223     /**
224      * Process problem notification cascade
225      * @param isReachable
226      * @param problem
227      */
228     private void clearRaiseIfConnected(Checker checker, DeviceMonitorProblems problem) {
229         LOG.debug("{} check start {} problem {} Raised-status {}",LOGMARKER, tickCounter, problem.name(), currentProblems.contains(problem));
230         if (checker.isConnected()) {
231             clear(problem);
232         } else {
233             raise(problem);
234         }
235         LOG.debug("{} check end {} problem {} Raised-status {}",LOGMARKER, tickCounter, problem.name(), currentProblems.contains(problem));
236     }
237
238     /*------------------------------------------------------------
239      * Functions to start/stop
240      */
241
242     private void startDisconnectSupervision() {
243         synchronized(lockDisconnectSupervisionTickout) {
244             this.disconnectSupervisionTickout = 2;
245         }
246     }
247
248     private void stopDisconnectSupervision() {
249         synchronized(lockDisconnectSupervisionTickout) {
250             this.disconnectSupervisionTickout = 0;
251         }
252     }
253
254     private boolean processDisconnectSupervisionAndCheckExceeded() {
255         synchronized(lockDisconnectSupervisionTickout) {
256             if (disconnectSupervisionTickout == 0) {
257                 return true;
258             } else if (disconnectSupervisionTickout > 0) {
259                 disconnectSupervisionTickout--;
260             }
261             return false;
262         }
263     }
264
265     /*------------------------------------------------------------
266      * TASK
267      */
268
269     /**
270      * Task to monitor connectivity to Network Elements.
271      * Connectivity problems lead to alarm indication.
272      */
273     @Override
274     public void run() {
275
276         try {
277             LOG.debug("{} UTCTime {} START mountpoint {} tick {} connecting supervision {} tickout {}",
278                     LOGMARKER,
279                     NETCONFTIME_CONVERTER.getTimeStamp(),
280                     mountPointName,
281                     tickCounter,
282                     mountpointConnectingStateSupervision,
283                     disconnectSupervisionTickout);
284
285                if (mountpointConnectingStateSupervision) {
286                    LOG.debug("{} {} Mountpoint supervision {}", LOGMARKER, tickCounter, mountPointName);
287                    if (processDisconnectSupervisionAndCheckExceeded()) {
288                        raise(DeviceMonitorProblems.connectionLossOAM);
289                    }
290
291                } else {
292                 synchronized (lockNe) {
293                        if (ne != null) {
294                            //checks during "Connected"
295                            clear(DeviceMonitorProblems.connectionLossOAM); //Always cleared never raised
296                            LOG.debug("{} {} Prepare check", LOGMARKER, tickCounter);
297                            ne.prepareCheck();  // Prepare ne check
298                            // Mediator check
299                            LOG.debug("{} {} Mediator check", LOGMARKER, tickCounter);
300                            clearRaiseIfConnected(checkConnectionToMediator, DeviceMonitorProblems.connectionLossMediator);
301
302                            // NE check
303                            LOG.debug("{} {} Ne check", LOGMARKER, tickCounter);
304                            clearRaiseIfConnected(checkConnectionToNe, DeviceMonitorProblems.connectionLossNeOAM);
305                        } else {
306                            //Monitor switch off.
307                            LOG.debug("{} {} Monitor switch off state", LOGMARKER, tickCounter);
308                            clear(DeviceMonitorProblems.connectionLossOAM); //Always cleared never raised
309                            clear(DeviceMonitorProblems.connectionLossMediator); //Always cleared never raised
310                            clear(DeviceMonitorProblems.connectionLossNeOAM); //Always cleared never raised
311                        }
312                    }
313             }
314         } catch (Exception e) {
315             //Prevent stopping the task
316             LOG.warn("{} {} During DeviceMontoring task",LOGMARKER, tickCounter, e);
317         }
318         LOG.debug("{} {} END", LOGMARKER, tickCounter++);
319
320     }
321 }