blob: c74934cc5bc7aa0986bb2ed9f9f9456d496a31b0 [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
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -080025import org.onosproject.cfg.ComponentConfigService;
Andrea Campanellae72ac552016-04-11 10:04:52 -070026import org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer;
27import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProvider;
28import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderRegistry;
29import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderService;
30import org.onosproject.mastership.MastershipEvent;
31import org.onosproject.mastership.MastershipListener;
32import org.onosproject.mastership.MastershipService;
33import org.onosproject.net.Device;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.device.DeviceEvent;
36import org.onosproject.net.device.DeviceListener;
37import org.onosproject.net.device.DeviceService;
38import org.onosproject.net.provider.AbstractProvider;
39import org.onosproject.net.provider.ProviderId;
40import org.osgi.service.component.ComponentContext;
41import org.slf4j.Logger;
42
43import java.util.Dictionary;
44import java.util.concurrent.ExecutorService;
45import java.util.concurrent.Executors;
46import java.util.concurrent.ScheduledExecutorService;
47import java.util.concurrent.ScheduledFuture;
48import java.util.concurrent.TimeUnit;
49
50import static com.google.common.base.Strings.isNullOrEmpty;
Yuta HIGUCHI1624df12016-07-21 16:54:33 -070051import static java.util.concurrent.Executors.newScheduledThreadPool;
Andrea Campanellae72ac552016-04-11 10:04:52 -070052import static org.onlab.util.Tools.get;
53import static org.onlab.util.Tools.groupedThreads;
54import static org.slf4j.LoggerFactory.getLogger;
55
56/**
57 * Alarm provider capable of polling the environment using the device driver
58 * {@link AlarmConsumer} behaviour.
59 */
60@Component(immediate = true)
61public class PollingAlarmProvider extends AbstractProvider implements AlarmProvider {
62
63 private final Logger log = getLogger(getClass());
64
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected DeviceService deviceService;
67
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected MastershipService mastershipService;
70
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected AlarmProviderRegistry providerRegistry;
73
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -080074 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected ComponentConfigService cfgService;
76
Andrea Campanellae72ac552016-04-11 10:04:52 -070077 protected AlarmProviderService providerService;
78
79 protected ScheduledExecutorService alarmsExecutor;
80
81 private ScheduledFuture<?> scheduledTask;
82
83 private ExecutorService eventHandlingExecutor;
84
85 protected final MastershipListener mastershipListener = new InternalMastershipListener();
86
87 protected final DeviceListener deviceListener = new InternalDeviceListener();
88
89 private static final int CORE_POOL_SIZE = 10;
90
91 private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 60;
92 @Property(name = "alarmPollFrequencySeconds", intValue = DEFAULT_POLL_FREQUENCY_SECONDS,
93 label = "Frequency (in seconds) for polling alarm from devices")
94 protected int alarmPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS;
95
96 // TODO implement purging of old alarms.
97 private static final int DEFAULT_CLEAR_FREQUENCY_SECONDS = 500;
98 @Property(name = "clearedAlarmPurgeSeconds", intValue = DEFAULT_CLEAR_FREQUENCY_SECONDS,
99 label = "Frequency (in seconds) for deleting cleared alarms")
100 private int clearedAlarmPurgeFrequencySeconds = DEFAULT_CLEAR_FREQUENCY_SECONDS;
101
102 public PollingAlarmProvider() {
103 super(new ProviderId("default", "org.onosproject.core"));
104 }
105
106 @Activate
107 public void activate(ComponentContext context) {
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -0800108 cfgService.registerProperties(getClass());
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700109 alarmsExecutor = newScheduledThreadPool(CORE_POOL_SIZE,
110 groupedThreads("onos/pollingalarmprovider",
111 "alarm-executor-%d", log));
Andrea Campanellae72ac552016-04-11 10:04:52 -0700112 eventHandlingExecutor =
113 Executors.newFixedThreadPool(CORE_POOL_SIZE,
114 groupedThreads("onos/pollingalarmprovider",
115 "device-installer-%d", log));
116
117 providerService = providerRegistry.register(this);
118
119 deviceService.addListener(deviceListener);
120 mastershipService.addListener(mastershipListener);
121
122 if (context == null) {
123 alarmPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS;
124 log.info("No component configuration");
125 } else {
126 Dictionary<?, ?> properties = context.getProperties();
127 alarmPollFrequencySeconds = getNewPollFrequency(properties, alarmPollFrequencySeconds);
128 }
129 scheduledTask = schedulePolling();
130 log.info("Started");
131 }
132
133 @Deactivate
134 public void deactivate() {
fahadnaeemkhan8ee2be92018-02-08 17:42:08 -0800135 cfgService.unregisterProperties(getClass(), false);
Andrea Campanellae72ac552016-04-11 10:04:52 -0700136 providerRegistry.unregister(this);
137 mastershipService.removeListener(mastershipListener);
138 deviceService.removeListener(deviceListener);
139 alarmsExecutor.shutdown();
140 providerService = null;
141 log.info("Stopped");
142 }
143
144 @Modified
145 public void modified(ComponentContext context) {
146 if (context == null) {
147 log.info("No component configuration");
148 return;
149 }
150
151 Dictionary<?, ?> properties = context.getProperties();
152 int newPollFrequency = getNewPollFrequency(properties, alarmPollFrequencySeconds);
153 if (newPollFrequency != alarmPollFrequencySeconds) {
154 alarmPollFrequencySeconds = newPollFrequency;
155 //stops the old scheduled task
156 scheduledTask.cancel(true);
157 //schedules new task at the new polling rate
158 scheduledTask = schedulePolling();
159 }
160 }
161
162 private ScheduledFuture schedulePolling() {
163 return alarmsExecutor.scheduleAtFixedRate(this::consumeAlarms,
164 alarmPollFrequencySeconds / 4, alarmPollFrequencySeconds,
165 TimeUnit.SECONDS);
166 }
167
168 private int getNewPollFrequency(Dictionary<?, ?> properties, int pollFrequency) {
169 int newPollFrequency;
170 try {
171 String s = get(properties, "pollFrequency");
172 newPollFrequency = isNullOrEmpty(s) ? pollFrequency : Integer.parseInt(s.trim());
173 } catch (NumberFormatException | ClassCastException e) {
174 newPollFrequency = DEFAULT_POLL_FREQUENCY_SECONDS;
175 }
176 return newPollFrequency;
177 }
178
179 @Override
180 public void triggerProbe(DeviceId deviceId) {
181 if (mastershipService.isLocalMaster(deviceId)) {
182 triggerProbe(deviceService.getDevice(deviceId));
183 }
184 }
185
186 private void triggerProbe(Device device) {
187 alarmsExecutor.submit(() -> consumeAlarms(device));
188 }
189
190 private void consumeAlarms() {
191 deviceService.getAvailableDevices().forEach(device -> {
192 if (mastershipService.isLocalMaster(device.id())) {
193 consumeAlarms(device);
194 }
195 });
196 }
197
198 private void consumeAlarms(Device device) {
199 if (device.is(AlarmConsumer.class)) {
200 providerService.updateAlarmList(device.id(),
201 device.as(AlarmConsumer.class).consumeAlarms());
202 } else {
Michele Santuari2cf84292016-08-12 11:56:48 +0200203 log.debug("Device {} does not support alarm consumer behaviour", device.id());
Andrea Campanellae72ac552016-04-11 10:04:52 -0700204 }
205 }
206
207 private class InternalMastershipListener implements MastershipListener {
208
209 @Override
210 public boolean isRelevant(MastershipEvent event) {
211 return mastershipService.isLocalMaster(event.subject());
212 }
213
214 @Override
215 public void event(MastershipEvent event) {
216 triggerProbe(event.subject());
217 }
218 }
219
220 /**
221 * Internal listener for device service events.
222 */
223 private class InternalDeviceListener implements DeviceListener {
224
225 @Override
226 public boolean isRelevant(DeviceEvent event) {
227 return event.type().equals(DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED)
228 && deviceService.isAvailable(event.subject().id());
229 }
230
231 @Override
232 public void event(DeviceEvent event) {
233 log.debug("InternalDeviceListener has got event from device-service{} with ", event);
234 eventHandlingExecutor.execute(() -> triggerProbe(event.subject().id()));
235 }
236
237 }
238}