SDN-R Sodium compliant netconfnode-state-service and devicemanager
[ccsdk/features.git] / sdnr / wt / devicemanager / provider / src / main / java / org / onap / ccsdk / features / sdnr / wt / devicemanager / devicemonitor / impl / DeviceMonitorImpl.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  * (c) 2017 highstreet technologies GmbH
20  */
21
22 package org.onap.ccsdk.features.sdnr.wt.devicemanager.devicemonitor.impl;
23
24 import java.util.Enumeration;
25 import java.util.Optional;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.ScheduledExecutorService;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.onap.ccsdk.features.sdnr.wt.common.configuration.ConfigurationFileRepresentation;
31 import org.onap.ccsdk.features.sdnr.wt.common.configuration.filechange.IConfigChangedListener;
32 import org.onap.ccsdk.features.sdnr.wt.devicemanager.devicemonitor.impl.config.DmConfig;
33 import org.onap.ccsdk.features.sdnr.wt.devicemanager.eventdatahandler.ODLEventListenerHandler;
34 import org.onap.ccsdk.features.sdnr.wt.devicemanager.ne.service.DeviceMonitoredNe;
35 import org.onap.ccsdk.features.sdnr.wt.devicemanager.ne.service.NetworkElement;
36 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfAccessor;
37 import org.opendaylight.mdsal.binding.api.DataBroker;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * Implementation of concept "Active monitoring" of a device.<br>
43  * <br>
44  * For each existing mountpoint a task runs with 120s cycle time. Every 120 seconds the check actions are performed. The
45  * request is handled by the NETCONF layer with a (default)configured time-out of 60 seconds.<br>
46  * Generated alarms, by the object/node "SDN-Controller" are (enum DeviceMonitorProblems):<br>
47  * - notConnected(InternalSeverity.Warning)<br>
48  * - noConnectionMediator(InternalSeverity.Minor)<br>
49  * - noConnectionNe(InternalSeverity.Critical)<br>
50  * <br>
51  * 1. Mountpoint does not exist<br>
52  * If the mountpoint does not exists there are no related current alarms in the database.<br>
53  * <br>
54  * 2. Created mountpoint with state "Connecting" or "UnableToConnect"<br>
55  * If the Mountpoint is created and connection status is "Connecting" or "UnableToConnect".<br>
56  * - After about 2..4 Minutes ... raise alarm "notConnected" with severity warning<br>
57  * <br>
58  * 3. Created mountpoint with state "Connection"<br>
59  * There are two monitor activities.<br>
60  * 3a. Check of Mediator connection by requesting (typical) cached data.<br>
61  * - After about 60 seconds raise alarm: connection-loss-mediator with severity minor<br>
62  * - Request from Mediator: network-element<br>
63  * <br>
64  * 3b. Check connection to NEby requesting (typical) non-cached data.<br>
65  * - Only if AirInterface available. The first one is used.<br>
66  * - Requested are the currentAlarms<br>
67  * - After about 60 seconds raise alarm: connection-loss-network-element with severity critical<br>
68  * <br>
69  * 
70  * @author herbert
71  */
72
73 public class DeviceMonitorImpl implements DeviceMonitor, IConfigChangedListener {
74
75     private static final Logger LOG = LoggerFactory.getLogger(DeviceMonitorImpl.class);
76
77     private final ConcurrentHashMap<String, DeviceMonitorTask> queue;
78     private final ScheduledExecutorService scheduler;
79     private final ODLEventListenerHandler odlEventListener;
80     @SuppressWarnings("unused")
81     private final DataBroker dataBroker; //Future usage
82     private final DmConfig dmConfig;
83     private final DeviceMonitoredNe dummyNe;
84
85     /*-------------------------------------------------------------
86      * Construction/ destruction of service
87      */
88
89     /**
90      * Basic implementation of devicemonitoring
91      * 
92      * @param odlEventListener as destination for problems
93      */
94     public DeviceMonitorImpl(DataBroker dataBroker, ODLEventListenerHandler odlEventListener,
95             ConfigurationFileRepresentation htconfig) {
96         LOG.info("Construct {}", this.getClass().getSimpleName());
97
98         this.odlEventListener = odlEventListener;
99         this.dataBroker = dataBroker;
100         this.dummyNe = getDummyNe();
101
102         htconfig.registerConfigChangedListener(this);
103         this.dmConfig = new DmConfig(htconfig);
104         setDmConfig(dmConfig);
105
106         this.queue = new ConcurrentHashMap<>();
107         this.scheduler = Executors.newScheduledThreadPool(10);
108     }
109
110     /**
111      * Stop the service. Stop all running monitoring tasks.
112      */
113     @Override
114     synchronized public void close() {
115         LOG.info("Close {}", this.getClass().getSimpleName());
116
117         Enumeration<String> e = queue.keys();
118         while (e.hasMoreElements()) {
119             deviceDisconnectIndication(e.nextElement());
120         }
121
122         scheduler.shutdown();
123     }
124
125     @Override
126     public void onConfigChanged() {
127         setDmConfig(dmConfig);
128     }
129
130     private void setDmConfig(DmConfig dmConfig) {
131         for (DeviceMonitorProblems problem : DeviceMonitorProblems.values()) {
132             problem.setSeverity(dmConfig.getSeverity(problem));
133         }
134     }
135
136     /*-------------------------------------------------------------
137      * Start/ stop/ update service for Mountpoint
138      */
139
140     /**
141      * Notify of device state changes to "connected" for slave nodes
142      * 
143      * @param mountPointNodeName name of mount point
144      */
145     @Override
146     synchronized public void deviceConnectSlaveIndication(String mountPointNodeName) {
147         deviceConnectMasterIndication(mountPointNodeName, (DeviceMonitoredNe) null);
148     }
149
150     @Override
151     public void deviceConnectMasterIndication(String mountPointNodeName, NetworkElement networkElement) {
152         Optional<DeviceMonitoredNe> monitoredNe = networkElement.getService(DeviceMonitoredNe.class);
153         deviceConnectMasterIndication(mountPointNodeName, monitoredNe.isPresent() ? monitoredNe.get() : dummyNe);
154     }
155
156     /**
157      * Notify of device state changes to "connected"
158      * 
159      * @param mountPointNodeName name of mount point
160      * @param ne to monitor
161      */
162     synchronized private void deviceConnectMasterIndication(String mountPointNodeName, @Nullable DeviceMonitoredNe ne) {
163
164         LOG.debug("ne changes to connected state {}", mountPointNodeName);
165         createMonitoringTask(mountPointNodeName);
166         if (queue.containsKey(mountPointNodeName)) {
167             DeviceMonitorTask task = queue.get(mountPointNodeName);
168             task.deviceConnectIndication(ne);
169         } else {
170             LOG.warn("Monitoring task not in queue: {} {} {}", mountPointNodeName, mountPointNodeName.hashCode(),
171                     queue.size());
172         }
173     }
174
175     /**
176      * Notify of device state change to "disconnected" Mount point supervision
177      * 
178      * @param mountPointNodeName to deregister
179      */
180     @Override
181     synchronized public void deviceDisconnectIndication(String mountPointNodeName) {
182
183         LOG.debug("State changes to not connected state {}", mountPointNodeName);
184         createMonitoringTask(mountPointNodeName);
185         if (queue.containsKey(mountPointNodeName)) {
186             DeviceMonitorTask task = queue.get(mountPointNodeName);
187             task.deviceDisconnectIndication();
188         } else {
189             LOG.warn("Monitoring task not in queue: {} {} {}", mountPointNodeName, mountPointNodeName.hashCode(),
190                     queue.size());
191         }
192     }
193
194     /**
195      * removeMountpointIndication deregisters a mountpoint for registration services
196      * 
197      * @param mountPointNodeName to deregister
198      */
199     @Override
200     synchronized public void removeMountpointIndication(String mountPointNodeName) {
201
202         if (queue.containsKey(mountPointNodeName)) {
203             DeviceMonitorTask task = queue.get(mountPointNodeName);
204             //Remove from here
205             queue.remove(mountPointNodeName);
206             //Clear all problems
207             task.removeMountpointIndication();
208             LOG.debug("Task stopped: {}", mountPointNodeName);
209         } else {
210             LOG.warn("Task not in queue: {}", mountPointNodeName);
211         }
212     }
213
214     /**
215      * Referesh database by raising all alarms again.
216      */
217     @Override
218     public void refreshAlarmsInDb() {
219         synchronized (queue) {
220             for (DeviceMonitorTask task : queue.values()) {
221                 task.refreshAlarms();
222             }
223         }
224     }
225
226     /**
227      * For test run the tasks
228      */
229     public void taskTestRun() {
230         synchronized (queue) {
231             for (DeviceMonitorTask task : queue.values()) {
232                 task.run();
233             }
234         }
235     }
236
237     /*-------------------------------------------------------------
238      * Private functions
239      */
240
241     /**
242      * createMountpoint registers a new mountpoint monitoring service
243      * 
244      * @param mountPointNodeName name of mountpoint
245      */
246     synchronized private DeviceMonitorTask createMonitoringTask(String mountPointNodeName) {
247
248         DeviceMonitorTask task;
249         LOG.debug("Register for monitoring {} {}", mountPointNodeName, mountPointNodeName.hashCode());
250
251         if (queue.containsKey(mountPointNodeName)) {
252             LOG.info("Monitoring task exists");
253             task = queue.get(mountPointNodeName);
254         } else {
255             LOG.info("Do start of DeviceMonitor task");
256             //Runnable task = new PerformanceManagerTask(queue, databaseService);
257             task = new DeviceMonitorTask(mountPointNodeName, this.odlEventListener);
258             queue.put(mountPointNodeName, task);
259             task.start(scheduler);
260         }
261         return task;
262     }
263
264
265     private static DeviceMonitoredNe getDummyNe() {
266         return new DeviceMonitoredNe() {
267
268             @Override
269             public void prepareCheck() {
270                 // Do nothing
271             }
272
273             @Override
274             public boolean checkIfConnectionToMediatorIsOk() {
275                 return true;
276             }
277
278             @Override
279             public boolean checkIfConnectionToNeIsOk() {
280                 return true;
281             }
282
283             @Override
284             public Optional<NetconfAccessor> getAcessor() {
285                 return Optional.empty();
286             }
287         };
288     }
289 }