/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2009-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) 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 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) 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 OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.poller.monitors;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Map;
import org.opennms.core.utils.InetAddressUtils;
import org.opennms.core.utils.LogUtils;
import org.opennms.core.utils.ParameterMap;
import org.opennms.core.utils.TimeoutTracker;
import org.opennms.netmgt.config.WmiPeerFactory;
import org.opennms.netmgt.model.PollStatus;
import org.opennms.netmgt.poller.Distributable;
import org.opennms.netmgt.poller.MonitoredService;
import org.opennms.netmgt.poller.NetworkInterface;
import org.opennms.netmgt.poller.NetworkInterfaceNotSupportedException;
import org.opennms.protocols.wmi.WmiAgentConfig;
import org.opennms.protocols.wmi.WmiException;
import org.opennms.protocols.wmi.WmiManager;
import org.opennms.protocols.wmi.WmiParams;
import org.opennms.protocols.wmi.WmiResult;
/**
* This class is designed to be used by the service poller framework to test
* the availability of WMI services on remote interfaces. The class
* implements the IPv4Monitor interface that allows it to be used along
* with other plug-ins by the service poller framework.
*
* @author <A HREF="mailto:matt.raykowski@gmail.com">Matt Raykowski</A>
* @author <A HREF="http://www.opennms.org/">OpenNMS </A>
*/
@Distributable
public class WmiMonitor extends AbstractServiceMonitor {
private final static String DEFAULT_WMI_CLASS = "Win32_ComputerSystem";
private final static String DEFAULT_WMI_OBJECT = "Status";
private final static String DEFAULT_WMI_COMP_VAL = "OK";
private final static String DEFAULT_WMI_MATCH_TYPE = "all";
private final static String DEFAULT_WMI_COMP_OP = "EQ";
private final static String DEFAULT_WMI_WQL = "NOTSET";
/**
* {@inheritDoc}
*
* Poll the specified address for service availability. During the poll an
* attempt is made to connect the WMI agent on the specified host. If the
* connection request is successful, the parameters are parsed and turned
* into <code>WmiParams</code> and a check is performed against the
* remote WMI service. If the <code>WmiManager</code> responds
* with a <code>WmiResult</code> containing a result code of
* <code>WmiResult.RES_STATE_OK</code> then we have determined that
* we are talking to a valid service and we set the service status to
* SERVICE_AVAILABLE and return.
*/
@Override
public PollStatus poll(final MonitoredService svc, final Map<String,Object> parameters) {
// Holds the response reason.
String reason = null;
// Used to exit the retry loop early, if possible.
int serviceStatus = PollStatus.SERVICE_UNAVAILABLE;
// This will hold the data the server sends back.
WmiResult response = null;
// Used to track how long the request took.
Double responseTime = null;
final NetworkInterface<InetAddress> iface = svc.getNetInterface();
// Get the address we're going to poll.
final InetAddress ipv4Addr = iface.getAddress();
// Validate the interface type.
if (iface.getType() != NetworkInterface.TYPE_INET) {
throw new NetworkInterfaceNotSupportedException("Unsupported interface type, only TYPE_INET currently supported");
}
final WmiAgentConfig agentConfig = WmiPeerFactory.getInstance().getAgentConfig(ipv4Addr);
String matchType = DEFAULT_WMI_MATCH_TYPE;
String compVal = DEFAULT_WMI_COMP_VAL;
String compOp = DEFAULT_WMI_COMP_OP;
String wmiClass = DEFAULT_WMI_CLASS;
String wmiObject = DEFAULT_WMI_OBJECT;
String wmiWqlStr = DEFAULT_WMI_WQL;
if (parameters != null) {
if (parameters.get("timeout") != null) {
int timeout = ParameterMap.getKeyedInteger(parameters, "timeout", agentConfig.getTimeout());
agentConfig.setTimeout(timeout);
}
if (parameters.get("retry") != null) {
int retries = ParameterMap.getKeyedInteger(parameters, "retry", agentConfig.getRetries());
agentConfig.setRetries(retries);
}
if (parameters.get("username") != null) {
String user = ParameterMap.getKeyedString(parameters, "username", agentConfig.getUsername());
agentConfig.setUsername(user);
}
if (parameters.get("password") != null) {
String pass = ParameterMap.getKeyedString(parameters, "password", agentConfig.getPassword());
agentConfig.setUsername(pass);
}
if (parameters.get("domain") != null) {
String domain = ParameterMap.getKeyedString(parameters, "domain", agentConfig.getDomain());
agentConfig.setUsername(domain);
}
matchType = ParameterMap.getKeyedString(parameters, "matchType", DEFAULT_WMI_MATCH_TYPE);
compVal = ParameterMap.getKeyedString(parameters, "compareValue", DEFAULT_WMI_COMP_VAL);
compOp = ParameterMap.getKeyedString(parameters, "compareOp", DEFAULT_WMI_COMP_OP);
wmiWqlStr = ParameterMap.getKeyedString(parameters, "wql", DEFAULT_WMI_WQL);
wmiClass = ParameterMap.getKeyedString(parameters, "wmiClass", DEFAULT_WMI_CLASS);
wmiObject = ParameterMap.getKeyedString(parameters, "wmiObject", DEFAULT_WMI_OBJECT);
}
final TimeoutTracker tracker = new TimeoutTracker(parameters, agentConfig.getRetries(), agentConfig.getTimeout());
final String hostAddress = InetAddressUtils.str(ipv4Addr);
LogUtils.debugf(this, "poll: address = %s, user = %s, %s", hostAddress, agentConfig.getUsername(), tracker);
WmiManager mgr = null;
for (tracker.reset(); tracker.shouldRetry() && serviceStatus != PollStatus.SERVICE_AVAILABLE; tracker.nextAttempt()) {
try {
tracker.startAttempt();
LogUtils.debugf(this, "poll: creating WmiManager object.");
// Create a client, set up details and connect.
mgr = new WmiManager(hostAddress, agentConfig.getUsername(), agentConfig.getPassword(), agentConfig.getDomain(), matchType);
mgr.setTimeout(tracker.getSoTimeout());
mgr.init();
LogUtils.debugf(this, "Completed initializing WmiManager object.");
// We are connected, so upgrade status to unresponsive
serviceStatus = PollStatus.SERVICE_UNRESPONSIVE;
// Set up the parameters the client will use to validate the response.
// Note: We will check and see if we were provided with a WQL string.
WmiParams clientParams = null;
if(DEFAULT_WMI_WQL.equals(wmiWqlStr)) {
clientParams = new WmiParams(WmiParams.WMI_OPERATION_INSTANCEOF, compVal, compOp, wmiClass, wmiObject);
LogUtils.debugf(this, "Attempting to perform operation: \\\\%s\\%s", wmiClass, wmiObject);
} else {
// Create parameters to run a WQL query.
clientParams = new WmiParams(WmiParams.WMI_OPERATION_WQL, compVal, compOp, wmiWqlStr, wmiObject);
LogUtils.debugf(this, "Attempting to perform operation: %s", wmiWqlStr);
}
// Send the request to the server and receive the response..
response = mgr.performOp(clientParams);
LogUtils.debugf(this, "Received result: %s", response);
// Now save the time it took to process the check command.
responseTime = tracker.elapsedTimeInMillis();
if (response == null) {
continue;
}
final ArrayList<Object> wmiObjects = response.getResponse();
final StringBuffer reasonBuffer = new StringBuffer();
// If there's no WQL string then use the class\object name as the result message
if (DEFAULT_WMI_WQL.equals(wmiWqlStr)) {
reasonBuffer.append("Result for ").append(wmiClass).append("\\").append(wmiObject);
} else {
// Otherwise, print the WQL statement in the result message
reasonBuffer.append("Result for \"").append(wmiWqlStr).append("\"");
}
if (response.getResultCode() == WmiResult.RES_STATE_OK) {
serviceStatus = PollStatus.SERVICE_AVAILABLE;
reasonBuffer.append(": ").append(wmiObjects.get(0));
} else if (response.getResultCode() == WmiResult.RES_STATE_CRIT) {
serviceStatus = PollStatus.SERVICE_UNAVAILABLE;
// set this to null so we don't try to save data when the node is down
responseTime = null;
}
reason = reasonBuffer.toString();
} catch (final WmiException e) {
LogUtils.debugf(this, e, "WMI Poller received exception from client.");
reason = "WmiException: " + e.getMessage();
} finally {
if (mgr != null) {
try {
mgr.close();
} catch (WmiException e) {
LogUtils.warnf(this, e, "An error occurred closing the WMI Manager.");
}
}
}
} // end for(;;)
return PollStatus.get(serviceStatus, reason, responseTime);
}
}