/******************************************************************************* * 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.capsd.plugins; import java.net.InetAddress; 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.netmgt.capsd.AbstractPlugin; import org.opennms.netmgt.config.WmiPeerFactory; 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; /** * <P> * This class is designed to be used by the capabilities daemon to test whether * a WMI service is running on the remote server and if the given class/object * can be successfully retrieved from the service. * </P> * * @author <a href="mailto:matt.raykowski@gmail.com">Matt Raykowski</a> * @author <a href="http://www.opennms.org">OpenNMS</a> */ public class WmiPlugin extends AbstractPlugin { /** * The protocol supported by the plugin */ private final static String PROTOCOL_NAME = "WMI"; 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} * * Returns the name of the protocol that this plugin checks on the target * system for support. */ @Override public String getProtocolName() { return PROTOCOL_NAME; } /** * {@inheritDoc} * * Returns true if the protocol defined by this plugin is supported. If the * protocol is not supported then a false value is returned to the caller. * <P> * The WmiPlugin does not support undirected checks, we must have a map of * parameters to determine how to issue a check to the target server. */ @Override public boolean isProtocolSupported(final InetAddress address) { throw new UnsupportedOperationException("Undirected TCP checking not supported"); } /** * {@inheritDoc} * * Returns true if the protocol defined by this plugin is supported. If the * protocol is not supported then a false value is returned to the caller. * The qualifier map passed to the method is used by the plugin to return * additional information by key-name. These key-value pairs can be added to * service events if needed. * <P> * The following parameters are used by this plugin: * <UL> * <LI>wmiObject - the command to be executed on this node. * <LI>wmiClass - the command to be executed on this node. * <LI>password - used to override the default WMI password * <LI>retry - overrides the number of times to retry connecting to the * service. * <LI>timeout - tcp port timeout. * <LI>parameter - a string used for checking services. see documentation * on specific check types for use. * </UL> * Protocol will return as supported only if the result code is * <code>WmiResult.RES_STATE_OK</code> or * <code>WmiResult.RES_STATE_WARNING</code>. */ @Override public boolean isProtocolSupported(final InetAddress address, final Map<String, Object> qualifiers) { final WmiAgentConfig agentConfig = WmiPeerFactory.getInstance().getAgentConfig(address); 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 (qualifiers != null) { if (qualifiers.get("timeout") != null) { int timeout = ParameterMap.getKeyedInteger(qualifiers, "timeout", agentConfig.getTimeout()); agentConfig.setTimeout(timeout); } if (qualifiers.get("retry") != null) { int retries = ParameterMap.getKeyedInteger(qualifiers, "retry", agentConfig.getRetries()); agentConfig.setRetries(retries); } if (qualifiers.get("username") != null) { String user = ParameterMap.getKeyedString(qualifiers, "username", agentConfig.getUsername()); agentConfig.setUsername(user); } if (qualifiers.get("password") != null) { String pass = ParameterMap.getKeyedString(qualifiers, "password", agentConfig.getPassword()); agentConfig.setUsername(pass); } if (qualifiers.get("domain") != null) { String domain = ParameterMap.getKeyedString(qualifiers, "domain", agentConfig.getDomain()); agentConfig.setUsername(domain); } matchType = ParameterMap.getKeyedString(qualifiers, "matchType", DEFAULT_WMI_MATCH_TYPE); compVal = ParameterMap.getKeyedString(qualifiers, "compareValue", DEFAULT_WMI_COMP_VAL); compOp = ParameterMap.getKeyedString(qualifiers, "compareOp", DEFAULT_WMI_COMP_OP); wmiWqlStr = ParameterMap.getKeyedString(qualifiers, "wql", DEFAULT_WMI_WQL); wmiClass = ParameterMap.getKeyedString(qualifiers, "wmiClass", DEFAULT_WMI_CLASS); wmiObject = ParameterMap.getKeyedString(qualifiers, "wmiObject", DEFAULT_WMI_OBJECT); } WmiParams clientParams = null; if(wmiWqlStr.equals(DEFAULT_WMI_WQL)) { // Create the check parameters holder. clientParams = new WmiParams(WmiParams.WMI_OPERATION_INSTANCEOF, compVal, compOp, wmiClass, wmiObject); } else { // Define the WQL Query. clientParams = new WmiParams(WmiParams.WMI_OPERATION_WQL, compVal, compOp, wmiWqlStr, wmiObject); } // Perform the operation specified in the parameters. WmiResult result = isServer(address, agentConfig.getUsername(), agentConfig.getPassword(), agentConfig.getDomain(), matchType, agentConfig.getRetries(), agentConfig.getTimeout(), clientParams); // Only fail on critical and unknown returns. return (result != null && result.getResultCode() != WmiResult.RES_STATE_CRIT && result.getResultCode() != WmiResult.RES_STATE_UNKNOWN); } /** * <P> * Test to see if the passed host-port pair is an endpoint for a TCP server. * If there is a TCP server at the destination value then a connection is * made using the params variable data and a check is requested from the * remote WMI service. * </P> * * @param host * The remote host to connect to. * @param retries * The number of retries to attempt when connecting. * @param timeout * The TCP socket timeout to use. * @param params * The WMI parameters used to validate the response. * @return The WmiResult the server sent, updated by WmiManager to * contain the proper result code based on the params passed. */ private WmiResult isServer(final InetAddress host, final String user, final String pass, final String domain, final String matchType, final int retries, final int timeout, final WmiParams params) { boolean isAServer = false; WmiResult result = null; for (int attempts = 0; attempts <= retries && !isAServer; attempts++) { WmiManager mgr = null; try { // Create the WMI Manager mgr = new WmiManager(InetAddressUtils.str(host), user, pass, domain, matchType); // Connect to the WMI server. mgr.init(); // Perform the operation specified in the parameters. result = mgr.performOp(params); if(params.getWmiOperation().equals(WmiParams.WMI_OPERATION_WQL)) { LogUtils.debugf(this, "WmiPlugin: %s : %s", params.getWql(), WmiResult.convertStateToString(result.getResultCode())); } else { LogUtils.debugf(this, "\\\\%s\\%s : %s", params.getWmiClass(), params.getWmiObject(), WmiResult.convertStateToString(result.getResultCode())); } isAServer = true; } catch (final WmiException e) { LogUtils.infof(this, e, "WmiPlugin: Check failed."); isAServer = false; } finally { if (mgr != null) { try { mgr.close(); } catch (final WmiException e) { LogUtils.warnf(this, e, "An error occurred closing the WMI manager."); } } } } return result; } }