/*
* 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.control.agent.server;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.agent.AgentAPIInfo;
import org.hyperic.hq.agent.AgentConfig;
import org.hyperic.hq.agent.AgentRemoteException;
import org.hyperic.hq.agent.AgentRemoteValue;
import org.hyperic.hq.agent.server.AgentDaemon;
import org.hyperic.hq.agent.server.AgentServerHandler;
import org.hyperic.hq.agent.server.AgentStartException;
import org.hyperic.hq.agent.server.AgentStorageProvider;
import org.hyperic.hq.agent.server.AgentTransportLifecycle;
import org.hyperic.hq.bizapp.client.ControlCallbackClient;
import org.hyperic.hq.bizapp.client.StorageProviderFetcher;
import org.hyperic.hq.bizapp.shared.lather.ControlSendCommandResult_args;
import org.hyperic.hq.control.agent.ControlCommandsAPI;
import org.hyperic.hq.control.agent.client.ControlCommandsClient;
import org.hyperic.hq.control.agent.commands.ControlPluginAdd_args;
import org.hyperic.hq.control.agent.commands.ControlPluginAdd_result;
import org.hyperic.hq.control.agent.commands.ControlPluginCommand_args;
import org.hyperic.hq.control.agent.commands.ControlPluginCommand_result;
import org.hyperic.hq.control.agent.commands.ControlPluginRemove_args;
import org.hyperic.hq.control.agent.commands.ControlPluginRemove_result;
import org.hyperic.hq.product.ControlPluginManager;
import org.hyperic.hq.product.ProductPlugin;
import org.hyperic.util.MultiRuntimeException;
import org.hyperic.util.config.ConfigResponse;
public class ControlCommandsServer
implements AgentServerHandler
{
// possibly make this configurable at some point
private static final String PROP_BACKUPDIR = "file_backup";
private ControlCommandsAPI verAPI; // Common API specifics
private Log log; // Our log
private AgentConfig bootConfig; // Agent boot config
private AgentStorageProvider storage; // Our storage provider
private ControlCommandsService controlCommandsService;
public ControlCommandsServer() {
this.verAPI = new ControlCommandsAPI();
this.bootConfig = null;
this.log = LogFactory.getLog(ControlCommandsServer.class);
}
public AgentAPIInfo getAPIInfo(){
return this.verAPI;
}
public String[] getCommandSet(){
return ControlCommandsAPI.commandSet;
}
public AgentRemoteValue dispatchCommand(String cmd, AgentRemoteValue args,
InputStream in, OutputStream out)
throws AgentRemoteException
{
if (cmd.equals(this.verAPI.command_controlPluginAdd)) {
ControlPluginAdd_args ca = new ControlPluginAdd_args(args);
return this.controlPluginAdd(ca);
} else if (cmd.equals(this.verAPI.command_controlPluginCommand)) {
ControlPluginCommand_args ca =
new ControlPluginCommand_args(args);
return this.controlPluginCommand(ca);
} else if (cmd.equals(this.verAPI.command_controlPluginRemove)) {
ControlPluginRemove_args ca =
new ControlPluginRemove_args(args);
return this.controlPluginRemove(ca);
} else {
throw new AgentRemoteException("Unexpected command: " + cmd);
}
}
public void startup(AgentDaemon agent)
throws AgentStartException
{
this.bootConfig = agent.getBootConfig();
Properties bootProps = bootConfig.getBootProperties();
// get our storage provider
try {
this.storage = agent.getStorageProvider();
} catch (Exception e) {
throw new AgentStartException("Unable to get storage " +
"provider: " + e.getMessage());
}
// setup control manager
ControlPluginManager controlManager;
ControlCallbackClient client;
try {
controlManager =
(ControlPluginManager)agent.
getPluginManager(ProductPlugin.TYPE_CONTROL);
client = setupClient();
} catch (Exception e) {
// Problem loading the plugin jars
throw new AgentStartException("Unable to load control jars: " +
e.getMessage());
}
controlCommandsService = new ControlCommandsService(controlManager, client);
AgentTransportLifecycle agentTransportLifecycle;
try {
agentTransportLifecycle = agent.getAgentTransportLifecycle();
} catch (Exception e) {
throw new AgentStartException("Unable to get agent transport lifecycle: "+
e.getMessage());
}
log.info("Registering Control Commands Service with Agent Transport");
try {
agentTransportLifecycle.registerService(ControlCommandsClient.class, controlCommandsService);
} catch (Exception e) {
throw new AgentStartException("Failed to register Control Commands Service.", e);
}
this.log.info("Control Commands Server started up");
}
public final void postInitActions() throws AgentStartException {
try{
this.processPersistedControlResponses() ;
} catch (Exception e) {
throw new AgentStartException("Failed to send persisted control response to the server.", e) ;
}//EO catch block
}//EOM
private final void processPersistedControlResponses() throws Exception {
//determine whether there are any persisted contorl responses to be posted to the server
final File persistedControlResponsesDir = new File(AgentConfig.PERSISTED_CONTROL_RESPONSES_DIR) ;
File[] tempControlResponses = null ;
if(!persistedControlResponsesDir.exists() || (tempControlResponses = persistedControlResponsesDir.listFiles()) == null) {
log.info("No persisted Control responses were found") ;
return ;
}//EO if the the persisted control responses dir exists
//else
final File[] controlResponses = tempControlResponses ;
final Runnable persistControlResponsesActionSender = new Runnable() {
public final void run() {
MultiRuntimeException thrown = null ;
ObjectInputStream ois = null ;
ControlSendCommandResult_args controlResponse = null ;
int counter = 0 ;
boolean errorOccured = false;
final ControlCallbackClient client = controlCommandsService.getClient() ;
for(File controlResponseFile : controlResponses) {
try{
ois = new ObjectInputStream(new FileInputStream(controlResponseFile)) ;
controlResponse = (ControlSendCommandResult_args) ois.readObject() ;
log.info("About to post persisted control response " + controlResponse.getId()) ;
client.controlSendCommandResult(controlResponse) ;
counter++ ;
}catch(Throwable t) {
t.printStackTrace() ;
thrown = MultiRuntimeException.newMultiRuntimeException(thrown, t, "Deserialization Error for Persisted Control Response " + controlResponseFile) ;
errorOccured = true ;
}finally{
try{
if(ois != null) ois.close() ;
}catch(IOException ioe) {
thrown = MultiRuntimeException.newMultiRuntimeException(thrown, ioe, "Error while closing FileInputStream" + controlResponseFile) ;
}//EO inner catch block
//if no error had occured, delete the file
if(!errorOccured) {
log.info("Deleting Persisted Control Response file " + controlResponseFile + ". Delete Successed: " + controlResponseFile.delete()) ;
}//EO if successful
errorOccured = false ;
}//EO catch block
}//EO while there are more control response files
log.info("Successfully sent " + counter + " persisted control response(s), while encountered errors for " + (thrown != null ? thrown.size() : 0)) ;
if(thrown != null) log.error(thrown) ;
}//EOM
};//EO anonymous Runnable
final Thread t = new Thread(persistControlResponsesActionSender, "PersistedControlResponses_Sender") ;
t.start() ;
}//EOM
public void shutdown() {
this.log.info("Control Commands Server shut down");
}
private ControlCallbackClient setupClient()
throws AgentStartException
{
StorageProviderFetcher fetcher;
fetcher = new StorageProviderFetcher(this.storage);
return new ControlCallbackClient(fetcher);
}
private ControlPluginAdd_result
controlPluginAdd(ControlPluginAdd_args args)
throws AgentRemoteException
{
ConfigResponse config = args.getConfigResponse();
String name = args.getName();
String type = args.getType();
controlCommandsService.controlPluginAdd(name, type, config);
ControlPluginAdd_result result = new ControlPluginAdd_result();
return result;
}
private ControlPluginCommand_result
controlPluginCommand(ControlPluginCommand_args args)
throws AgentRemoteException
{
String pluginName = args.getPluginName();
String pluginType = args.getPluginType();
String id = args.getId();
String pluginAction = args.getPluginAction();
String[] pluginArgs = args.getArgs();
controlCommandsService.controlPluginCommand(pluginName,
pluginType,
id,
pluginAction,
pluginArgs);
return new ControlPluginCommand_result();
}
private ControlPluginRemove_result
controlPluginRemove(ControlPluginRemove_args args)
throws AgentRemoteException
{
String pluginName = args.getPluginName();
controlCommandsService.controlPluginRemove(pluginName);
return new ControlPluginRemove_result();
}
}