/* * 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], 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; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.util.AutoApproveConfig; import org.hyperic.util.config.ConfigResponse; import org.hyperic.hq.product.HypericOperatingSystem; import org.hyperic.hq.product.PlatformDetector; import org.hyperic.hq.product.PlatformResource; import org.hyperic.hq.product.PluginException; import org.hyperic.hq.product.ProductPlugin; import org.hyperic.hq.product.ServerDetector; import org.hyperic.hq.product.AutoinventoryPluginManager; import org.hyperic.hq.product.PluginNotFoundException; /** * The Scanner class performs the actual auto-inventory system scan. */ public class Scanner { private static final Log _log = LogFactory.getLog(Scanner.class.getName()); private ScanConfiguration _scanConfig = null; private ScanListener _scanListener = null; /** The auto-approval configuration instance */ private AutoApproveConfig _autoApproveConfig; private volatile ScanState _state = new ScanState(); private volatile boolean _isInterrupted = false; private AutoinventoryPluginManager _pluginManager = null; /** * Create a new Scanner with the specified configuration. * @param scanConfig The configuration to use when * scanning. * @param listener The class to notify when various scan events * occur, such as scan completion. * @param apm The autoinventory plugin manager. */ public Scanner (ScanConfiguration scanConfig, ScanListener listener, AutoinventoryPluginManager apm, AutoApproveConfig autoApproveConfig) { _scanConfig = scanConfig; _scanListener = listener; _pluginManager = apm; if (_scanConfig.getIsDefaultScan()) _state.setIsDefaultScan(true); _autoApproveConfig = autoApproveConfig; } public boolean getIsInterrupted () { return _isInterrupted; } public static PlatformResource detectPlatform(AutoinventoryPluginManager apm, ConfigResponse config) throws AutoinventoryException { String platformType = HypericOperatingSystem.getInstance().getName(); PlatformDetector detector; String type=null; boolean isDevice; if (config != null) { type = config.getValue(ProductPlugin.PROP_PLATFORM_TYPE); } if (type == null) { type = platformType; } isDevice = !type.equals(platformType); if (isDevice && _log.isDebugEnabled() && config != null) { String fqdn = config.getValue(ProductPlugin.PROP_PLATFORM_FQDN); String addr = config.getValue(ProductPlugin.PROP_PLATFORM_IP); _log.debug("Running discovery for another platform: " + type + "=" + fqdn + "/" + addr); } try { detector = (PlatformDetector)apm.getPlugin(type); } catch (PluginNotFoundException e) { if (isDevice) { detector = new PlatformDetector(); //default } else { throw new AutoinventoryException("PlatformDetector not found: " + type); } } try { return detector.getPlatformResource(config); } catch (PluginException e) { throw new AutoinventoryException(e.getMessage(), e); } } /** * Get the current state of the scan. Note that the ScanState * object returned from this method may be modified after * it is returned. Callers who want to persist the state should * acquire the object's monitor (via a synchronized block) * before writing the object out. * * @return The current state of the scan. */ public ScanState getScanState () { return _state; } public void start() { ConfigResponse platformConfig = _scanConfig.getConfigResponse(); _isInterrupted = false; try { _state.initStartTime(); // We do this first because we want to make sure the // ScanState knows about the scan methods so that // if a "status" command is issued rapidly after // a "start" command, the client won't get a // "scan not yet started" message. It could still happen of course, // but by putting this first we minimize the chances. _state.setScanMethods(_scanConfig.getScanMethodNames()); if ( _isInterrupted ) { setStateInterrupted(); return; } PlatformResource pValue = detectPlatform(_pluginManager, platformConfig); //default platform config to the platform values we just discovered. if (_scanConfig.getIsDefaultScan() && (platformConfig == null)) { platformConfig = new ConfigResponse(); platformConfig.setValue(ProductPlugin.PROP_PLATFORM_FQDN, pValue.getFqdn()); platformConfig.setValue(ProductPlugin.PROP_PLATFORM_NAME, pValue.getFqdn()); platformConfig.setValue(ProductPlugin.PROP_PLATFORM_TYPE, pValue.getPlatformTypeName()); } _state.setPlatform(pValue); if ( _isInterrupted ) { setStateInterrupted(); return; } ServerSignature[] serverSigs = _scanConfig.getServerSignatures(); // If there are no server signatures, then stop scanning now, and // set the appropriate flag in the scan state. if ( serverSigs == null || serverSigs.length == 0 ) { _state.setAreServersIncluded(false); _log.warn("No server signatures were found."); return; } ServerDetector[] serverDetectors = loadDetectors(pValue.getPlatformTypeName(), serverSigs); if ( serverDetectors == null || serverDetectors.length == 0 ) { _log.warn("No server detectors were loaded."); } ScanMethod scanMethod; ScanMethodState[] smStates = _state.getScanMethodStates(); for ( int i=0; i<smStates.length; i++ ) { if ( _isInterrupted ) { setStateInterrupted(); return; } scanMethod = _state.findScanMethod(smStates[i].getMethodClass()); scanMethod.init(this, _scanConfig.getScanMethodConfig(scanMethod), _autoApproveConfig); try { scanMethod.scan(platformConfig, serverDetectors); } catch ( Exception e ) { _log.error("Error during inventory scan: " + e, e); _state.addScanException(scanMethod, e); } } } catch ( Exception global ) { _log.error("Global error during inventory scan: " + global, global); _state.setGlobalException(global); } finally { if ( _isInterrupted ) { setStateInterrupted(); return; } _state.setIsDone(); _state.initEndTime(); notifyScanComplete(); } } private void setStateInterrupted () { _state.setIsInterrupted(); _state.setIsDone(); } public void stop() { _isInterrupted = true; } /** * Load the server detectors for the given set of server signatures. * @param serverSigs An array of ServerSignature objects. * @return An array of ServerDetector objects. */ private ServerDetector[] loadDetectors(String type, ServerSignature[] serverSigs) throws AutoinventoryException { ServerDetector detector; List<ServerDetector> detectorList = new ArrayList<ServerDetector>(); String pluginName = null; int i; try { for ( i=0; i<serverSigs.length; i++ ) { pluginName = serverSigs[i].getServerTypeName(); try { detector = (ServerDetector)_pluginManager.getPlatformPlugin(type, pluginName); detector.setAutoApproveConfig(_autoApproveConfig); } catch (PluginNotFoundException ne) { //plugins are not required to support AI _log.warn(ne.getMessage()); continue; } detectorList.add(detector); } } catch ( Exception e ) { String msg = "Error loading server detector class for plugin: '" + pluginName + "'"; throw new AutoinventoryException(msg, e); } Collections.sort(detectorList, new Comparator<ServerDetector>() { public int compare(ServerDetector detector1, ServerDetector detector2) { int order1 = detector1.getScanOrder(); int order2 = detector2.getScanOrder(); return order1 - order2; } }); return detectorList.toArray(new ServerDetector[detectorList.size()]); } private void notifyScanComplete () { try { _scanListener.scanComplete(_state); } catch (Exception e) { _log.error("Error in ScanListener.scanComplete", e); } } public boolean equals ( Object o ) { if (o instanceof Scanner) { Scanner s = (Scanner) o; return s._scanConfig.equals(_scanConfig) && s._pluginManager == _pluginManager && s._scanListener == _scanListener; } return false; } }