blob: f5e4a27798bfb29878a5d5fb4d561b01bfd52a94 [file] [log] [blame]
Andrea Campanellae72ac552016-04-11 10:04:52 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Andrea Campanellae72ac552016-04-11 10:04:52 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Andrea Campanella637c8072016-04-12 17:29:17 -070016package org.onosproject.faultmanagement.impl;
Andrea Campanellae72ac552016-04-11 10:04:52 -070017
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -080018import org.onosproject.cfg.ComponentConfigService;
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080019import org.onosproject.alarm.AlarmConsumer;
20import org.onosproject.alarm.AlarmProvider;
21import org.onosproject.alarm.AlarmProviderRegistry;
22import org.onosproject.alarm.AlarmProviderService;
Andrea Campanellae72ac552016-04-11 10:04:52 -070023import org.onosproject.mastership.MastershipEvent;
24import org.onosproject.mastership.MastershipListener;
25import org.onosproject.mastership.MastershipService;
26import org.onosproject.net.Device;
27import org.onosproject.net.DeviceId;
28import org.onosproject.net.device.DeviceEvent;
29import org.onosproject.net.device.DeviceListener;
30import org.onosproject.net.device.DeviceService;
31import org.onosproject.net.provider.AbstractProvider;
32import org.onosproject.net.provider.ProviderId;
33import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070034import org.osgi.service.component.annotations.Activate;
35import org.osgi.service.component.annotations.Component;
36import org.osgi.service.component.annotations.Deactivate;
37import org.osgi.service.component.annotations.Modified;
38import org.osgi.service.component.annotations.Reference;
39import org.osgi.service.component.annotations.ReferenceCardinality;
Andrea Campanellae72ac552016-04-11 10:04:52 -070040import org.slf4j.Logger;
41
42import java.util.Dictionary;
43import java.util.concurrent.ExecutorService;
44import java.util.concurrent.Executors;
45import java.util.concurrent.ScheduledExecutorService;
46import java.util.concurrent.ScheduledFuture;
47import java.util.concurrent.TimeUnit;
48
49import static com.google.common.base.Strings.isNullOrEmpty;
Yuta HIGUCHI1624df12016-07-21 16:54:33 -070050import static java.util.concurrent.Executors.newScheduledThreadPool;
Andrea Campanellae72ac552016-04-11 10:04:52 -070051import static org.onlab.util.Tools.get;
52import static org.onlab.util.Tools.groupedThreads;
Ray Milkey4694e062018-10-31 13:17:18 -070053import static org.onosproject.faultmanagement.impl.OsgiPropertyConstants.CLEAR_FREQUENCY_SECONDS;
54import static org.onosproject.faultmanagement.impl.OsgiPropertyConstants.CLEAR_FREQUENCY_SECONDS_DEFAULT;
55import static org.onosproject.faultmanagement.impl.OsgiPropertyConstants.POLL_FREQUENCY_SECONDS;
56import static org.onosproject.faultmanagement.impl.OsgiPropertyConstants.POLL_FREQUENCY_SECONDS_DEFAULT;
Andrea Campanellae72ac552016-04-11 10:04:52 -070057import static org.slf4j.LoggerFactory.getLogger;
58
59/**
60 * Alarm provider capable of polling the environment using the device driver
61 * {@link AlarmConsumer} behaviour.
62 */
Ray Milkey4694e062018-10-31 13:17:18 -070063@Component(
64 immediate = true,
65 property = {
66 POLL_FREQUENCY_SECONDS + "=" + POLL_FREQUENCY_SECONDS_DEFAULT,
67 CLEAR_FREQUENCY_SECONDS + "=" + CLEAR_FREQUENCY_SECONDS_DEFAULT
68 }
69)
Andrea Campanellae72ac552016-04-11 10:04:52 -070070public class PollingAlarmProvider extends AbstractProvider implements AlarmProvider {
71
72 private final Logger log = getLogger(getClass());
73
Ray Milkeyd84f89b2018-08-17 14:54:17 -070074 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanellae72ac552016-04-11 10:04:52 -070075 protected DeviceService deviceService;
76
Ray Milkeyd84f89b2018-08-17 14:54:17 -070077 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanellae72ac552016-04-11 10:04:52 -070078 protected MastershipService mastershipService;
79
Ray Milkeyd84f89b2018-08-17 14:54:17 -070080 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Andrea Campanellae72ac552016-04-11 10:04:52 -070081 protected AlarmProviderRegistry providerRegistry;
82
Ray Milkeyd84f89b2018-08-17 14:54:17 -070083 @Reference(cardinality = ReferenceCardinality.MANDATORY)
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -080084 protected ComponentConfigService cfgService;
85
Andrea Campanellae72ac552016-04-11 10:04:52 -070086 protected AlarmProviderService providerService;
87
88 protected ScheduledExecutorService alarmsExecutor;
89
90 private ScheduledFuture<?> scheduledTask;
91
92 private ExecutorService eventHandlingExecutor;
93
94 protected final MastershipListener mastershipListener = new InternalMastershipListener();
95
96 protected final DeviceListener deviceListener = new InternalDeviceListener();
97
98 private static final int CORE_POOL_SIZE = 10;
99
Ray Milkey4694e062018-10-31 13:17:18 -0700100 /** Frequency (in seconds) for polling alarm from devices. */
101 protected int alarmPollFrequencySeconds = POLL_FREQUENCY_SECONDS_DEFAULT;
Andrea Campanellae72ac552016-04-11 10:04:52 -0700102
Ray Milkey4694e062018-10-31 13:17:18 -0700103 /** Frequency (in seconds) for deleting cleared alarms. */
104 private int clearedAlarmPurgeFrequencySeconds = CLEAR_FREQUENCY_SECONDS_DEFAULT;
Andrea Campanellae72ac552016-04-11 10:04:52 -0700105
106 public PollingAlarmProvider() {
107 super(new ProviderId("default", "org.onosproject.core"));
108 }
109
110 @Activate
111 public void activate(ComponentContext context) {
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -0800112 cfgService.registerProperties(getClass());
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700113 alarmsExecutor = newScheduledThreadPool(CORE_POOL_SIZE,
114 groupedThreads("onos/pollingalarmprovider",
115 "alarm-executor-%d", log));
Andrea Campanellae72ac552016-04-11 10:04:52 -0700116 eventHandlingExecutor =
117 Executors.newFixedThreadPool(CORE_POOL_SIZE,
118 groupedThreads("onos/pollingalarmprovider",
119 "device-installer-%d", log));
120
121 providerService = providerRegistry.register(this);
122
123 deviceService.addListener(deviceListener);
124 mastershipService.addListener(mastershipListener);
125
126 if (context == null) {
Ray Milkey4694e062018-10-31 13:17:18 -0700127 alarmPollFrequencySeconds = POLL_FREQUENCY_SECONDS_DEFAULT;
Andrea Campanellae72ac552016-04-11 10:04:52 -0700128 log.info("No component configuration");
129 } else {
130 Dictionary<?, ?> properties = context.getProperties();
131 alarmPollFrequencySeconds = getNewPollFrequency(properties, alarmPollFrequencySeconds);
132 }
133 scheduledTask = schedulePolling();
134 log.info("Started");
135 }
136
137 @Deactivate
138 public void deactivate() {
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -0800139 cfgService.unregisterProperties(getClass(), false);
Andrea Campanellae72ac552016-04-11 10:04:52 -0700140 providerRegistry.unregister(this);
141 mastershipService.removeListener(mastershipListener);
142 deviceService.removeListener(deviceListener);
143 alarmsExecutor.shutdown();
144 providerService = null;
145 log.info("Stopped");
146 }
147
148 @Modified
149 public void modified(ComponentContext context) {
150 if (context == null) {
151 log.info("No component configuration");
152 return;
153 }
154
155 Dictionary<?, ?> properties = context.getProperties();
156 int newPollFrequency = getNewPollFrequency(properties, alarmPollFrequencySeconds);
157 if (newPollFrequency != alarmPollFrequencySeconds) {
158 alarmPollFrequencySeconds = newPollFrequency;
159 //stops the old scheduled task
160 scheduledTask.cancel(true);
161 //schedules new task at the new polling rate
162 scheduledTask = schedulePolling();
163 }
164 }
165
166 private ScheduledFuture schedulePolling() {
167 return alarmsExecutor.scheduleAtFixedRate(this::consumeAlarms,
168 alarmPollFrequencySeconds / 4, alarmPollFrequencySeconds,
169 TimeUnit.SECONDS);
170 }
171
172 private int getNewPollFrequency(Dictionary<?, ?> properties, int pollFrequency) {
173 int newPollFrequency;
174 try {
Ray Milkey4694e062018-10-31 13:17:18 -0700175 String s = get(properties, POLL_FREQUENCY_SECONDS);
Andrea Campanellae72ac552016-04-11 10:04:52 -0700176 newPollFrequency = isNullOrEmpty(s) ? pollFrequency : Integer.parseInt(s.trim());
177 } catch (NumberFormatException | ClassCastException e) {
Ray Milkey4694e062018-10-31 13:17:18 -0700178 newPollFrequency = POLL_FREQUENCY_SECONDS_DEFAULT;
Andrea Campanellae72ac552016-04-11 10:04:52 -0700179 }
180 return newPollFrequency;
181 }
182
183 @Override
184 public void triggerProbe(DeviceId deviceId) {
185 if (mastershipService.isLocalMaster(deviceId)) {
186 triggerProbe(deviceService.getDevice(deviceId));
187 }
188 }
189
190 private void triggerProbe(Device device) {
191 alarmsExecutor.submit(() -> consumeAlarms(device));
192 }
193
194 private void consumeAlarms() {
195 deviceService.getAvailableDevices().forEach(device -> {
196 if (mastershipService.isLocalMaster(device.id())) {
197 consumeAlarms(device);
198 }
199 });
200 }
201
202 private void consumeAlarms(Device device) {
203 if (device.is(AlarmConsumer.class)) {
204 providerService.updateAlarmList(device.id(),
205 device.as(AlarmConsumer.class).consumeAlarms());
206 } else {
Michele Santuari2cf84292016-08-12 11:56:48 +0200207 log.debug("Device {} does not support alarm consumer behaviour", device.id());
Andrea Campanellae72ac552016-04-11 10:04:52 -0700208 }
209 }
210
211 private class InternalMastershipListener implements MastershipListener {
212
213 @Override
214 public boolean isRelevant(MastershipEvent event) {
215 return mastershipService.isLocalMaster(event.subject());
216 }
217
218 @Override
219 public void event(MastershipEvent event) {
220 triggerProbe(event.subject());
221 }
222 }
223
224 /**
225 * Internal listener for device service events.
226 */
227 private class InternalDeviceListener implements DeviceListener {
228
229 @Override
230 public boolean isRelevant(DeviceEvent event) {
231 return event.type().equals(DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED)
232 && deviceService.isAvailable(event.subject().id());
233 }
234
235 @Override
236 public void event(DeviceEvent event) {
237 log.debug("InternalDeviceListener has got event from device-service{} with ", event);
238 eventHandlingExecutor.execute(() -> triggerProbe(event.subject().id()));
239 }
240
241 }
242}