kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 Open Networking Laboratory |
| 3 | * |
| 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 | */ |
| 16 | package org.onosproject.provider.snmp.alarm.impl; |
| 17 | |
| 18 | import com.btisystems.pronx.ems.core.snmp.DefaultSnmpConfigurationFactory; |
| 19 | import com.btisystems.pronx.ems.core.snmp.ISnmpConfiguration; |
| 20 | import com.btisystems.pronx.ems.core.snmp.ISnmpSession; |
| 21 | import com.btisystems.pronx.ems.core.snmp.ISnmpSessionFactory; |
| 22 | import com.btisystems.pronx.ems.core.snmp.SnmpSessionFactory; |
| 23 | import com.btisystems.pronx.ems.core.snmp.V2cSnmpConfiguration; |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 24 | import com.google.common.collect.Sets; |
Jonathan Hart | 51539b8 | 2015-10-29 09:53:04 -0700 | [diff] [blame] | 25 | import org.apache.felix.scr.annotations.Activate; |
| 26 | import org.apache.felix.scr.annotations.Component; |
| 27 | import org.apache.felix.scr.annotations.Deactivate; |
| 28 | import org.apache.felix.scr.annotations.Modified; |
| 29 | import org.apache.felix.scr.annotations.Reference; |
| 30 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 31 | import org.apache.felix.scr.annotations.Service; |
| 32 | import org.onosproject.core.ApplicationId; |
| 33 | import org.onosproject.core.CoreService; |
| 34 | import org.onosproject.incubator.net.faultmanagement.alarm.Alarm; |
| 35 | import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEvent; |
| 36 | import org.onosproject.incubator.net.faultmanagement.alarm.AlarmListener; |
| 37 | import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProvider; |
| 38 | import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm; |
| 39 | import org.onosproject.net.DeviceId; |
| 40 | import org.onosproject.net.device.DeviceEvent; |
| 41 | import org.onosproject.net.device.DeviceListener; |
| 42 | import org.onosproject.net.device.DeviceService; |
| 43 | import org.onosproject.net.provider.AbstractProvider; |
| 44 | import org.onosproject.net.provider.ProviderId; |
| 45 | import org.osgi.service.component.ComponentContext; |
| 46 | import org.slf4j.Logger; |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 47 | |
Jonathan Hart | 51539b8 | 2015-10-29 09:53:04 -0700 | [diff] [blame] | 48 | import java.io.IOException; |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 49 | import java.util.Collection; |
| 50 | import java.util.HashMap; |
| 51 | import java.util.HashSet; |
| 52 | import java.util.Map; |
| 53 | import java.util.Set; |
| 54 | import java.util.concurrent.ExecutorService; |
| 55 | import java.util.concurrent.Executors; |
| 56 | |
Jonathan Hart | 51539b8 | 2015-10-29 09:53:04 -0700 | [diff] [blame] | 57 | import static com.google.common.base.Preconditions.checkNotNull; |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 58 | import static org.onlab.util.Tools.groupedThreads; |
Jonathan Hart | 51539b8 | 2015-10-29 09:53:04 -0700 | [diff] [blame] | 59 | import static org.slf4j.LoggerFactory.getLogger; |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 60 | |
| 61 | /** |
| 62 | * SNMP alarms provider. |
Andrea Campanella | 3eca4a8 | 2016-02-10 17:35:14 -0800 | [diff] [blame] | 63 | * @deprecated 1.5.0 Falcon, not compliant with ONOS SB and driver architecture. |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 64 | */ |
Andrea Campanella | 3eca4a8 | 2016-02-10 17:35:14 -0800 | [diff] [blame] | 65 | @Deprecated |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 66 | @Component(immediate = true) |
kmcpeake | 899ea8b | 2016-01-04 15:00:45 +0000 | [diff] [blame] | 67 | @Service |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 68 | public class SnmpAlarmProviderService extends AbstractProvider implements AlarmProvider { |
| 69 | |
| 70 | private final Logger log = getLogger(getClass()); |
| 71 | |
kmcpeake | 899ea8b | 2016-01-04 15:00:45 +0000 | [diff] [blame] | 72 | private final InternalDeviceListener internalDeviceListener = new InternalDeviceListener(); |
| 73 | |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 74 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 75 | protected CoreService coreService; |
| 76 | |
| 77 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 78 | protected DeviceService deviceService; |
| 79 | |
| 80 | private ApplicationId appId; |
| 81 | |
| 82 | private final ISnmpSessionFactory sessionFactory; |
| 83 | |
| 84 | // TODO convert to standard ONOS listener service approach ? |
| 85 | protected Set<AlarmListener> alarmEventListener = Sets.newHashSet(); |
| 86 | |
| 87 | private ExecutorService eventHandlingExecutor; |
| 88 | |
| 89 | // TODO Could be replaced with a service lookup, and bundles per device variant. |
| 90 | Map<String, SnmpDeviceAlarmProvider> providers = new HashMap<>(); |
| 91 | |
Andrea Campanella | 3eca4a8 | 2016-02-10 17:35:14 -0800 | [diff] [blame] | 92 | @Deprecated |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 93 | public SnmpAlarmProviderService() { |
| 94 | super(new ProviderId("snmp", "org.onosproject.provider.alarm")); |
kmcpeake | 899ea8b | 2016-01-04 15:00:45 +0000 | [diff] [blame] | 95 | log.info("SnmpAlarmProviderService ..."); |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 96 | sessionFactory = new SnmpSessionFactory( |
| 97 | new DefaultSnmpConfigurationFactory(new V2cSnmpConfiguration())); |
| 98 | providers.put("1.3.6.1.4.1.18070.2.2", new Bti7000SnmpAlarmProvider()); |
| 99 | providers.put("1.3.6.1.4.1.20408", new NetSnmpAlarmProvider()); |
| 100 | } |
| 101 | |
| 102 | @Activate |
| 103 | public void activate(ComponentContext context) { |
| 104 | appId = coreService.registerApplication("org.onosproject.snmp"); |
| 105 | eventHandlingExecutor = Executors.newSingleThreadExecutor( |
| 106 | groupedThreads("onos/alarms", "event-handler")); |
kmcpeake | 899ea8b | 2016-01-04 15:00:45 +0000 | [diff] [blame] | 107 | deviceService.addListener(internalDeviceListener); |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 108 | log.info("activated SNMP provider with appId = {} and context props {}", appId, context.getProperties()); |
| 109 | modified(context); |
| 110 | |
| 111 | log.info("Started"); |
| 112 | } |
| 113 | |
| 114 | @Deactivate |
| 115 | public void deactivate() { |
| 116 | log.info("deactivate SNMP provider {}", appId); |
kmcpeake | 899ea8b | 2016-01-04 15:00:45 +0000 | [diff] [blame] | 117 | deviceService.removeListener(internalDeviceListener); |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | @Modified |
| 121 | public void modified(ComponentContext context) { |
| 122 | log.info("modified {}", context); |
| 123 | |
| 124 | if (context == null) { |
| 125 | log.info("No configuration file"); |
| 126 | } |
| 127 | |
| 128 | } |
| 129 | |
| 130 | @Override |
| 131 | public void triggerProbe(DeviceId deviceId) { |
| 132 | log.info("SNMP walk request for alarms at deviceId={}", deviceId); |
| 133 | if (!isSnmpDevice(deviceId)) { |
| 134 | log.info("Ignore non-snmp device!"); |
| 135 | return; |
| 136 | } |
| 137 | String[] deviceComponents = deviceId.toString().split(":"); |
| 138 | Set<Alarm> alarms = new HashSet<>(Sets.newHashSet()); |
| 139 | |
| 140 | if (deviceComponents.length > 1) { |
| 141 | String ipAddress = deviceComponents[1]; |
| 142 | String port = deviceComponents[2]; |
| 143 | ISnmpConfiguration config = new V2cSnmpConfiguration(); |
| 144 | config.setPort(Integer.parseInt(port)); |
| 145 | |
| 146 | try (ISnmpSession session = getSessionFactory().createSession(config, ipAddress)) { |
| 147 | // Each session will be auto-closed. |
Jonathan Hart | 51539b8 | 2015-10-29 09:53:04 -0700 | [diff] [blame] | 148 | String deviceOid = session.identifyDevice(); |
| 149 | alarms.addAll(getAlarmsForDevice(deviceOid, session, deviceId)); |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 150 | log.info("SNMP walk completed ok for deviceId={}", deviceId); |
| 151 | } catch (IOException | RuntimeException ex) { |
| 152 | log.error("Failed to walk device.", ex.getMessage()); |
| 153 | log.debug("Detailed problem was ", ex); |
| 154 | alarms.add( |
| 155 | buildWalkFailedAlarm(deviceId) |
| 156 | ); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | AlarmEvent alarmEvent = new AlarmEvent(alarms, deviceId); |
| 161 | |
| 162 | alarmEventListener.stream().forEach((listener) -> { |
| 163 | listener.event(alarmEvent); |
| 164 | log.info("Successfully event with discovered alarms for deviceId={} to {}", deviceId, listener); |
| 165 | }); |
| 166 | |
| 167 | } |
| 168 | |
| 169 | private static DefaultAlarm buildWalkFailedAlarm(DeviceId deviceId) { |
| 170 | return new DefaultAlarm.Builder( |
| 171 | deviceId, "SNMP alarm retrieval failed", |
| 172 | Alarm.SeverityLevel.CRITICAL, |
| 173 | System.currentTimeMillis()).build(); |
| 174 | } |
| 175 | |
| 176 | protected ISnmpSessionFactory getSessionFactory() { |
| 177 | return sessionFactory; |
| 178 | } |
| 179 | |
Jonathan Hart | 51539b8 | 2015-10-29 09:53:04 -0700 | [diff] [blame] | 180 | private Collection<Alarm> getAlarmsForDevice(String deviceOid, ISnmpSession session, |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 181 | DeviceId deviceID) throws IOException { |
| 182 | Collection<Alarm> alarms = new HashSet<>(); |
Jonathan Hart | 51539b8 | 2015-10-29 09:53:04 -0700 | [diff] [blame] | 183 | if (providers.containsKey(deviceOid)) { |
| 184 | alarms.addAll(providers.get(deviceOid).getAlarms(session, deviceID)); |
kmcpeake | b172d5f | 2015-12-10 11:30:43 +0000 | [diff] [blame] | 185 | } |
| 186 | return alarms; |
| 187 | } |
| 188 | |
| 189 | @Override |
| 190 | public void addAlarmListener(AlarmListener listener) { |
| 191 | alarmEventListener.add(checkNotNull(listener, "Listener cannot be null")); |
| 192 | } |
| 193 | |
| 194 | @Override |
| 195 | public void removeAlarmListener(AlarmListener listener) { |
| 196 | alarmEventListener.remove(checkNotNull(listener, "Listener cannot be null")); |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | * Internal listener for device service events. |
| 201 | */ |
| 202 | private class InternalDeviceListener implements DeviceListener { |
| 203 | |
| 204 | @Override |
| 205 | public void event(DeviceEvent event) { |
| 206 | log.info("InternalDeviceListener has got event from device-service{} with ", event); |
| 207 | eventHandlingExecutor.execute(() -> { |
| 208 | try { |
| 209 | DeviceId deviceId = event.subject().id(); |
| 210 | log.info("From device {}", deviceId); |
| 211 | if (!isSnmpDevice(deviceId)) { |
| 212 | log.info("Ignore non-snmp device event for {}", deviceId); |
| 213 | return; |
| 214 | } |
| 215 | |
| 216 | switch (event.type()) { |
| 217 | case DEVICE_ADDED: |
| 218 | case DEVICE_UPDATED: |
| 219 | case DEVICE_AVAILABILITY_CHANGED: |
| 220 | if (deviceService.isAvailable(event.subject().id())) { |
| 221 | triggerProbe(deviceId); |
| 222 | } |
| 223 | break; |
| 224 | case DEVICE_REMOVED: |
| 225 | case DEVICE_SUSPENDED: |
| 226 | default: |
| 227 | // Could potentially remove all alarms when eg DEVICE_REMOVED or DEVICE_SUSPENDED |
| 228 | // however for now ignore and fall through |
| 229 | break; |
| 230 | } |
| 231 | } catch (Exception e) { |
| 232 | log.warn("Failed to process {}", event, e); |
| 233 | } |
| 234 | }); |
| 235 | } |
| 236 | |
| 237 | } |
| 238 | |
| 239 | private static boolean isSnmpDevice(DeviceId deviceId) { |
| 240 | return deviceId.uri().getScheme().equalsIgnoreCase("snmp"); |
| 241 | } |
| 242 | } |