/* * This file is part of the OpenNMS(R) Application. * * OpenNMS(R) is Copyright (C) 2009 The OpenNMS Group, Inc. All rights reserved. * OpenNMS(R) is a derivative work, containing both original code, included code and modified * code that was published under the GNU General Public License. Copyrights for modified * and included code are below. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * Modifications: * * 2009 Jul 8: Created file. - r.trommer@open-factory.org * * Original code base Copyright (C) 1999-2001 Oculan Corp. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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. * * For more information contact: * OpenNMS Licensing * http://www.opennms.org/ * http://www.opennms.com/ * */ package org.opennms.netmgt.poller.monitors; import java.io.IOException; import java.lang.reflect.UndeclaredThrowableException; import java.net.InetAddress; import java.util.Map; import org.apache.log4j.Level; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.ValidationException; import org.opennms.netmgt.config.SnmpPeerFactory; import org.opennms.netmgt.model.PollStatus; import org.opennms.netmgt.poller.Distributable; import org.opennms.netmgt.poller.DistributionContext; import org.opennms.netmgt.poller.MonitoredService; import org.opennms.netmgt.poller.NetworkInterface; import org.opennms.netmgt.snmp.SnmpAgentConfig; import org.opennms.netmgt.snmp.SnmpInstId; import org.opennms.netmgt.snmp.SnmpObjId; import org.opennms.netmgt.snmp.SnmpUtils; import org.opennms.netmgt.snmp.SnmpValue; import org.opennms.netmgt.utils.ParameterMap; /** *

* This class is used to monitor Dell OpenManage power supplies. The specific * OIDs referenced to "SNMP Reference Guide", available from * http://support.dell.com/support/edocs/software/svradmin/6.1/en *

* * @author Ronny Trommer * @author OpenNMS */ // this does snmp and there relies on the snmp configuration so it is not // distributable @Distributable(DistributionContext.DAEMON) final public class OpenManagePowerSupplyMonitor extends SnmpMonitorStrategy { /** * Name of monitored service. */ private static final String m_serviceName = "Dell_OpenManagePowerSupply"; /** * Interface attribute key used to store the interfaces SnmpAgentConfig * object. */ static final String SNMP_AGENTCONFIG_KEY = "org.opennms.netmgt.snmp.SnmpAgentConfig"; /** * Defines the status of all power supplies in this chassis. */ private static final String PS_STATUS_COMBINED_OID = ".1.3.6.1.4.1.674.10892.1.200.10.1.9.1"; /** * This attribute defines the index (one based) of the power supply. */ private static final String PS_INDEX_OID = ".1.3.6.1.4.1.674.10892.1.600.12.1.2"; /** * Defines the status of the power supply. */ private static final String PS_STATUS_OID = "1.3.6.1.4.1.674.10892.1.600.12.1.5"; /** * Defines the type of power supply. */ private static final String PS_TYPE_OID = "1.3.6.1.4.1.674.10892.1.600.12.1.7"; /** * Defines the location name of the power supply. */ private static final String PS_LOCATION_OID = "1.3.6.1.4.1.674.10892.1.600.12.1.8"; /** * Defines the manufacturers name for this chassis. */ private static final String MANUFACTURER_OID = ".1.3.6.1.4.1.674.10892.1.300.10.1.8.1"; /** * Defines the status of the chassis. */ private static final String MODEL_NAME_OID = "1.3.6.1.4.1.674.10892.1.300.10.1.9.1"; /** * Defines the service tag name for this chassis. */ private static final String SERVICE_TAG_OID = ".1.3.6.1.4.1.674.10892.1.300.10.1.11.1"; /** * Implement the dell status */ private enum DELL_STATUS { OTHER(1), UNKNOWN(2), OK(3), NON_CRITICAL(4), CRITICAL(5), NON_RECOVERABLE( 6); private final int state; // state code DELL_STATUS(int s) { this.state = s; } private int value() { return this.state; } }; /** * Implement the DellPowerSupplyType */ private enum DELL_PS_TYPE { OTHER(1), UNKNOWN(2), LINEAR(3), SWITCHING(4), BATTERY(5), UPS(6), CONVERTER( 7), REGULATOR(8), AC(9), DC(10), VRM(11); private final int state; // state code DELL_PS_TYPE(int s) { this.state = s; } private int value() { return this.state; } }; /** *

