/* * 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-2008], 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.autoinventory.agent.server; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.agent.AgentRemoteException; import org.hyperic.hq.agent.AgentRemoteValue; import org.hyperic.hq.autoinventory.AutoinventoryException; import org.hyperic.hq.autoinventory.ScanConfiguration; import org.hyperic.hq.autoinventory.ScanConfigurationCore; import org.hyperic.hq.autoinventory.ScanManager; import org.hyperic.hq.autoinventory.ScanMethod; import org.hyperic.hq.autoinventory.ScanState; import org.hyperic.hq.autoinventory.ScanStateCore; import org.hyperic.hq.autoinventory.ServerSignature; import org.hyperic.hq.autoinventory.agent.client.AICommandsClient; import org.hyperic.hq.autoinventory.agent.client.AICommandsUtils; import org.hyperic.hq.autoinventory.scanimpl.NullScan; import org.hyperic.hq.autoinventory.scanimpl.WindowsRegistryScan; import org.hyperic.hq.product.AutoServerDetector; import org.hyperic.hq.product.AutoinventoryPluginManager; import org.hyperic.hq.product.GenericPlugin; import org.hyperic.hq.product.HypericOperatingSystem; import org.hyperic.hq.product.PlatformDetector; import org.hyperic.hq.product.ProductPlugin; import org.hyperic.hq.product.RegistryServerDetector; import org.hyperic.hq.product.ServerDetector; import org.hyperic.hq.product.TypeInfo; import org.hyperic.util.ArrayUtil; import org.hyperic.util.config.ConfigResponse; /** * The AI Commands service. */ public class AICommandsService implements AICommandsClient { private static final Log _log = LogFactory.getLog(AICommandsService.class); private final AutoinventoryPluginManager _pluginManager; private final RuntimeAutodiscoverer _rtAutodiscoverer; private final ScanManager _scanManager; private final Object _lock = new Object(); private ScanState _mostRecentState; public AICommandsService(AutoinventoryPluginManager pluginManager, RuntimeAutodiscoverer rtAutodiscoverer, ScanManager scanManager) { _pluginManager = pluginManager; _rtAutodiscoverer = rtAutodiscoverer; _scanManager = scanManager; } /** * @see org.hyperic.hq.autoinventory.agent.client.AICommandsClient#getScanStatus() */ public ScanStateCore getScanStatus() throws AgentRemoteException { return getScanStatus(true); } ScanStateCore getScanStatus(boolean interruptHangingScan) throws AgentRemoteException { if (interruptHangingScan) { _scanManager.interruptHangingScan(); } ScanState state; try { state = doGetScanStatus(); // Fix bug 7004 -- set endtime so that duration appears // correctly on the serverside when viewing status // Fix bug 7134 -- only set endtime if the scan is not yet done if ( !state.getIsDone() ) state.initEndTime(); } catch (Exception e) { _log.error("Error getting scan state.", e); throw new AgentRemoteException("Error getting scan status: " + e.toString()); } return state.getCore(); } /** * @see org.hyperic.hq.autoinventory.agent.client.AICommandsClient#pushRuntimeDiscoveryConfig(int, int, java.lang.String, java.lang.String, org.hyperic.util.config.ConfigResponse) */ public void pushRuntimeDiscoveryConfig(int type, int id, String typeName, String name, ConfigResponse response) throws AgentRemoteException { AgentRemoteValue args = AICommandsUtils.createArgForRuntimeDiscoveryConfig(type, id, typeName, name, response); pushRuntimeDiscoveryConfig(args, true); } void pushRuntimeDiscoveryConfig(AgentRemoteValue args, boolean interruptHangingScan) throws AgentRemoteException { if (interruptHangingScan) { _scanManager.interruptHangingScan(); } _rtAutodiscoverer.updateConfig(args); } /** * @see org.hyperic.hq.autoinventory.agent.client.AICommandsClient#startScan(org.hyperic.hq.autoinventory.ScanConfigurationCore) */ public void startScan(ScanConfigurationCore scanConfigCore) throws AgentRemoteException { startScan(scanConfigCore, true); } void startScan(ScanConfigurationCore scanConfigCore, boolean interruptHangingScan) throws AgentRemoteException { if (interruptHangingScan) { _scanManager.interruptHangingScan(); } if ( scanConfigCore == null ) { throw new AgentRemoteException("No scan configuration exists."); } ScanConfiguration scanConfig = new ScanConfiguration(scanConfigCore); startScan(scanConfig); } void startScan(ScanConfiguration scanConfig) { _log.debug("[startScan] scanConfig="+scanConfig); ConfigResponse platformConfig = scanConfig.getConfigResponse(); String platformType = null; boolean isDefault = scanConfig.getIsDefaultScan(); String type = isDefault ? "auto" : "user"; ServerSignature[] autoSigs, rgySigs; autoSigs = rgySigs = scanConfig.getServerSignatures(); //user scan, default to all if no servers specified. boolean userDefault = ((autoSigs == null) || (autoSigs.length == 0)); if (platformConfig != null) { platformType = platformConfig.getValue(ProductPlugin.PROP_PLATFORM_TYPE); } if (platformType == null) { platformType = HypericOperatingSystem.getInstance().getName(); } boolean isWin32 = PlatformDetector.isWin32(platformType); if (isDefault || userDefault) { autoSigs = getAutoScanners(platformType); if (isWin32) { rgySigs = getWindowsRegistryScanners(); } } addScanners(scanConfig, new NullScan(), autoSigs); if (isWin32 && (rgySigs != null)) { addScanners(scanConfig, new WindowsRegistryScan(), rgySigs); } if (_log.isDebugEnabled()) { ServerSignature[] sigs = scanConfig.getServerSignatures(); ArrayList types = new ArrayList(); for (int i=0; i<sigs.length; i++) { types.add(sigs[i].getServerTypeName()); } _log.debug(type + " scan for: " + types); } synchronized ( _scanManager ) { _scanManager.queueScan(scanConfig); } } /** * @see org.hyperic.hq.autoinventory.agent.client.AICommandsClient#stopScan() */ public void stopScan() throws AgentRemoteException { stopScan(true); } void stopScan(boolean interruptHangingScan) throws AgentRemoteException { if (interruptHangingScan) { _scanManager.interruptHangingScan(); } try { if ( !doStopScan() ) { throw new AgentRemoteException("No scan is currently running."); } } catch ( Exception e ){ _log.error("Error stopping scan.", e); throw new AgentRemoteException("Error stopping scan: " + e.toString()); } } void setMostRecentState(ScanState scanState) { synchronized (_lock) { _mostRecentState = scanState; } } private ServerSignature[] getAutoScanners(String type) { ArrayList sigs = new ArrayList(); Map plugins = _pluginManager.getPlatformPlugins(type); //XXX hack. we want the jboss plugin to run before tomcat //so jboss can drop a hint about the embedded tomcat. TreeSet detectors = new TreeSet(new Comparator() { public int compare(Object o1, Object o2) { String name1 = ((GenericPlugin)o1).getName(); String name2 = ((GenericPlugin)o2).getName(); return name1.compareTo(name2); } }); for (Iterator i = plugins.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry)i.next(); ServerDetector detector; if (!(entry.getValue() instanceof ServerDetector)) { continue; } detector = (ServerDetector)entry.getValue(); TypeInfo info = ((GenericPlugin)detector).getTypeInfo(); if (info.getType() != TypeInfo.TYPE_SERVER) { continue; } if (!(detector instanceof AutoServerDetector)) { continue; } detectors.add(detector); } for (Iterator i = detectors.iterator(); i.hasNext();) { ServerDetector detector = (ServerDetector)i.next(); sigs.add(detector.getServerSignature()); } return (ServerSignature[])sigs.toArray(new ServerSignature[0]); } private ServerSignature[] getWindowsRegistryScanners() { ArrayList sigs = new ArrayList(); Map plugins = _pluginManager.getPlatformPlugins(); for (Iterator it = plugins.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry)it.next(); ServerDetector detector; if (!(entry.getValue() instanceof RegistryServerDetector)) { continue; } detector = (ServerDetector)entry.getValue(); TypeInfo info = ((GenericPlugin)detector).getTypeInfo(); if (info.getType() != TypeInfo.TYPE_SERVER) { continue; } sigs.add(detector.getServerSignature()); } return (ServerSignature[])sigs.toArray(new ServerSignature[0]); } private void addScanners(ScanConfiguration scanConfig, ScanMethod method, ServerSignature[] sigs) { ServerSignature[] signatures = scanConfig.getServerSignatures(); signatures = (ServerSignature[]) ArrayUtil.combine(signatures, sigs); scanConfig.setServerSignatures(signatures); scanConfig.setScanMethodConfig(method, new ConfigResponse()); } /** * @return true if a scan was actually running, false otherwise. */ private boolean doStopScan() { // A best-effort attempt to grab the most recent scanState we can try { doGetScanStatus(); } catch ( Exception e ) {} synchronized ( _scanManager ) { try { return _scanManager.stopScan(); } catch ( AutoinventoryException e ) { // Error stopping scan - restart the entire scan manager _log.error("Error stopping scan, restarting scan manager: " + e); _scanManager.shutdown(1000); _scanManager.startup(); } return true; } } private ScanState doGetScanStatus() throws AutoinventoryException { ScanState scanState = _scanManager.getStatus(); synchronized (_lock) { if ( scanState == null ) { if ( _mostRecentState == null ) { throw new AutoinventoryException ("No autoinventory scan has been started."); } else { return _mostRecentState; } } _mostRecentState = scanState; } return scanState; } }