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