/* * RHQ Management Platform * Copyright (C) 2005-2011 Red Hat, Inc. * 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 version 2 of the License. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.plugins.apache.util; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.sigar.SigarProxy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.event.Event; import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.resource.ProcessScan; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.pluginapi.availability.AvailabilityCollectorRunnable; import org.rhq.core.pluginapi.availability.AvailabilityContext; import org.rhq.core.pluginapi.availability.AvailabilityFacet; import org.rhq.core.pluginapi.event.EventContext; import org.rhq.core.pluginapi.event.EventPoller; import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; import org.rhq.core.pluginapi.inventory.PluginContainerDeployment; import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; import org.rhq.core.pluginapi.operation.OperationResult; import org.rhq.core.system.ProcessInfo; import org.rhq.core.system.SystemInfo; import org.rhq.core.system.SystemInfoFactory; import org.rhq.core.system.pquery.ProcessInfoQuery; import org.rhq.plugins.apache.ApacheServerComponent; import org.rhq.plugins.apache.ApacheServerDiscoveryComponent; import org.rhq.plugins.apache.parser.ApacheDirectiveTree; import org.rhq.plugins.platform.PlatformComponent; /** * * * @author Lukas Krejci */ public class ApacheExecutionUtil { private static final Log LOG = LogFactory.getLog(ApacheExecutionUtil.class); private ResourceType apacheServerResourceType; private ApacheServerComponent serverComponent; private ResourceContext<PlatformComponent> resourceContext; private String serverRootPath; private String exePath; private String httpdConfPath; private String snmpHost; private int snmpPort; private String pingUrl; public enum ExpectedApacheState { RUNNING, STOPPED }; public ApacheExecutionUtil(ResourceType apacheServerResourceType, String serverRootPath, String exePath, String httpdConfPath, String pingUrl, String snmpHost, int snmpPort) { this.apacheServerResourceType = apacheServerResourceType; this.serverRootPath = serverRootPath; this.exePath = exePath; this.httpdConfPath = httpdConfPath; this.snmpHost = snmpHost; this.snmpPort = snmpPort; this.pingUrl = pingUrl; } public void init() throws Exception { ApacheServerDiscoveryComponent discoveryComponent = new ApacheServerDiscoveryComponent(); SystemInfo systemInfo = SystemInfoFactory.createSystemInfo(); ResourceDiscoveryContext<PlatformComponent> discoveryContext = new ResourceDiscoveryContext<PlatformComponent>( apacheServerResourceType, null, null, systemInfo, scanProcesses(systemInfo), null, PluginContainerDeployment.AGENT); Configuration config = discoveryContext.getDefaultPluginConfiguration(); config.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SERVER_ROOT, serverRootPath)); config.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_EXECUTABLE_PATH, exePath)); config.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_HTTPD_CONF, httpdConfPath)); config.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SNMP_AGENT_HOST, snmpHost)); config.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SNMP_AGENT_PORT, snmpPort)); config.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_URL, pingUrl)); DiscoveredResourceDetails result = discoveryComponent.discoverResource(config, discoveryContext); serverComponent = new ApacheServerComponent(); Resource resource = new Resource(result.getResourceKey(), null, apacheServerResourceType); resource.setPluginConfiguration(config); resourceContext = new ResourceContext<PlatformComponent>(resource, null, null, discoveryComponent, systemInfo, null, null, null, new EventContext() { @Override public void unregisterEventPoller(@NotNull String eventType, @NotNull String sourceLocation) { } @Override public void unregisterEventPoller(@NotNull String eventType) { } @Override public void registerEventPoller(@NotNull EventPoller poller, int pollingInterval, @NotNull String sourceLocation) { } @Override public void registerEventPoller(@NotNull EventPoller poller, int pollingInterval) { } @Override public void publishEvent(@NotNull Event event) { } @Override @Nullable public SigarProxy getSigar() { return null; } }, null, null, new AvailabilityContext() { @Override public void requestAvailabilityCheck() { } @Override public AvailabilityType getLastReportedAvailability() { return AvailabilityType.UP; } @Override public void enable() { } @Override public void disable() { } @Override public AvailabilityCollectorRunnable createAvailabilityCollectorRunnable( AvailabilityFacet availChecker, long interval) { return null; } }, null, null); serverComponent.start(resourceContext); } public void invokeOperation(ExpectedApacheState desiredState, String operation) throws Exception { int i = 0; while (i < 10) { OperationResult res = serverComponent.invokeOperation(operation, new Configuration()); LOG.debug("Invoked operation '" + operation + "' on " + resourceContext.getResourceKey() + " (waiting for " + desiredState + "), attempt " + i + ": " + res.getComplexResults().getMap().toString()); //wait for max 30s for the operation to "express" itself int w = 0; ProcessInfo pi; while (w < 30) { pi = getResourceContext().getNativeProcess(); switch (desiredState) { case RUNNING: if (pi != null && pi.isRunning()) { return; } break; case STOPPED: if (pi == null || !pi.isRunning()) { return; } } Thread.sleep(1000); ++w; } ++i; LOG.warn("httpd process is in an unexpected state after invoking the '" + operation + "' operation on " + resourceContext.getResourceKey() + " but the operation didn't throw any exception. I will retry at most ten times and then fail loudly. This has been attempt no. " + i); } throw new IllegalStateException( "Failed to start the httpd process even after 10 retries without the apache component complaining. This is super strange."); } public ResourceContext<PlatformComponent> getResourceContext() { return resourceContext; } public ApacheDirectiveTree getRuntimeConfiguration() { return serverComponent.parseRuntimeConfiguration(true); } public ApacheServerComponent getServerComponent() { return serverComponent; } private List<ProcessScanResult> scanProcesses(SystemInfo systemInfo) { List<ProcessScanResult> scanResults = new ArrayList<ProcessScanResult>(); Set<ProcessScan> processScans = apacheServerResourceType.getProcessScans(); if (processScans != null && !processScans.isEmpty()) { ProcessInfoQuery piq = new ProcessInfoQuery(systemInfo.getAllProcesses()); for (ProcessScan processScan : processScans) { List<ProcessInfo> queryResults = piq.query(processScan.getQuery()); if ((queryResults != null) && (queryResults.size() > 0)) { for (ProcessInfo autoDiscoveredProcess : queryResults) { scanResults.add(new ProcessScanResult(processScan, autoDiscoveredProcess)); } } } } return scanResults; } }