com.impetus.ankush2.ganglia.GangliaDeployer.java Source code

Java tutorial

Introduction

Here is the source code for com.impetus.ankush2.ganglia.GangliaDeployer.java

Source

/*******************************************************************************
 * ===========================================================
 * 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.ganglia;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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 org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.aspectj.util.FileUtil;

import com.impetus.ankush.AppStoreWrapper;
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.ClearFile;
import com.impetus.ankush.common.scripting.impl.ExecSudoCommand;
import com.impetus.ankush.common.scripting.impl.MakeDirectory;
import com.impetus.ankush.common.utils.FileNameUtils;
import com.impetus.ankush.common.utils.Symbols;
import com.impetus.ankush2.agent.AgentConstant;
import com.impetus.ankush2.agent.AgentUtils;
import com.impetus.ankush2.agent.ComponentService;
import com.impetus.ankush2.constant.Constant;
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;
import com.impetus.ankush2.utils.SSHUtils;

public class GangliaDeployer extends AbstractDeployer {

    private ClusterConfig clusterConf;
    private ComponentConfig compConfig;
    private Map<String, Object> advanceConf;
    /** The newClusterConf */
    private ClusterConfig newClusterConf = null;

    private String gmetadHost;

    /** GangliaDeployer logger */
    private AnkushLogger logger = new AnkushLogger(GangliaDeployer.class);

    /**
     * Setting clusterConf, componentConf and logger
     * 
     * @param clusterConf
     *            {@link ClusterConfig}
     */
    private boolean initializeDataMembers(ClusterConfig clusterConf) throws AnkushException {
        try {
            this.clusterConf = clusterConf;
            this.logger.setCluster(clusterConf);
            if (!clusterConf.getComponents().containsKey(getComponentName())) {
                throw new AnkushException(
                        "Could not find " + getComponentName() + " in cluster configuration object.");
            }
            this.compConfig = clusterConf.getComponents().get(getComponentName());

            // Initializing advancedConf to use it to for getting and setting
            // cluster level properties
            if (this.compConfig == null || this.compConfig.getAdvanceConf() == null) {
                throw new AnkushException("Could not get configuration details for " + getComponentName());
            }
            this.advanceConf = this.compConfig.getAdvanceConf();
            return true;
        } catch (AnkushException e) {
            throw e;
        } catch (Exception e) {
            throw new AnkushException("Could not initialize data members for " + getComponentName(), e);
        }
    }

    private boolean addClusterError(String error, String host) {
        return addClusterError(error, host, null);
    }

    private boolean addClusterError(String error, Throwable t) {
        return addClusterError(error, null, t);
    }

    private boolean addClusterError(String error, String host, Throwable t) {

        if (host != null) {
            this.clusterConf.addError(host, getComponentName(), error);
            logger.error(error, getComponentName(), host, t);
        } else {
            this.clusterConf.addError(getComponentName(), error);
            logger.error(error, getComponentName(), t);
        }
        return false;
    }

    @Override
    public boolean createConfig(ClusterConfig conf) {
        try {
            // Initializing data members
            if (!initializeDataMembers(conf)) {
                return false;
            }
            if (compConfig.isRegister()) {
                if (!(new GangliaRegister(clusterConf).createConfig())) {
                    return false;
                }
                gmetadHost = (String) this.advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST);
                return true;
            } else {
                // set server gmond and gmetad template configuration folder.
                // Getting resource path.
                String resourceBasePath = AppStoreWrapper.getResourcePath();
                // Setting server conf folder.
                advanceConf.put(GangliaConstants.ClusterProperties.SERVER_CONF_FOLDER,
                        FileNameUtils.convertToValidPath(resourceBasePath)
                                + GangliaConstants.CONFIG_GANGLIA_RELATIVE_PATH);
                return addGmondNodes();
            }
        } catch (AnkushException e) {
            return addClusterError(e.getMessage(), e);
        } catch (Exception e) {
            return addClusterError("There is some exception while creating configuration for deploying "
                    + getComponentName() + ". " + GangliaConstants.EXCEPTION_STRING, e);
        }
    }

    /**
     * Adding all cluster nodes to Ganglia component nodes
     * 
     * @return true , if successful
     */
    private boolean addGmondNodes() throws AnkushException {
        try {
            // Preparing Ganglia component nodes. Adding all cluster nodes to
            // Ganglia nodes
            Map<String, Map<String, Object>> compNodes = new HashMap<String, Map<String, Object>>();
            Map<String, Set<String>> roles;
            Set<String> gmondNodes = new HashSet<String>();
            for (Map.Entry<String, NodeConfig> node : clusterConf.getNodes().entrySet()) {
                compNodes.put(node.getKey(), new HashMap<String, Object>());
                roles = node.getValue().getRoles();
                if (!roles.containsKey(getComponentName())) {
                    logger.warn(
                            "Could not find any roles for " + getComponentName()
                                    + " in node's roles map, so adding an empty roles set.",
                            getComponentName(), node.getKey());
                    roles.put(getComponentName(), new HashSet<String>());
                }
                if (roles.get(getComponentName()).contains(Constant.Role.GMETAD)) {
                    // assuming that there is single Ganglia master
                    advanceConf.put(GangliaConstants.ClusterProperties.GMETAD_HOST, node.getKey());
                    gmetadHost = node.getKey();
                }
                gmondNodes.add(node.getKey());
            }

            if (gmetadHost == null || gmetadHost.isEmpty()) {
                throw new AnkushException(
                        "Could not find any node with role as " + GangliaConstants.Ganglia_Services.GangliaMaster
                                + ", so could not deploy " + getComponentName() + ".");
            }
            advanceConf.put(GangliaConstants.ClusterProperties.GMOND_SET, gmondNodes);
            compConfig.setNodes(compNodes);
            return true;
        } catch (AnkushException e) {
            throw e;
        } catch (Exception e) {
            throw new AnkushException(
                    "There is some exception while adding cluster nodes to Ganglia component nodes object. + "
                            + GangliaConstants.EXCEPTION_STRING,
                    e);
        }
    }

    @Override
    public boolean validate(ClusterConfig conf) {
        try {
            // if (!this.initializeDataMembers(conf)) {
            // return false;
            // }
            // TODO: Ganglia cluster registration validation
            if (compConfig.isRegister()) {
                return true;
            }
            return validate(compConfig.getNodes().keySet());
        } catch (AnkushException e) {
            return addClusterError(e.getMessage(), e);
        } catch (Exception e) {
            return addClusterError("There is some exception while validating nodes for " + getComponentName()
                    + " deployment." + GangliaConstants.EXCEPTION_STRING, e);
        }
    }

    @Override
    public boolean deploy(ClusterConfig conf) {
        // deploying and starting ganglia on all nodes
        return (deployNodes(conf, compConfig.getNodes()) && start(conf, compConfig.getNodes().keySet()));
    }

    @Override
    public boolean register(final ClusterConfig conf) {

        try {
            if (String.valueOf(advanceConf.get(Constant.Keys.REGISTER_LEVEL))
                    .equalsIgnoreCase(Constant.RegisterLevel.LEVEL1.toString())) {
                return true;
            }
            final String infoMsg = "Registering " + getComponentName() + "...";
            logger.info(infoMsg);
            // Getting node map for cluster deployment
            Map<String, Map<String, Object>> nodeMap = new HashMap<String, Map<String, Object>>(
                    compConfig.getNodes());

            // Node Registration process ...
            final Semaphore semaphore = new Semaphore(nodeMap.size());
            for (final String host : nodeMap.keySet()) {
                semaphore.acquire();
                AppStoreWrapper.getExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        conf.getNodes().get(host).setStatus(configureServiceMonitoring(host));
                        if (semaphore != null) {
                            semaphore.release();
                        }
                    }
                });
            }
            semaphore.acquire(nodeMap.size());

            // Return false if any of the node is not deployed.
            return AnkushUtils.getStatus(conf.getNodes());
        } catch (Exception e) {
            addClusterError("Could not register " + getComponentName(), e);
            return false;
        }
    }

    @Override
    public boolean undeploy(ClusterConfig conf) {
        try {
            // setting clusterconf, componentconf and logger
            if (!initializeDataMembers(conf)) {
                return false;
            }
            if (clusterConf.getNodes().keySet() != null || !clusterConf.getNodes().isEmpty()) {
                return removeNode(conf, clusterConf.getNodes().keySet());
            }
        } catch (Exception e) {
            addClusterError("Could not remove Ganglia. Please view server logs for more details.", e);
        }
        return false;
    }

    @Override
    public boolean unregister(final ClusterConfig conf) {

        try {
            if (String.valueOf(advanceConf.get(Constant.Keys.REGISTER_LEVEL))
                    .equalsIgnoreCase(Constant.RegisterLevel.LEVEL1.toString())) {
                return true;
            }

            if (!initializeDataMembers(conf)) {
                return false;
            }
            final String infoMsg = "Unregistering " + getComponentName() + "...";
            logger.info(infoMsg, getComponentName());
            // Getting node map for cluster deployment
            Map<String, Map<String, Object>> nodeMap = new HashMap<String, Map<String, Object>>(
                    compConfig.getNodes());

            // Node Registration process ...
            final Semaphore semaphore = new Semaphore(nodeMap.size());
            for (final String host : nodeMap.keySet()) {
                semaphore.acquire();
                AppStoreWrapper.getExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        conf.getNodes().get(host).setStatus(unregisterNode(host));
                        if (semaphore != null) {
                            semaphore.release();
                        }
                    }
                });
            }
            semaphore.acquire(nodeMap.size());

            // Return false if any of the node is not deployed.
            return AnkushUtils.getStatus(conf.getNodes());
        } catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    /**
     * unregister node
     * 
     * @param host
     *            {@link String}
     * @return <code>true</code>, if successful
     */
    private boolean unregisterNode(String host) {
        try {
            // getting connection object
            SSHExec connection = getConnection(host);
            if (connection == null) {
                addClusterError("Could not get connection.", host);
                return false;
            }
            // Removing Ganglia service.xml
            String command = "rm -rf " + clusterConf.getAgentHomeDir()
                    + AgentConstant.Relative_Path.SERVICE_CONF_DIR + getComponentName() + "."
                    + Constant.File_Extension.XML;

            execCustomtask(command, connection, host, "Could not remove " + getComponentName() + ".xml" + " file.");
            return true;
        } catch (Exception e) {
            addClusterError("Could not register node.", host, e);
            return false;
        }
    }

    @Override
    public boolean start(ClusterConfig conf) {
        return start(conf, compConfig.getNodes().keySet());
    }

    @Override
    public boolean start(final ClusterConfig conf, Collection<String> nodes) {
        final Semaphore semaphore = new Semaphore(nodes.size());
        String gangliaMaster = (String) advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST);
        try {
            // starting Ganglia master during deployment case
            if (newClusterConf == null) {
                // starting ganglia master first and then applying a 1 minute
                // sleep
                // before starting gmond
                if (!startGangliaMaster(gangliaMaster)) {
                    return false;
                }
            }

            // starting service in each cluster node
            for (final String host : nodes) {
                semaphore.acquire();
                AppStoreWrapper.getExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        conf.getNodes().get(host).setStatus(startGmond(host));
                        if (semaphore != null) {
                            semaphore.release();
                        }
                    }
                });
            }
            semaphore.acquire(nodes.size());
        } catch (Exception e) {
            logger.warn("There is some exception while stating " + getComponentName() + " services.",
                    getComponentName(), e);
        }
        // Return false if any of the node service is not started.
        // return AnkushUtils.getStatus(conf.getNodes());
        return true;
    }

    @Override
    public boolean addNode(ClusterConfig conf, ClusterConfig newConf) {

        try {
            // Set logger
            if (!initializeDataMembers(conf)) {
                return false;
            }
            this.newClusterConf = newConf;

            Map<String, Map<String, Object>> nodeMap = newConf.getComponents().get(getComponentName()).getNodes();
            Set<String> gmondNodeSet = (Set<String>) compConfig.getAdvanceConf()
                    .get(GangliaConstants.ClusterProperties.GMOND_SET);
            for (String newNode : nodeMap.keySet()) {
                gmondNodeSet.add(newNode);
            }
            if (!deployNodes(newConf, nodeMap)) {
                return false;
            }
            // TODO: Updating 'gmondSet' in component advanceConf
            return start(newConf, nodeMap.keySet());
        } catch (AnkushException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }

    private void updateGmondSet() {

    }

    @Override
    public boolean removeNode(final ClusterConfig conf, Collection<String> nodes) {
        try {
            if (newClusterConf == null) {
                // setting clusterconf, componentconf and logger
                if (!initializeDataMembers(conf)) {
                    return false;
                }
            }
            final Semaphore semaphore = new Semaphore(nodes.size());
            // undeploying package from each node
            for (final String host : nodes) {
                semaphore.acquire();
                AppStoreWrapper.getExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        // setting nodestatus default value to false
                        boolean nodestatus = false;
                        // if service stopped successfully, then removing
                        // component from node
                        if (stopNode(host)) {
                            nodestatus = removeNode(host);
                        }
                        conf.getNodes().get(host).setStatus(nodestatus);
                        if (semaphore != null) {
                            semaphore.release();
                        }
                    }
                });
            }
            semaphore.acquire(nodes.size());
        } catch (Exception e) {
            addClusterError("Could not remove " + getComponentName(), e);
            return false;
        }
        return AnkushUtils.getStatus(conf.getNodes());
    }

    public boolean removeNode(ClusterConfig conf, ClusterConfig newConf) {
        this.newClusterConf = newConf;
        return removeNode(newConf, newConf.getComponents().get(getComponentName()).getNodes().keySet());
    }

    /**
     * Stop cluster.
     * 
     * @param host
     *            {@link String}
     * @return <code>true</code>, if successful
     */
    public boolean stopNode(String host) {
        String message = "Stopping ganglia...";
        // // Setting the start progress message for activity startup.
        logger.info(message, getComponentName(), host);
        String stopGmondCmd = "killall -9 " + GangliaConstants.GangliaExecutables.GMOND;
        String stopGmetadCmd = "killall -9 " + GangliaConstants.GangliaExecutables.GMETAD;
        try {
            // Connection with node via SSH connection
            SSHExec connection = getConnection(host);
            if (connection == null) {
                addClusterError("Could not get connection.", host);
                return false;
            }

            // stopping gmond
            execCustomtask(stopGmondCmd, connection, host, "Could not stop " + Constant.Role.GMOND);
            if (((String) advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST)).equals(host)) {
                // stopping gmetad
                execCustomtask(stopGmetadCmd, connection, host, "Could not stop " + Constant.Role.GMETAD);
            }
        } catch (Exception e) {
            addClusterError("Could not stop " + getComponentName(), host, e);
            return false;
        }
        return true;
    }

    /**
     * Removes Ganglia cluster related directories and environment variables
     * from node
     * 
     * @param host
     *            {@link String}
     * @return <code>true</code>, if successful
     */
    private boolean removeNode(String host) {
        // Setting the start progress message for activity remove.
        String message = "Removing ganglia";
        logger.info(message, getComponentName(), host);

        List<String> rmCmds = new ArrayList<String>();
        rmCmds.add("rm -rf " + advanceConf.get(GangliaConstants.ClusterProperties.GMOND_CONF_PATH));
        // removing gmetad.conf if node is ganglia master
        if (((String) advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST)).equals(host)) {
            rmCmds.add("rm -rf  " + advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_CONF_PATH));
        }
        rmCmds.add("rm -rf " + (String) advanceConf.get(GangliaConstants.ClusterProperties.RRD_FILE_PATH));
        try {
            SSHExec connection = getConnection(host);
            if (connection == null) {
                addClusterError("Could not get connection.", host);
                return false;
            }
            // Removing directories
            CustomTask execTask = new ExecSudoCommand(GangliaUtils.getAuthentication(clusterConf),
                    rmCmds.toArray(new String[rmCmds.size()]));
            return (connection.exec(execTask).rc == 0);
        } catch (Exception e) {
            addClusterError("Could not remove " + getComponentName() + " directories.", host, e);
            return false;
        }
    }

    /**
     * Perform asynchronous operations nodes.
     * 
     * @param nodeList
     *            {@link Collection}
     * @return <code>true</code>, if successful
     */
    private boolean validate(Collection<String> nodeList) throws AnkushException {
        try {
            // Create semaphore to join threads
            final Semaphore semaphore = new Semaphore(nodeList.size());
            for (final String host : nodeList) {
                final NodeConfig nodeConf = clusterConf.getNodes().get(host);
                semaphore.acquire();
                AppStoreWrapper.getExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            nodeConf.setStatus(new GangliaValidator(clusterConf, nodeConf).validate());
                        } catch (AnkushException e) {
                            addClusterError(e.getMessage(), host, e);
                        } catch (Exception e) {
                            addClusterError("There is some exception while validating " + host + " for "
                                    + getComponentName() + " deployment. " + GangliaConstants.EXCEPTION_STRING,
                                    host, e);
                        } finally {
                            if (semaphore != null) {
                                semaphore.release();
                            }
                        }
                    }
                });
            }
            semaphore.acquire(nodeList.size());

        } catch (Exception e) {
            throw new AnkushException("There is some exception while validating nodes for " + getComponentName()
                    + " deployment." + GangliaConstants.EXCEPTION_STRING, e);
        }
        return AnkushUtils.getStatus(clusterConf, nodeList);
    }

    private boolean deployNodes(final ClusterConfig conf, Map<String, Map<String, Object>> nodeMap) {
        try {
            // Node Deployment process ...
            final Semaphore semaphore = new Semaphore(nodeMap.size());
            for (final String host : nodeMap.keySet()) {
                semaphore.acquire();
                AppStoreWrapper.getExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        conf.getNodes().get(host).setStatus(createNode(host));
                        if (semaphore != null) {
                            semaphore.release();
                        }
                    }
                });
            }
            semaphore.acquire(nodeMap.size());
        } catch (Exception e) {
            return addClusterError("There is some exception while deploying " + getComponentName()
                    + " on all nodes. " + GangliaConstants.EXCEPTION_STRING, e);
        }
        if (newClusterConf == null) {
            if (!clusterConf.getNodes().get(gmetadHost).getStatus()) {
                logger.error("Could not deploy " + getComponentName() + " on "
                        + GangliaConstants.Ganglia_Services.GangliaMaster + " node , so initializing rollback.",
                        getComponentName());
            }
            return clusterConf.getNodes().get(gmetadHost).getStatus();
        } else {
            return AnkushUtils.getStatus(conf.getNodes());
        }
    }

    /**
     * installing and configuring Ganglia
     * 
     * @param host
     *            {@link String}
     * @return <code>true</code> , if successful
     */
    private boolean createNode(String host) {
        boolean isGmetad = host.equals(gmetadHost);
        try {
            // Setting the start progress message for activity startup.
            String message = "Deploying " + getComponentName() + " on host : " + host;
            logger.info(message, getComponentName(), host);
            // getting connection
            SSHExec connection = getConnection(host);
            if (connection == null) {
                throw new AnkushException("Issue while connecting to node : " + host);
            }
            // Gmond conf folder directory
            String gmondConfFolderPath = FilenameUtils
                    .getFullPath((String) advanceConf.get(GangliaConstants.ClusterProperties.GMOND_CONF_PATH));
            // Gmetad conf folder directory
            String gmetadConfFolderPath = FilenameUtils
                    .getFullPath((String) advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_CONF_PATH));

            if (gmondConfFolderPath == null || gmondConfFolderPath.isEmpty() || gmetadConfFolderPath == null
                    || gmetadConfFolderPath.isEmpty()) {

                return addClusterError(
                        getComponentName() + " configuration path provided from UI is either null or empty.", host);
            }

            // Make gmond conf directory if not exists
            AnkushTask mkGmondConfFolderPath = new MakeDirectory(gmondConfFolderPath);
            if (connection.exec(mkGmondConfFolderPath).rc != 0) {
                throw new AnkushException(
                        "Could not create " + gmondConfFolderPath + " directory on $TYPE node " + host + ".");
            }
            // make gmetad conf directory on node
            AnkushTask mkGmetadConfFolderPath = new MakeDirectory(gmetadConfFolderPath);
            // if gmetad parent directory is different than the gmond parent
            // directory
            if (!mkGmondConfFolderPath.equals(mkGmetadConfFolderPath)) {
                if (connection.exec(mkGmetadConfFolderPath).rc != 0) {
                    throw new AnkushException(
                            "Could not create " + gmetadConfFolderPath + " directory on $TYPE node " + host + ".");
                }
            }
            // TODO: gmetad conf path creation
            if (!installGanglia(host, connection, isGmetad) || !createConfigurationFiles(host, connection, isGmetad)
                    || !createRRDDirectories(host, connection, isGmetad) || !configureServiceMonitoring(host)) {
                return false;
            }
            // setting installed ganglia version in ganglia
            // conf.
            setInstalledGangliaVersion(host, isGmetad);
            return true;
        } catch (AnkushException e) {
            logger.warn(e.getMessage(), getComponentName(), host, e);
            return false;
        } catch (Exception e) {
            return addClusterError("There is some exception while installing " + getComponentName() + " on node: "
                    + host + ". " + GangliaConstants.EXCEPTION_STRING, host, e);
        }
    }

    /**
     * 
     * @param isGmetad
     * @param message
     * @param host
     * @param e
     * @throws AnkushException
     */
    private void addErrorOrWarning(boolean isGmetad, String message, String host, Exception e)
            throws AnkushException {
        if (isGmetad) {
            throw new AnkushException(
                    message.replace("$TYPE ", GangliaConstants.Ganglia_Services.GangliaMaster.toString())
                            + " So rolling back " + getComponentName() + " deployment.",
                    e);
        } else {
            logger.warn(message.replace("$TYPE ", ""), getComponentName(), host, e);
        }
    }

    /**
     * 
     * @param isGmetad
     * @param message
     * @param host
     * @throws AnkushException
     */
    private void addErrorOrWarning(boolean isGmetad, String message, String host) throws AnkushException {
        if (isGmetad) {
            throw new AnkushException(
                    message.replace("$TYPE ", GangliaConstants.Ganglia_Services.GangliaMaster.toString())
                            + " So rolling back " + getComponentName() + " deployment.");
        } else {
            logger.warn(message.replace("$TYPE ", ""), getComponentName(), host);
        }
    }

    /**
     * Install ganglia.
     * 
     * @param nodeConf
     *            the node conf
     * @param conf
     *            the conf
     * @param connection
     *            the connection
     * @return true, if successful
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * @throws TaskExecFailException
     *             the task exec fail exception
     */
    private boolean installGanglia(String host, SSHExec connection, boolean isGmetad) throws AnkushException {

        try {
            // Getting the OS Name of the Node.
            String osName = SSHUtils.getOS(connection, host);
            if (osName == null || osName.isEmpty()) {
                throw new AnkushException("Could not identify OS details on node : " + host + ".");
            }

            String componentName = GangliaConstants.ComponentType.GMOND;
            if (isGmetad) {
                componentName = GangliaConstants.ComponentType.GMETAD;
            }
            String message = "Executing " + getComponentName() + " deployment scripts";
            logger.info(message, getComponentName(), host);
            /* Getting the installer file name of the component. */
            String installerFilePath = FileNameUtils.getInstallerFilePath(osName, componentName);
            if (installerFilePath == null) {
                throw new AnkushException(
                        "Could not get script file to install " + componentName + " on node : " + host + ".");
            }
            // Getting list of installation commands from the file.
            List<String> depListCmds = FileUtils.readLines(new File(installerFilePath));
            // Iterating over the command lists.
            for (String installCmd : depListCmds) {
                if (!installCmd.isEmpty()) {
                    // Executing the installation command.
                    CustomTask execTask = new ExecSudoCommand(GangliaUtils.getAuthentication(clusterConf),
                            installCmd);
                    if (connection.exec(execTask).rc != 0) {
                        throw new AnkushException(
                                "Executing command '" + installCmd + "' on node " + host + " failed.");
                    }
                }
            }
            return true;
        } catch (AnkushException e) {
            throw e;
        } catch (Exception e) {
            throw new AnkushException("There is some exception while installing " + getComponentName()
                    + " on node : " + host + ". " + GangliaConstants.EXCEPTION_STRING);
        }
    }

    private void setInstalledGangliaVersion(String host, boolean isGmetad) throws Exception {

        // Command to show the installed version of gmond
        String command = GangliaConstants.GangliaExecutables.GMOND;

        if (isGmetad) {
            // Command to show the installed version of gmetad
            command = GangliaConstants.GangliaExecutables.GMETAD;
        }
        try {
            SSHExec connection = getConnection(host);
            if (connection == null) {
                logger.warn(
                        "There is some connection issue with node while running '" + command
                                + "' --v command for getting " + getComponentName() + " version.",
                        getComponentName(), host);
            }
            /* Executing the command to get the output. */
            CustomTask task = new ExecCommand(command + " --v");
            /* Executing the command. */
            Result rs = connection.exec(task);

            if (rs.sysout != null) {
                String version = rs.sysout.split(" ")[1];
                compConfig.setVersion(version);
            }
        } catch (Exception e) {
            logger.warn("There is some exception while getting " + getComponentName() + " version on node: " + host
                    + ". " + GangliaConstants.EXCEPTION_STRING, getComponentName(), host, e);
        }

    }

    /**
     * Used to create gmond.conf and gmetad.conf file
     */
    private boolean createConfigurationFiles(String host, SSHExec connection, boolean isGmetad)
            throws AnkushException {

        try {
            // getting gmond.conf path on node
            String confPath = (String) advanceConf.get(GangliaConstants.ClusterProperties.GMOND_CONF_PATH);
            if (confPath == null || confPath.isEmpty()) {
                return addClusterError("Gmond configuration path provided from UI is either null or empty.", host);
            }
            // getting gmond.conf from server
            String confFileName = (String) advanceConf.get(GangliaConstants.ClusterProperties.SERVER_CONF_FOLDER)
                    + GangliaConstants.ConfigurationFiles.GMOND_CONF;
            // Create the gmond configuration on node
            String message = "Configuring gmond file on node : " + host;
            logger.info(message, getComponentName(), host);
            CustomTask clearFile = new ClearFile(confPath);
            String fileContent = getConfigurationContent(host, confFileName).replaceAll("\\\"", "\\\\\"");
            CustomTask appendFile = new AppendFileUsingEcho(fileContent, confPath);

            if ((connection.exec(clearFile).rc != 0) || (connection.exec(appendFile).rc != 0)) {
                throw new AnkushException(
                        "Could not create Gmond configuration file " + confPath + " on node : " + host);
            }
            if (isGmetad) {
                confPath = (String) advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_CONF_PATH);
                if (confPath == null || confPath.isEmpty()) {
                    return addClusterError("Gmetad configuration path provided from UI is either null or empty.",
                            host);
                }
                confFileName = (String) advanceConf.get(GangliaConstants.ClusterProperties.SERVER_CONF_FOLDER)
                        + GangliaConstants.ConfigurationFiles.GMETAD_CONF;
                clearFile = new ClearFile(confPath);
                fileContent = getConfigurationContent(host, confFileName).replaceAll("\\\"", "\\\\\"");
                appendFile = new AppendFileUsingEcho(fileContent, confPath);
                if (((connection.exec(clearFile).rc != 0) || (connection.exec(appendFile).rc != 0))) {
                    throw new AnkushException(
                            "Could not create Gmetad configuration file " + confPath + " on $TYPE node : " + host);
                }
            }
        } catch (AnkushException e) {
            throw e;
        } catch (Exception e) {
            throw new AnkushException("There is some exception while configuring " + getComponentName()
                    + " on $TYPE node " + host + ". " + GangliaConstants.EXCEPTION_STRING);
        }
        return true;
    }

    /**
     * Used to create RRD directory
     */
    private boolean createRRDDirectories(String host, SSHExec connection, boolean isGmetad) throws AnkushException {
        try {
            logger.info("Creating rrd directory.", getComponentName(), host);

            // logging startup message.
            String message = "Creating ganglia directories";
            logger.info(message, getComponentName(), host);

            CustomTask mkdirRRd = new MakeDirectory(
                    (String) advanceConf.get(GangliaConstants.ClusterProperties.RRD_FILE_PATH));
            return (connection.exec(mkdirRRd).rc == 0);
        } catch (TaskExecFailException e) {
            throw new AnkushException("Could not create RRD directory on $TYPE node: " + host);
        }
    }

    /**
     * function to execute Custom Tasks and setting error if it fails
     * 
     * @return <code>true</code>, if successful
     */
    private boolean execCustomtask(String command, SSHExec connection, String publicIp, String errMsg) {
        // set clusterName in cassandra.yaml
        try {
            CustomTask task = new ExecCommand(command);
            if (connection.exec(task).rc == 0) {
                return true;
            }
            logger.warn(errMsg, getComponentName(), publicIp);
            // addClusterError(errMsg, publicIp);
        } catch (TaskExecFailException e) {
            logger.warn(errMsg, getComponentName(), publicIp, e);
            // addClusterError(errMsg, publicIp, e);
        }
        return false;
    }

    public String getConfigurationContent(String host, String confFileName) throws Exception {
        String fileContent = null;
        Map<String, Object> configValues = getConfigValueMap();

        String udpRecvChannel = "udp_recv_channel {\n port = " + configValues.get("port") + " \n } ";
        // 'udp_recv_channel' value for gmond.conf
        configValues.put("udp_recv_channel", "/*" + udpRecvChannel + "*/");

        if (((String) advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST)).equals(host)) {
            StringBuffer nodeIpPorts = new StringBuffer();
            // Preparing a String of nodeIp:port of gmetad node used in
            // data_source in gmetad.conf.
            nodeIpPorts.append(advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST))
                    .append(Symbols.STR_COLON);
            nodeIpPorts.append(advanceConf.get(GangliaConstants.ClusterProperties.GANGLIA_PORT));
            // Putting the nodeIpsPorts string in map
            configValues.put("nodeIpsPorts", nodeIpPorts.toString());
            // On gmond nodes other than Gmetad node commenting
            // udp_recv_channel block
            configValues.put("udp_recv_channel", udpRecvChannel);
        }
        // Reading the content of the template file
        fileContent = FileUtil.readAsString(new File(confFileName));

        // Creating a string substitutor using config values map
        StrSubstitutor sub = new StrSubstitutor(configValues);

        // Replacing the config values key found in the file content with
        // respected values.
        return sub.replace(fileContent);
    }

    public String getGmetadConfigurationContent(String host) throws Exception {
        String fileContent = null;
        String confFileName = (String) advanceConf.get(GangliaConstants.ClusterProperties.SERVER_CONF_FOLDER)
                + GangliaConstants.ConfigurationFiles.GMOND_CONF;

        Map<String, Object> configValues = getConfigValueMap();

        String udpRecvChannel = "udp_recv_channel {\n port = " + configValues.get("port") + " \n } ";
        configValues.put("udp_recv_channel", "/*" + udpRecvChannel + "*/");

        if (((String) advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST)).equals(host)) {
            confFileName = (String) advanceConf.get(GangliaConstants.ClusterProperties.SERVER_CONF_FOLDER)
                    + GangliaConstants.ConfigurationFiles.GMETAD_CONF;
            StringBuffer nodeIpPorts = new StringBuffer();
            // Preparing a String of nodeIp:port of gmetad node.
            nodeIpPorts.append(advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST))
                    .append(Symbols.STR_COLON);
            nodeIpPorts.append(advanceConf.get(GangliaConstants.ClusterProperties.GANGLIA_PORT));
            // Putting the nodeIpsPorts string in map
            configValues.put("nodeIpsPorts", nodeIpPorts.toString());
            // On gmond nodes other than Gmetad node commenting
            // udp_recv_channel block
            configValues.put("udp_recv_channel", udpRecvChannel);
        }
        // Reading the content of the template file
        fileContent = FileUtil.readAsString(new File(confFileName));

        // Creating a string substitutor using config values map
        StrSubstitutor sub = new StrSubstitutor(configValues);

        // Replacing the config values key found in the file content with
        // respected values.
        return sub.replace(fileContent);
    }

    /**
     * Create a map for configuration generation.
     * 
     * @return The map of configuration values
     */
    private Map<String, Object> getConfigValueMap() {

        Map<String, Object> configValues = new HashMap<String, Object>();
        configValues.put("nodeIP", advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_HOST));
        configValues.put("clusterName", advanceConf.get(GangliaConstants.ClusterProperties.GANGLIA_CLUSTER_NAME));
        configValues.put("clusterOwner", clusterConf.getAuthConf().getUsername());
        configValues.put("port", advanceConf.get(GangliaConstants.ClusterProperties.GANGLIA_PORT));
        configValues.put("pollingInterval", advanceConf.get(GangliaConstants.ClusterProperties.POLLING_INTERVAL));
        configValues.put("gridName", advanceConf.get(GangliaConstants.ClusterProperties.GRID_NAME));
        configValues.put("rrdFilePath", advanceConf.get(GangliaConstants.ClusterProperties.RRD_FILE_PATH));
        return configValues;
    }

    private boolean configureServiceMonitoring(String host) {
        try {
            // getting connection
            SSHExec connection = getConnection(host);
            if (connection == null) {
                logger.warn("Issue while connecting to node: " + host, getComponentName(), host);
            }
            // List of service object
            List<ComponentService> services = new ArrayList<ComponentService>();
            // Considering Ganglia registration case when separate node is used
            // as
            // Ganglia Master and no gmond is installed on it
            // if (((Set<String>) advanceConf
            // .get(GangliaConstants.ClusterProperties.GMOND_SET))
            // .contains(host)) {
            services.add(
                    new ComponentService(Constant.Process.GMOND, Constant.Role.GMOND, Constant.ServiceType.PS));
            // }

            // Gmetad component service.
            if (host.equals(gmetadHost)) {
                // gmetad service object.
                services.add(new ComponentService(Constant.Process.GMETAD, Constant.Role.GMETAD,
                        Constant.ServiceType.PS));
            }
            // Create Ganglia service xml.
            AgentUtils.createServiceXML(connection, services, getComponentName(), clusterConf.getAgentHomeDir());
        } catch (Exception e) {
            logger.warn("There is some exception while creating service xml files for monitoring "
                    + getComponentName() + " services.", getComponentName(), host, e);
        }
        return true;
    }

    public boolean startGangliaMaster(String host) {
        try {
            // Connection with node via SSH connection
            SSHExec connection = getConnection(host);
            if (connection == null) {
                logger.warn("Issue while creating connection with "
                        + GangliaConstants.Ganglia_Services.GangliaMaster + " node while starting 'gmetad' process",
                        getComponentName(), host);
            }
            logger.info("Starting " + Constant.Role.GMETAD + "...", getComponentName(), host);
            String startGmetadCmd = GangliaConstants.GangliaExecutables.GMETAD + " --conf="
                    + advanceConf.get(GangliaConstants.ClusterProperties.GMETAD_CONF_PATH);
            execCustomtask(startGmetadCmd, connection, host,
                    "Could not start " + GangliaConstants.Ganglia_Services.GangliaMaster + " on node " + host
                            + " . Please start it manually after cluster deployment.");
        } catch (Exception e) {
            logger.warn(
                    "There is some exception while starting " + GangliaConstants.Ganglia_Services.GangliaMaster
                            + " on node: " + host + ". " + GangliaConstants.EXCEPTION_STRING,
                    getComponentName(), host, e);
        }
        return true;
    }

    public boolean startGmond(String host) {
        String message = "Starting " + Constant.Role.GMOND + "...";
        // Setting the start progress message for activity startup.
        logger.info(message, getComponentName(), host);
        String startGmondCmd = GangliaConstants.GangliaExecutables.GMOND + " --conf="
                + advanceConf.get(GangliaConstants.ClusterProperties.GMOND_CONF_PATH);
        try {
            // Connection with node via SSH connection
            SSHExec connection = getConnection(host);
            if (connection == null) {
                logger.warn("Issue while creating connection with node : " + host, getComponentName(), host);
            }
            // Starting the gmond process on node
            execCustomtask(startGmondCmd, connection, host, "Could not start " + Constant.Role.GMOND + " on node "
                    + host + " . Please start it manually after cluster deployment.");
        } catch (Exception e) {
            logger.warn("There is some exception while starting gmond process on node: " + host, getComponentName(),
                    host, e);
        }
        return true;
    }

    /**
     * Provides node's connection object
     * 
     * @param host
     *            {@link String}
     * @return {@link SSHExec}
     */
    private SSHExec getConnection(String host) {
        try {
            if (clusterConf.getNodes().containsKey(host)) {
                return clusterConf.getNodes().get(host).getConnection();
            }
            return newClusterConf.getNodes().get(host).getConnection();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Checks whether a node can be deleted
     */
    @Override
    public boolean canNodeBeDeleted(ClusterConfig clusterConfig, Collection<String> nodes) {
        logger.setCluster(clusterConfig);
        if (nodes.contains(clusterConfig.getComponents().get(getComponentName())
                .getAdvanceConfStringProperty(GangliaConstants.ClusterProperties.GMETAD_HOST))) {
            logger.error("Could not delete nodes as they contains GangliaMaster which cannot be deleted.",
                    getComponentName());
            return false;
        }
        return true;
    }
}