/*******************************************************************************
* ===========================================================
* Ankush : Big Data Cluster Management Solution
* ===========================================================
*
* (C) Copyright 2014, by Impetus Technologies
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL v3) as
* published by the Free Software Foundation;
*
* This software 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
******************************************************************************/
package com.impetus.ankush2.agent;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Semaphore;
import net.neoremind.sshxcute.core.Result;
import net.neoremind.sshxcute.core.SSHExec;
import net.neoremind.sshxcute.exception.TaskExecFailException;
import net.neoremind.sshxcute.task.CustomTask;
import net.neoremind.sshxcute.task.impl.ExecCommand;
import com.impetus.ankush.AppStoreWrapper;
import com.impetus.ankush.common.config.ConfigurationReader;
import com.impetus.ankush.common.domain.AppConf;
import com.impetus.ankush.common.exception.AnkushException;
import com.impetus.ankush.common.scripting.AnkushTask;
import com.impetus.ankush.common.scripting.impl.AppendFileUsingEcho;
import com.impetus.ankush.common.scripting.impl.MakeDirectory;
import com.impetus.ankush.common.scripting.impl.Move;
import com.impetus.ankush.common.scripting.impl.PrependFile;
import com.impetus.ankush.common.scripting.impl.Remove;
import com.impetus.ankush.common.scripting.impl.ReplaceText;
import com.impetus.ankush.common.scripting.impl.Untar;
import com.impetus.ankush.common.service.GenericManager;
import com.impetus.ankush.common.utils.FileUtils;
import com.impetus.ankush.common.utils.JsonMapperUtil;
import com.impetus.ankush2.constant.Constant;
import com.impetus.ankush2.constant.Constant.Strings.ExceptionsMessage;
import com.impetus.ankush2.framework.AbstractDeployer;
import com.impetus.ankush2.framework.config.ClusterConfig;
import com.impetus.ankush2.framework.config.ComponentConfig;
import com.impetus.ankush2.framework.config.NodeConfig;
import com.impetus.ankush2.logger.AnkushLogger;
import com.impetus.ankush2.utils.AnkushUtils;
// Responsible for Agent and preprocessor deployment.
public class AgentDeployer extends AbstractDeployer {
/** Method to add process name in the agent.properties file. */
public static final String AGENT_PROPERTY_FILE_PATH = "$HOME/.ankush/agent/conf/agent.properties";
public static final String ANKUSH_SERVER_PROCSS_NAME = "ankush.jar";
public static final String AGENT_BUNDLE_NAME = "agent.tar.gz";
public static final String AGENT_VERSION_FILENAME = "VERSION.txt";
private static final String CRON_TARGET_TEXT_JAVA = "JAVA_HOME";
private static final String CRON_TARGET_TEXT_USERNAME = "USER_NAME";
/** The log. */
private AnkushLogger logger = new AnkushLogger(AgentDeployer.class);
private String agentHomeDir;
final static ConfigurationReader ankushConf = AppStoreWrapper
.getAnkushConfReader();
// Creating agent bundle path.
private final static String agentBundlePath = AppStoreWrapper
.getResourcePath() + AnkushConstant.Agent.Keys.AGENT_TAR;
private final static String AGENT_DAEMON_CLASS = ankushConf
.getStringValue(AnkushConstant.Agent.Keys.AGENT_DAEMON_CLASS);
private ClusterConfig clusterConfig;
private void setClusterAndLogger(ClusterConfig clusterConfig) {
this.clusterConfig = clusterConfig;
this.agentHomeDir = clusterConfig.getComponents()
.get(Constant.Component.Name.AGENT).getInstallPath()
+ AgentConstant.Relative_Path.AGENT_HOME_DIR;
// setting logger config.
logger.setCluster(clusterConfig);
}
@Override
public boolean createConfig(ClusterConfig clusterConfig) {
this.setClusterAndLogger(clusterConfig);
return true;
}
@Override
public boolean validate(ClusterConfig clusterConfig) {
this.setClusterAndLogger(clusterConfig);
// validate java on all nodes
final Semaphore semaphore = new Semaphore(clusterConfig.getNodes()
.size());
final ComponentConfig javaConf = clusterConfig.getJavaConf();
boolean status = false;
try {
// validate java on all nodes
for (final NodeConfig nodeConfig : clusterConfig.getNodes()
.values()) {
// acuiring the semaphore
semaphore.acquire();
// starting a thread to start pre-processing on node.
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
validateJava(javaConf, nodeConfig);
if (nodeConfig.getStatus()) {
logger.info("Validating java done.",
getComponentName(),
nodeConfig.getHost());
} else {
logger.info("Validating java failed.",
getComponentName(),
nodeConfig.getHost());
}
} catch (Exception e) {
logger.error(
"Exception in validating Java."
+ Constant.Strings.ExceptionsMessage.VIEW_SERVER_LOGS,
Constant.Component.Name.AGENT,
nodeConfig.getHost(), e);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
// waiting for all semaphores to finish the installation.
semaphore.acquire(clusterConfig.getNodes().size());
// getting the status on behalf of if status is false on a single
// node, final status will be false as JAVA needs to be same on all
// the nodes
status = getStatus(clusterConfig.getNodes());
} catch (Exception e) {
logger.error(e.getMessage(), this.getComponentName());
}
if (!status) {
logger.error("Validating Java failed.", this.getComponentName());
this.clusterConfig.addError(this.getComponentName(),
"Validating Java failed.");
}
return status;
}
private void validateJava(ComponentConfig javaConf, NodeConfig nodeConfig) {
boolean status = true;
logger.info("Validating java...", this.getComponentName(),
nodeConfig.getHost());
try {
// if java is already installed
if (javaConf.isRegister()) {
//check for java/bin existence at the user given Java Path and run jav --version command
// JavaValidator javaValidator = new JavaValidator(
// nodeConfig.getConnection());
// // validate java home
// if (!javaValidator.validate(clusterConfig.getJavaConf()
// .getHomeDir())) {
// clusterConfig.addError(nodeConfig.getHost(),
// this.getComponentName(), javaValidator.getErrMsg());
// logger.error(javaValidator.getErrMsg(),
// this.getComponentName(), nodeConfig.getHost());
// status = false;
// }
} else {
// validate java bundle existence in Server Repo
File f = new File(AppStoreWrapper.getServerRepoPath()
+ javaConf.getSource());
if (!f.exists()) {
String errMsg = "Given java bundle - "
+ javaConf.getSource()
+ " doesn't exist in Ankush repo : "
+ AppStoreWrapper.getServerRepoPath() + ".";
clusterConfig.addError(nodeConfig.getHost(),
this.getComponentName(), errMsg);
logger.error(errMsg, this.getComponentName(),
nodeConfig.getHost());
status = false;
}
}
} catch (Exception e) {
logger.error("Exception in validating java."
+ Constant.Strings.ExceptionsMessage.VIEW_SERVER_LOGS,
this.getComponentName(), nodeConfig.getHost(), e);
status = false;
}
nodeConfig.setStatus(status);
}
@Override
public boolean deploy(ClusterConfig config) {
// set cluster
this.setClusterAndLogger(config);
// deploy nodes
return deployNodes(this.clusterConfig);
}
private boolean deployNodes(final ClusterConfig clusterConf) {
final Semaphore semaphore = new Semaphore(clusterConf.getNodes().size());
final String deployFailureMsg = "Could not deploy Agent on node";
try {
for (final NodeConfig nodeConfig : clusterConf.getNodes().values()) {
// acuiring the semaphore
semaphore.acquire();
final AgentServiceManager agentServiceManager = new AgentServiceManager(
clusterConf);
// starting a thread to start pre-processing on node.
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
if (createAgentNode(nodeConfig)) {
agentServiceManager.startAgent(clusterConfig,
nodeConfig);
} else {
throw new AnkushException(deployFailureMsg);
}
} catch (AnkushException e) {
logger.error(e.getMessage(),
Constant.Component.Name.AGENT,
nodeConfig.getHost());
clusterConf.addError(Constant.Component.Name.AGENT,
e.getMessage());
} catch (Exception e) {
logger.error(deployFailureMsg,
Constant.Component.Name.AGENT,
nodeConfig.getHost());
clusterConf.addError(Constant.Component.Name.AGENT,
deployFailureMsg);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
// waiting for all semaphores to finish the installation.
semaphore.acquire(clusterConf.getNodes().size());
return AnkushUtils.getStatus(clusterConf.getNodes());
} catch (Exception e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT, e);
return false;
}
}
private boolean createAgentNode(NodeConfig nodeConfig) {
String agentInstallDir = clusterConfig.getComponents()
.get(Constant.Component.Name.AGENT).getInstallPath();
SSHExec connection = null;
boolean status = false;
// Log message.
String message = "Installing Ankush agent";
logger.info(message + "...", Constant.Component.Name.AGENT,
nodeConfig.getHost());
try {
connection = nodeConfig.getConnection();
if (connection == null) {
throw new AnkushException(
ExceptionsMessage.CONNECTION_NULL_STRING);
}
/* Creating the Kill Process Command for AnkushAgent */
CustomTask killProcess = new ExecCommand("sh " + this.agentHomeDir
+ AgentConstant.Relative_Path.STOP_SCRIPT);
// stopping already running agent
connection.exec(killProcess);
// backup old existing agent folder.
Move backUpAgent = new Move(agentHomeDir, agentHomeDir
+ "/../agentBackup");
// execute task.
connection.exec(backUpAgent);
logger.debug("Create directory - " + agentHomeDir,
nodeConfig.getHost());
/* make installation directory if not exists */
AnkushTask mkInstallationPath = new MakeDirectory(agentHomeDir);
status = connection.exec(mkInstallationPath).isSuccess;
if (!status) {
/*
* Throwing Progress message exception for directory creation
* failure.
*/
throw new AnkushException(
"Could not create installation and Conf directory.");
}
// upload agent bundle from the server and Extract it
logger.info("Uploading Agent...", Constant.Component.Name.AGENT,
nodeConfig.getHost());
status = uploadAndExtractAgent(nodeConfig, connection);
if (!status) {
throw new AnkushException(
"Failed to upload and Extract Agent bundle.");
}
// configure agent.properties file.
logger.info("Configuring Agent...", Constant.Component.Name.AGENT,
nodeConfig.getHost());
/* Updating agent.properties file */
status = updateAgentPropertyFile(connection, nodeConfig);
if (!status) {
throw new AnkushException("Couldn't configure Agent.");
}
// prepend agent start-script, action-script and
// log4j.properties file with Agent Install Dir
logger.info(
"Updating Agent Script files with Agent install dir...",
Constant.Component.Name.AGENT, nodeConfig.getHost());
status = updateAgentScripts(agentInstallDir, connection, status);
if (!status) {
throw new AnkushException(
"Couldn't update Agent Scripts with Agent install dir.");
}
logger.info("Creating service dir in Agent...",
Constant.Component.Name.AGENT, nodeConfig.getHost());
// Creating make service dir command.
CustomTask mkDir = new MakeDirectory(this.agentHomeDir
+ AgentConstant.Relative_Path.SERVICE_CONF_DIR);
// Execute command.
status = connection.exec(mkDir).isSuccess;
if (!status) {
throw new AnkushException(
"Couldn't create service dir in Agent install dir.");
}
status = configureJmxTrans(nodeConfig, connection, status);
if (!status) {
throw new AnkushException("Couldn't configure JMXTrans.");
}
// update agent cron file
status = updateAgentCronFile(nodeConfig, agentInstallDir,
connection, status);
if (!status) {
throw new AnkushException("Could not update agent cron file");
}
/* Setting status of the execution to the node status. */
nodeConfig.setStatus(status);
} catch (AnkushException e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getHost(), e);
nodeConfig.setStatus(false);
} catch (Exception e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getHost(), e);
nodeConfig.setStatus(false);
}
return nodeConfig.getStatus();
}
private boolean configureJmxTrans(NodeConfig nodeConfig,
SSHExec connection, boolean status) {
// configure JMXTrans only if Ganglia is availbale
if (clusterConfig.getComponents().containsKey(
Constant.Component.Name.GANGLIA)) {
String jmxTransInstallRelPath = ankushConf
.getStringValue("jmxtrans.installation.relative.path");
String jmxtransPath = agentHomeDir + jmxTransInstallRelPath;
// configure jmxtrans.
status = this.configureJmxTrans(connection, nodeConfig,
jmxtransPath, this.clusterConfig.getAuthConf()
.getPassword());
}
return status;
}
private boolean uploadAndExtractAgent(NodeConfig nodeConfig,
SSHExec connection) throws Exception, TaskExecFailException {
boolean status;
/* if directories exists at destination */
String copyJarMsg = "Copying agent bundle";
logger.info(copyJarMsg + "...", Constant.Component.Name.AGENT,
nodeConfig.getHost());
/* Uploading the jar files to node */
connection.uploadSingleDataToServer(agentBundlePath, agentHomeDir);
// untar and remove task creation.
String tarFilePath = agentHomeDir + AgentDeployer.AGENT_BUNDLE_NAME;
AnkushTask unTarTask = new Untar(tarFilePath, agentHomeDir, false);
AnkushTask removeTask = new Remove(tarFilePath);
// executing untar and task creation task.
status = connection.exec(unTarTask).isSuccess;
connection.exec(removeTask);
if (!status) {
logger.error("Could not extract agent bunble.",
Constant.Component.Name.AGENT, nodeConfig.getHost());
status = false;
}
return status;
}
private boolean updateAgentScripts(String agentInstallDir,
SSHExec connection, boolean status) throws TaskExecFailException {
// map containing filePaths and agentInstallDir line
Map<String, String> filePathAndPrependingLineMap = new HashMap<String, String>();
StringBuilder agentInstallDirVariableInLog4j = new StringBuilder(
AgentConstant.Key.JAVA_PROPERTY_AGENT_INSTALL_DIR).append("=")
.append(agentInstallDir);
StringBuilder agentInstallDirVariable = new StringBuilder(
AgentConstant.Key.INSTALL_DIR_ENV_VARIABLE_KEY).append("=")
.append(agentInstallDir);
filePathAndPrependingLineMap.put(agentHomeDir
+ AgentConstant.Relative_Path.LOG4J_PROPERTIES_FILE,
agentInstallDirVariableInLog4j.toString());
filePathAndPrependingLineMap.put(agentHomeDir
+ AgentConstant.Relative_Path.START_SCRIPT,
agentInstallDirVariable.toString());
filePathAndPrependingLineMap.put(agentHomeDir
+ AgentConstant.Relative_Path.ACTION_SCRIPT,
agentInstallDirVariable.toString());
for (String filePath : filePathAndPrependingLineMap.keySet()) {
AnkushTask ankushTask = new PrependFile(
filePathAndPrependingLineMap.get(filePath), filePath);
status = connection.exec(ankushTask).rc == 0;
if (!status) {
logger.error("Could not update " + filePath + " for Agent.");
}
}
return status;
}
private boolean updateAgentCronFile(NodeConfig nodeConfig,
String agentInstallDir, SSHExec connection, boolean status)
throws TaskExecFailException {
Map<String, String> updateCronConfMap = new LinkedHashMap<String, String>();
String javaBinDir = FileUtils
.getSeparatorTerminatedPathEntry(this.clusterConfig
.getJavaConf().getHomeDir())
+ "bin";
updateCronConfMap.put(AgentDeployer.CRON_TARGET_TEXT_JAVA, javaBinDir);
updateCronConfMap.put(AgentDeployer.CRON_TARGET_TEXT_USERNAME,
this.clusterConfig.getAuthConf().getUsername());
updateCronConfMap.put(AgentConstant.Key.INSTALL_DIR_ENV_VARIABLE_KEY,
agentInstallDir);
String filePathCronConf = agentHomeDir
+ AgentConstant.Relative_Path.CRON_CONF_FILE;
for (String targetText : updateCronConfMap.keySet()) {
AnkushTask updateCronConf = new ReplaceText(targetText,
updateCronConfMap.get(targetText), filePathCronConf, false);
if (connection.exec(updateCronConf).rc != 0) {
logger.error("Could not update " + targetText
+ " in agent cron configuration file.",
Constant.Component.Name.AGENT, nodeConfig.getHost());
status = false;
}
}
return status;
}
private boolean updateAgentPropertyFile(SSHExec connection,
NodeConfig nodeConfig) {
boolean status = false;
String agentServiceConfPath = this.agentHomeDir
+ AgentConstant.Relative_Path.SERVICE_CONF_DIR;
String agentConfFile = this.agentHomeDir
+ AgentConstant.Relative_Path.AGENT_CONF_FILE;
try {
GenericManager<AppConf, Long> appConfManager = AppStoreWrapper
.getManager("appConfManager", AppConf.class);
Properties agentProps = new Properties();
agentProps.setProperty(Constant.Properties.Agent.NODE_ID,
nodeConfig.getId().toString());
// set the cluster id
agentProps.setProperty(Constant.Properties.Agent.CLUSTER_ID,
clusterConfig.getClusterId().toString());
// set the service conf directory.
agentProps.setProperty(Constant.Properties.Agent.SERVICE_CONF_DIR,
agentServiceConfPath);
String publicIp = null;
String publicPort = null;
// if app conf manager is not null.
if (appConfManager != null) {
// Getting app conf object.
AppConf appConf = appConfManager.getByPropertyValueGuarded(
Constant.Keys.CONFKEY, Constant.Keys.SERVERIP);
// if app conf is null.
if (appConf == null) {
logger.error(
"Unable to configure the public ip/port in agent",
Constant.Component.Name.AGENT, nodeConfig.getHost());
return false;
}
// getting app conf object as map.
Map map = JsonMapperUtil.mapFromObject(appConf.getObject());
// if it contains the public ip.
if (map.containsKey(Constant.Keys.PUBLICIP)) {
publicIp = (String) map.get(Constant.Keys.PUBLICIP);
}
// if it contains the port.
if (map.containsKey(Constant.Keys.PORT)) {
publicPort = (String) map.get(Constant.Keys.PORT);
}
}
if (publicIp != null && !publicIp.isEmpty()) {
agentProps.setProperty(Constant.Properties.Agent.SERVER_IP,
publicIp);
}
if (publicPort != null && !publicPort.isEmpty()) {
agentProps.setProperty(Constant.Properties.Agent.PORT,
publicPort);
}
// Setting host ip
agentProps.setProperty("HOST_IP", nodeConfig.getHost());
// setting host public ip
agentProps.setProperty(Constant.Properties.Agent.HOST_PUBLIC_IP,
nodeConfig.getHost());
// setting host private ip
agentProps.setProperty(Constant.Properties.Agent.HOST_PRIVATE_IP,
nodeConfig.getHost());
// props file.
StringBuilder fileContent = new StringBuilder(
com.impetus.ankush2.constant.Constant.Strings.LINE_SEPERATOR);
// iterating over the properties.
for (String key : agentProps.stringPropertyNames()) {
fileContent
.append(key)
.append("=")
.append(agentProps.getProperty(key))
.append(com.impetus.ankush2.constant.Constant.Strings.LINE_SEPERATOR);
}
// Writing the agent.properties file on node
CustomTask appendTask = new AppendFileUsingEcho(
fileContent.toString(), agentConfFile);
status = (connection.exec(appendTask).rc == 0);
} catch (Exception e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getHost(), e);
}
return status;
}
private boolean configureJmxTrans(SSHExec connection,
NodeConfig nodeConfig, String jmxtransInstallPath, String password) {
try {
String targetText_DirLog = ankushConf
.getStringValue("jmx.dir.targetText.log");
String targetText_DirJson = ankushConf
.getStringValue("jmx.dir.targetText.json");
String targetText_JarFile = ankushConf
.getStringValue("jmx.dir.targetText.jarfile");
String filePath = jmxtransInstallPath
+ ankushConf.getStringValue("jmx.script.file.name");
String replacementText = "\"" + jmxtransInstallPath + "\"";
AnkushTask jmxTask = new ReplaceText(targetText_DirLog,
replacementText, filePath, false, password);
Result res = connection.exec(jmxTask);
if (!res.isSuccess) {
logger.error("Unable to update JmxTrans script file",
Constant.Component.Name.AGENT, nodeConfig.getHost());
return false;
}
jmxTask = new ReplaceText(targetText_DirJson, replacementText,
filePath, false, password);
res = connection.exec(jmxTask);
if (!res.isSuccess) {
logger.error("Unable to update JmxTrans script file",
Constant.Component.Name.AGENT, nodeConfig.getHost());
return false;
}
replacementText = "\"" + jmxtransInstallPath
+ ankushConf.getStringValue("jmx.dir.jarfile.name") + "\"";
jmxTask = new ReplaceText(targetText_JarFile, replacementText,
filePath, false, password);
res = connection.exec(jmxTask);
if (!res.isSuccess) {
logger.error("Unable to update JmxTrans script file",
Constant.Component.Name.AGENT, nodeConfig.getHost());
return false;
}
} catch (Exception e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getHost(), e);
return false;
}
return true;
}
private boolean startNode(NodeConfig nodeConfig) {
String message = "Starting Agent";
CustomTask task = new ExecCommand("sh " + this.agentHomeDir
+ AgentConstant.Relative_Path.START_SCRIPT);
// Setting the start progress message for activity startup.
logger.info(message + "...", Constant.Component.Name.AGENT,
nodeConfig.getHost());
SSHExec connection = null;
try {
// Connection with node via SSH connection
connection = nodeConfig.getConnection();
// if connected
if (connection != null) {
Result result = connection.exec(task);
// nodeConfig.setStatus(result.isSuccess);
} else {
// nodeConfig.setStatus(false);
logger.error(ExceptionsMessage.CONNECTION_NULL_STRING,
Constant.Component.Name.AGENT, nodeConfig.getHost());
}
} catch (Exception e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getHost(), e);
// nodeConfig.setStatus(false);
}
// return nodeConfig.getStatus();
return true;
}
@Override
public boolean undeploy(ClusterConfig conf) {
this.setClusterAndLogger(conf);
logger.info("Undeploying Agent...", Constant.Component.Name.AGENT);
return undeployNodes(conf);
}
private boolean undeployNodes(ClusterConfig conf) {
try {
final Semaphore semaphore = new Semaphore(conf.getNodes().size());
for (final NodeConfig nc : conf.getNodes().values()) {
semaphore.acquire();
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
removeNode(nc);
} catch (Exception e) {
logger.error(e.getMessage(), e);
nc.setStatus(false);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
semaphore.acquire(conf.getNodes().size());
return AnkushUtils.getStatus(conf.getNodes());
} catch (InterruptedException e) {
logger.info(e.getMessage(), Constant.Component.Name.AGENT);
return false;
} catch (Exception e) {
logger.info(e.getMessage(), Constant.Component.Name.AGENT);
return false;
}
}
private void removeNode(NodeConfig nodeConfig) {
SSHExec connection = null;
boolean statusFlag = true;
// Setting the start progress message for activity startup.
try {
// Connection with node via SSH connection
connection = nodeConfig.getConnection();
if (connection != null) {
AgentServiceManager agentServiceManager = new AgentServiceManager(
clusterConfig);
logger.info("Stopping Agent...", Constant.Component.Name.AGENT,
nodeConfig.getHost());
// stopping Agent
agentServiceManager.stopAgent(clusterConfig, nodeConfig);
logger.info(
"Removing Agent home dir - "
+ clusterConfig.getAgentHomeDir(),
Constant.Component.Name.AGENT, nodeConfig.getHost());
// Removing agent directory
AnkushTask removeAgentDir = new Remove(
clusterConfig.getAgentHomeDir());
if (connection.exec(removeAgentDir).rc != 0) {
logger.error(
"Couldn't remove Agent : "
+ clusterConfig.getAgentHomeDir(),
Constant.Component.Name.AGENT,
nodeConfig.getPublicHost());
}
} else {
logger.error(ExceptionsMessage.CONNECTION_NULL_STRING,
Constant.Component.Name.AGENT,
nodeConfig.getPublicHost());
}
} catch (AnkushException e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getPublicHost(), e);
statusFlag = false;
} catch (Exception e) {
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getPublicHost(), e);
statusFlag = false;
}
nodeConfig.setStatus(statusFlag);
}
private boolean stopNode(NodeConfig nodeConfig) {
// Log message.
String message = "Stopping agent";
/* Creating the Kill Process Command for AnkushAgent */
CustomTask killProcess = new ExecCommand("sh " + this.agentHomeDir
+ AgentConstant.Relative_Path.STOP_SCRIPT);
/* Setting the start progress message for activity startup. */
logger.info(message + "...", Constant.Component.Name.AGENT,
nodeConfig.getPublicHost());
boolean statusFlag = false;
SSHExec connection = null;
try {
/* Connection with node via SSH connection */
connection = nodeConfig.getConnection();
/* if connected */
if (connection != null) {
/* Executing the Kill Process Task for AnkushAgent. */
Result result = connection.exec(killProcess);
statusFlag = result.isSuccess;
} else {
logger.error(ExceptionsMessage.CONNECTION_NULL_STRING,
Constant.Component.Name.AGENT,
nodeConfig.getPublicHost());
}
} catch (Exception e) {
statusFlag = false;
logger.error(e.getMessage(), Constant.Component.Name.AGENT,
nodeConfig.getHost(), e);
}
nodeConfig.setStatus(statusFlag);
return statusFlag;
}
@Override
public boolean unregister(ClusterConfig conf) {
return undeploy(conf);
}
@Override
public boolean start(ClusterConfig conf) {
// set clusterConfig
this.setClusterAndLogger(conf);
final Semaphore semaphore = new Semaphore(clusterConfig.getNodes()
.size());
try {
for (final NodeConfig nodeConfig : clusterConfig.getNodes()
.values()) {
// acuiring the semaphore
semaphore.acquire();
// starting a thread to start pre-processing on node.
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
if (!startNode(nodeConfig)) {
logger.error("Could not start Agent on node",
Constant.Component.Name.AGENT,
nodeConfig.getHost());
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
// waiting for all semaphores to finish the installation.
semaphore.acquire(clusterConfig.getNodes().size());
} catch (Exception e) {
logger.error(e.getMessage(), e);
return false;
}
return AnkushUtils.getStatus(clusterConfig.getNodes());
}
@Override
public boolean stop(ClusterConfig conf) {
// set clusterConfig and logger
this.setClusterAndLogger(conf);
final Semaphore semaphore = new Semaphore(clusterConfig.getNodes()
.size());
try {
for (final NodeConfig nodeConfig : clusterConfig.getNodes()
.values()) {
// acuiring the semaphore
semaphore.acquire();
// starting a thread to start pre-processing on node.
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
if (!stopNode(nodeConfig)) {
logger.error("Could not stop Agent on node",
Constant.Component.Name.AGENT,
nodeConfig.getHost());
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
// waiting for all semaphores to finish the installation.
semaphore.acquire(clusterConfig.getNodes().size());
} catch (Exception e) {
logger.error(e.getMessage(), e);
return false;
}
return AnkushUtils.getStatus(clusterConfig.getNodes());
}
@Override
public boolean addNode(ClusterConfig conf, ClusterConfig newConf) {
this.setClusterAndLogger(conf);
return deployNodes(newConf);
}
@Override
public boolean removeNode(ClusterConfig conf, Collection<String> nodes) {
this.setClusterAndLogger(conf);
try {
final Semaphore semaphore = new Semaphore(nodes.size());
for (final String host : nodes) {
semaphore.acquire();
final NodeConfig nc = conf.getNodes().get(host);
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
removeNode(nc);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
semaphore.acquire(nodes.size());
return AnkushUtils.getStatus(conf, nodes);
} catch (InterruptedException e) {
logger.info(e.getMessage(), Constant.Component.Name.AGENT);
return false;
} catch (Exception e) {
logger.info(e.getMessage(), Constant.Component.Name.AGENT);
return false;
}
}
@Override
public boolean removeNode(ClusterConfig conf, ClusterConfig newConf) {
this.setClusterAndLogger(conf);
return undeployNodes(newConf);
}
@Override
public boolean register(ClusterConfig conf) {
return deploy(clusterConfig);
}
public boolean getStatus(Map<String, NodeConfig> map) {
boolean status = true;
for (NodeConfig nodeConf : map.values()) {
if (!nodeConf.getStatus()) {
return false;
}
}
return status;
}
}