* Returns the name of the service that the plug-in monitors *

* * @return The service that the plug-in monitors. */ public String serviceName() { return m_serviceName; } /** *

* Initialize the service monitor. *

* * @param parameters * Not currently used. * @exception RuntimeException * Thrown if an unrecoverable error occurs that prevents * the plug-in from functioning. */ public void initialize(Map parameters) { // Initialize the SnmpPeerFactory // try { SnmpPeerFactory.init(); } catch (MarshalException ex) { log().fatal("initialize: Failed to load SNMP configuration", ex); throw new UndeclaredThrowableException(ex); } catch (ValidationException ex) { log().fatal("initialize: Failed to load SNMP configuration", ex); throw new UndeclaredThrowableException(ex); } catch (IOException ex) { log().fatal("initialize: Failed to load SNMP configuration", ex); throw new UndeclaredThrowableException(ex); } return; } /** *

* Called by the poller framework when an interface is being added to the * scheduler. Here we perform any necessary initialization to prepare the * NetworkInterface object for polling. *

* * @exception RuntimeException * Thrown if an unrecoverable error occurs that prevents * the interface from being monitored. */ public void initialize(MonitoredService svc) { NetworkInterface iface = svc.getNetInterface(); // Log4j category // // Get interface address from NetworkInterface // super.initialize(svc); InetAddress ipAddr = (InetAddress) iface.getAddress(); SnmpAgentConfig agentConfig = SnmpPeerFactory.getInstance().getAgentConfig( ipAddr); if (log().isDebugEnabled()) { log().debug("initialize: SnmpAgentConfig address: " + agentConfig); } // Add the snmp config object as an attribute of the interface // if (log().isDebugEnabled()) log().debug( "initialize: OpenManagePowerSupplyMonitor setting SNMP peer attribute for interface " + ipAddr.getHostAddress()); iface.setAttribute(SNMP_AGENTCONFIG_KEY, agentConfig); log().debug( "initialize: interface: " + agentConfig.getAddress() + " initialized."); return; } /** *

* The poll() method is responsible for polling the specified address for * SNMP service availability. *

* * @param parameters * The package parameters (timeout, retry, etc...) to be used * for this poll. * @param iface * The network interface to test the service on. * @return The availability of the interface and if a transition event * should be supressed. * @exception RuntimeException * Thrown for any uncrecoverable errors. */ public PollStatus poll(MonitoredService svc, Map parameters) { NetworkInterface iface = svc.getNetInterface(); String returnValue = new String(); PollStatus status = PollStatus.unavailable(); InetAddress ipaddr = (InetAddress) iface.getAddress(); // Initialize the messages if the session is down String psStatusCombinedTxt = "N/A"; String psStatusTxt = "N/A"; String psTypeTxt = "N/A"; String psLocTxt = "N/A"; String manufacturerName = "N/A"; String modelName = "N/A"; String serviceTagTxt = "N/A"; String psInstanceTxt = ""; // Retrieve this interface's SNMP peer object // SnmpAgentConfig agentConfig = (SnmpAgentConfig) iface.getAttribute(SNMP_AGENTCONFIG_KEY); if (agentConfig == null) throw new RuntimeException( "SnmpAgentConfig object not available for interface " + ipaddr); // set timeout and retries on SNMP peer object // agentConfig.setTimeout(ParameterMap.getKeyedInteger( parameters, "timeout", agentConfig.getTimeout())); agentConfig.setRetries(ParameterMap.getKeyedInteger( parameters, "retry", ParameterMap.getKeyedInteger( parameters, "retries", agentConfig.getRetries()))); agentConfig.setPort(ParameterMap.getKeyedInteger( parameters, "port", agentConfig.getPort())); // Establish SNMP session with interface // try { if (log().isDebugEnabled()) { log().debug("poll: SnmpAgentConfig address: " + agentConfig); } // Get the power supply status combined SnmpObjId psStatusCombinedSnmpObject = SnmpObjId.get(PS_STATUS_COMBINED_OID); SnmpValue psStatusCombined = SnmpUtils.get(agentConfig, psStatusCombinedSnmpObject); // If no chassis status is received or SNMP is not possible, // service is down if (psStatusCombined == null) { log().warn("No power supply status combined received!"); return status; } else { if (log().isDebugEnabled()) { log().debug( "poll: power supply status combined: " + psStatusCombined); } } /* * Do no unnecessary SNMP requests, if chassis status is OK, * return with service available and go away. */ if (psStatusCombined.toInt() == DELL_STATUS.OK.value()) { if (log().isDebugEnabled()) { log().debug( "poll: power supply status combined: " + psStatusCombined.toInt()); } return PollStatus.available(); } else { if (log().isDebugEnabled()) { log().debug( "poll: power supply status combined: " + psStatusCombined.toInt()); } psStatusCombinedTxt = resolveDellStatus(psStatusCombined.toInt()); status = PollStatus.down(); } // Power status combined is not OK gather some information SnmpObjId manufacturerSnmpObject = SnmpObjId.get(MANUFACTURER_OID); SnmpValue manufacturer = SnmpUtils.get(agentConfig, manufacturerSnmpObject); // Check correct MIB-Support if (manufacturer == null) { log().warn("Cannot receive manufacturer."); } else { if (log().isDebugEnabled()) { log().debug("poll: manufacturer: " + manufacturer); } manufacturerName = manufacturer.toString(); } // Get the chassis model SnmpObjId modelSnmpObject = SnmpObjId.get(MODEL_NAME_OID); SnmpValue model = SnmpUtils.get(agentConfig, modelSnmpObject); // Check correct MIB-Support if (model == null) { log().warn("Cannot receive model name."); } else { if (log().isDebugEnabled()) { log().debug("poll: model name: " + model); } modelName = model.toString(); } // Get the service tag from chassis SnmpObjId serviceTagSnmpObject = SnmpObjId.get(SERVICE_TAG_OID); SnmpValue serviceTag = SnmpUtils.get(agentConfig, serviceTagSnmpObject); // Check correct MIB-Support if (serviceTag == null) { log().warn("Cannot receive service tag"); } else { if (log().isDebugEnabled()) { log().debug("poll: service tag: " + serviceTag); } serviceTagTxt = serviceTag.toString(); } returnValue = "Combined power supply status from " + manufacturerName + " " + modelName + " with service tag " + serviceTagTxt + " is " + psStatusCombinedTxt + "."; // Do root cause analysis, get all map with all installed power supplies SnmpObjId psIdxSnmpObject = SnmpObjId.get(PS_INDEX_OID); Map psIndices = SnmpUtils.getOidValues( agentConfig, "OpenManagePowerSupplyMonitor", psIdxSnmpObject); // Check correct MIB-Support if (psIndices == null) { log().warn("Cannot receive power supply indices,"); // request for root cause failed, service down return PollStatus.unavailable(returnValue); } // Iterate over the list of power supplies for (SnmpInstId index : psIndices.keySet()) { // get the current status SnmpObjId psStatusSnmpObject = SnmpObjId.get(PS_STATUS_OID + "." + index); SnmpValue psStatus = SnmpUtils.get(agentConfig, psStatusSnmpObject); // Check correct MIB-Support if (psStatus == null) { log().warn("Cannot receive power supply status: " + index); // request failed go to next continue; } if (log().isDebugEnabled()) { log().debug("poll: power supply status: " + psStatus); } // See if the current power supply is OK if (psStatus.toInt() == DELL_STATUS.OK.value()) { log().debug( "poll: power supply status: " + resolveDellStatus(psStatus.toInt())); // power supply OK, go to the next continue; } else { // power supply not OK, resolve status code psStatusTxt = resolveDellStatus(psStatus.toInt()); if (log().isDebugEnabled()) { log().debug( "poll: power supply status: " + resolveDellStatus(psStatus.toInt())); } // Get location SnmpObjId psLocationSnmpObject = SnmpObjId.get(PS_LOCATION_OID + "." + index); SnmpValue psLocation = SnmpUtils.get(agentConfig, psLocationSnmpObject); // Check correct MIB-Support if (psLocation == null) { log().warn( "Cannot receive power supply location: " + index); continue; } psLocTxt = psLocation.toString(); SnmpObjId psTypeSnmpObject = SnmpObjId.get(PS_TYPE_OID + "." + index); SnmpValue psType = SnmpUtils.get(agentConfig, psTypeSnmpObject); // Check correct MIB-Support if (psType == null) { log().warn( "Cannot receive power supply type: " + index); continue; } psTypeTxt = resolveDellPowerSupplyType(psType.toInt()); psInstanceTxt += " Power supply " + psLocTxt + " from type " + psTypeTxt + " is " + psStatusTxt + "."; } } returnValue += psInstanceTxt + " For further information, check your OpenManage website!"; // Set service down and return gathered information status = PollStatus.unavailable(returnValue); } catch (NullPointerException e) { status = logDown(Level.WARN, "Unexpected error during SNMP poll of interface " + ipaddr.getHostAddress(), e); } catch (NumberFormatException e) { status = logDown(Level.WARN, "Number operator used on a non-number " + e.getMessage()); } catch (IllegalArgumentException e) { status = logDown(Level.WARN, "Invalid Snmp Criteria: " + e.getMessage()); } catch (Throwable t) { status = logDown(Level.WARN, "Unexpected exception during SNMP poll of interface " + ipaddr.getHostAddress(), t); } // If matchAll is set to true, then the status is set to available // above with a single match. // Otherwise, the service will be unavailable. return status; } /** * Method to resolve a given Dell status to human readable string. * * @param sc * Dell status code * @return Human readable Dell status */ private String resolveDellStatus(int sc) { String name = "N/A"; if (DELL_STATUS.OTHER.value() == sc) name = DELL_STATUS.OTHER.name(); if (DELL_STATUS.UNKNOWN.value() == sc) name = DELL_STATUS.UNKNOWN.name(); if (DELL_STATUS.OK.value() == sc) name = DELL_STATUS.OK.name(); if (DELL_STATUS.NON_CRITICAL.value() == sc) name = DELL_STATUS.NON_CRITICAL.name(); if (DELL_STATUS.CRITICAL.value() == sc) name = DELL_STATUS.CRITICAL.name(); if (DELL_STATUS.NON_RECOVERABLE.value() == sc) name = DELL_STATUS.NON_RECOVERABLE.name(); return name; } /** * Method to resolve a given Dell power supply type to human readable * string. * * @param sc * Dell status code * @return Human readable Dell status */ private String resolveDellPowerSupplyType(int sc) { String name = "N/A"; if (DELL_PS_TYPE.OTHER.value() == sc) name = DELL_PS_TYPE.OTHER.name(); if (DELL_PS_TYPE.UNKNOWN.value() == sc) name = DELL_PS_TYPE.UNKNOWN.name(); if (DELL_PS_TYPE.LINEAR.value() == sc) name = DELL_PS_TYPE.LINEAR.name(); if (DELL_PS_TYPE.SWITCHING.value() == sc) name = DELL_PS_TYPE.SWITCHING.name(); if (DELL_PS_TYPE.BATTERY.value() == sc) name = DELL_PS_TYPE.BATTERY.name(); if (DELL_PS_TYPE.UPS.value() == sc) name = DELL_PS_TYPE.UPS.name(); if (DELL_PS_TYPE.CONVERTER.value() == sc) name = DELL_PS_TYPE.CONVERTER.name(); if (DELL_PS_TYPE.REGULATOR.value() == sc) name = DELL_PS_TYPE.REGULATOR.name(); if (DELL_PS_TYPE.AC.value() == sc) name = DELL_PS_TYPE.AC.name(); if (DELL_PS_TYPE.DC.value() == sc) name = DELL_PS_TYPE.DC.name(); if (DELL_PS_TYPE.VRM.value() == sc) name = DELL_PS_TYPE.VRM.name(); return name; } }