/*
* 'SNMPCollector.java' NOTE: This copyright does *not* cover user programs that
* use HQ program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development Kit or
* the Hyperic Client Development Kit - this is merely considered normal use of
* the program, and does *not* fall under the heading of "derived work".
* Copyright (C) [2004, 2005, 2006, 2007, 2008, 2009], Hyperic, Inc. This file
* is part of HQ. HQ is free software; you can redistribute it and/or modify it
* under the terms version 2 of the GNU General Public License as published by
* the Free Software Foundation. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.plugin.netdevice;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.product.Collector;
import org.hyperic.hq.product.Metric;
import org.hyperic.hq.product.MetricValue;
import org.hyperic.hq.product.PluginException;
import org.hyperic.hq.product.SNMPMeasurementPlugin;
import org.hyperic.snmp.SNMPClient;
import org.hyperic.snmp.SNMPException;
import org.hyperic.snmp.SNMPSession;
import org.hyperic.snmp.SNMPValue;
public class SNMPCollector
extends Collector
{
protected static final String AVAILABLE_VALUES = "AvailableValues";
protected static final Double DEFAULT_AVAILABLE_VALUE = 1d;
protected static final String PROP_COLUMN = "snmpColumn";
protected Properties _props;
protected SNMPClient _client;
protected Set<Double> availableValues = new HashSet<Double>();
private static final String[][] DEFAULT_PROPS = { { SNMPClient.PROP_IP, SNMPClient.DEFAULT_IP },
{ SNMPClient.PROP_PORT, SNMPClient.DEFAULT_PORT_STRING },
{ SNMPClient.PROP_VERSION, SNMPClient.VALID_VERSIONS[1] },
{ SNMPClient.PROP_COMMUNITY, SNMPClient.DEFAULT_COMMUNITY } };
protected Log getLog() {
return LogFactory.getLog(getClass().getName());
}
protected String getInfo() {
String info = _props.getProperty(SNMPClient.PROP_IP) + ":" + _props.getProperty(SNMPClient.PROP_PORT) + " " +
_props.getProperty(SNMPClient.PROP_VERSION) + "," + _props.getProperty(SNMPClient.PROP_COMMUNITY);
return info;
}
protected boolean isEmpty(List list, String name) {
boolean isEmpty;
if (list == null) {
isEmpty = true;
} else {
isEmpty = list.isEmpty();
}
if (isEmpty) {
setErrorMessage("No data returned for: " + name);
}
return isEmpty;
}
protected boolean isEmpty(Map map, String name) {
boolean isEmpty;
if (map == null) {
isEmpty = true;
} else {
isEmpty = map.isEmpty();
}
if (isEmpty) {
setErrorMessage("No data returned for: " + name);
}
return isEmpty;
}
/**
* These values represent the Availability metric values that constitute an AVAIL_UP value.
* Default value of 1 is added to the set if the property is not specified.
*/
protected void initAvailableValues() {
String delimitedValueString = getPlugin().getTypeProperty(
AVAILABLE_VALUES);
if (delimitedValueString == null) {
// in most cases 1 means Availability metric is available.
availableValues.add(DEFAULT_AVAILABLE_VALUE);
} else {
String[] values = delimitedValueString.split(",");
for (String value : values) {
try {
availableValues.add(Double.parseDouble(value.trim()));
} catch (Exception e) {
getLog().error(
"Invalid value set for " + AVAILABLE_VALUES + ": "
+ value);
}
}
}
}
protected boolean isAvailability() {
String availName = getPlugin().getTypeProperty(Metric.ATTR_AVAIL);
if (availName == null) {
return false;
}
return getCounterName().equals(availName);
}
protected String getColumnName() {
return _props.getProperty(PROP_COLUMN);
}
protected String getCounterName() {
return _props.getProperty(PROP_COLUMN);
}
protected String getIndexName() {
return _props.getProperty(SNMPMeasurementPlugin.PROP_INDEX_NAME);
}
protected String getColumnIndex(SNMPValue val) {
String oid = val.getOID();
int last = oid.lastIndexOf('.');
return oid.substring(last + 1);
}
protected Map getIndexedColumn(SNMPSession session, String name) throws SNMPException {
return getIndexedColumn(session, name, true);
}
protected Map getIndexedColumn(SNMPSession session, String name, boolean asString) throws SNMPException {
// Expose walk() in SNMPClient...
List column;
Map values = new HashMap();
try {
column = session.getBulk(name);
if (isEmpty(column, name)) {
return values;
}
for (int i = 0; i < column.size(); i++) {
SNMPValue val = (SNMPValue) column.get(i);
String ix = getColumnIndex(val);
Object obj;
if (asString) {
obj = val.toString().trim();
} else {
obj = val;
}
values.put(ix, obj);
}
} catch (Exception e) {
getLog().error("getBulk ( " + name + " ): " + e);
return null;
}
return values;
}
public interface ColumnValueConverter {
public double convert(String index, SNMPValue value) throws Exception;
}
public static class GenericColumnValueConverter implements ColumnValueConverter {
public double convert(String index, SNMPValue value) throws Exception {
return value.toLong();
}
}
protected SNMPSession getSession() throws Exception {
try {
return _client.getSession(_props);
} catch (Exception e) {
setErrorMessage(e.getMessage());
throw e;
}
}
protected boolean isTotalCounter(String name) {
return false;
}
protected void collectIndexedColumn() {
collectIndexedColumn(new GenericColumnValueConverter());
}
protected void collectIndexedColumn(ColumnValueConverter converter) {
String indexName = getIndexName();
String columnName = getColumnName();
String counterName = getCounterName();
boolean isAvail = isAvailability();
SNMPSession session;
List column;
Map indexNames;
boolean doTotal = isTotalCounter(counterName);
double total = 0.0;
try {
session = getSession();
indexNames = getIndexedColumn(session, indexName);
column = session.getBulk(columnName);
} catch (Exception e) {
return;
}
if (isEmpty(column, columnName) || isEmpty(indexNames, indexName)) {
return;
}
for (int i = 0; i < column.size(); i++) {
SNMPValue val = (SNMPValue) column.get(i);
String ix = getColumnIndex(val);
String name = (String) indexNames.get(ix);
try {
double value = converter.convert(ix, val);
if (doTotal && (value > 0.0) && (value != MetricValue.VALUE_NONE)) {
total += value;
}
setValue(name + "." + counterName, value);
if (isAvail) {
if (availableValues.contains(value)) {
setValue(name + "." + Metric.ATTR_AVAIL,
Metric.AVAIL_UP);
} else {
setValue(name + "." + Metric.ATTR_AVAIL,
Metric.AVAIL_DOWN);
}
}
} catch (Exception e) {
getLog().warn(columnName + ".convert failed for " + name + "@" + getInfo());
}
}
if (doTotal) {
setValue("_TOTAL_" + "." + counterName, total);
}
}
public void init() throws PluginException {
_client = new SNMPClient();
_props = getProperties();
initAvailableValues();
for (int i = 0; i < DEFAULT_PROPS.length; i++) {
String key = DEFAULT_PROPS[i][0];
String val = DEFAULT_PROPS[i][1];
if (_props.getProperty(key) == null) {
_props.setProperty(key, val);
}
}
setSource(getInfo());
try {
init(_client.getSession(_props));
} catch (SNMPException e) {
throw new PluginException(getInfo() + ": " + e.getMessage());
}
}
protected void init(SNMPSession session) throws PluginException {
}
public void collect() {
}
}