/*******************************************************************************
* ===========================================================
* 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.zookeeper;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Semaphore;
import javax.management.ObjectName;
import com.impetus.ankush.AppStoreWrapper;
import com.impetus.ankush.common.exception.AnkushException;
import com.impetus.ankush.common.utils.FileUtils;
import com.impetus.ankush.common.utils.JmxUtil;
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;
/**
* The Class ZookeeperDeployer.
*/
public class ZookeeperDeployer extends AbstractDeployer {
/** The logger. */
private final AnkushLogger logger = new AnkushLogger(
ZookeeperDeployer.class);
/** The cluster config. */
private ClusterConfig clusterConfig;
/**
* Sets the cluster and logger.
*
* @param clusterConfig
* the cluster config
* @return true, if successful
*/
private boolean setClusterAndLogger(ClusterConfig clusterConfig) {
this.clusterConfig = clusterConfig;
if (this.clusterConfig.getComponents().get(this.componentName) == null) {
logger.error(ZookeeperConstant.Keys.ERROR_Zookeeper_CONF_NOT_FOUND,
this.componentName);
this.clusterConfig.addError(this.componentName,
"Couldn't get Zookeeper configuration from cluster conf.");
return false;
}
logger.setCluster(clusterConfig);
return true;
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#createConfig(com.impetus.ankush2
* .framework.config.ClusterConfig)
*/
@Override
public boolean createConfig(ClusterConfig clusterConfig) {
if (!this.setClusterAndLogger(clusterConfig)) {
return false;
}
ComponentConfig compConf = clusterConfig.getComponents().get(
this.componentName);
if (!compConf.isRegister()) {
compConf.setHomeDir(FileUtils
.getSeparatorTerminatedPathEntry(compConf.getInstallPath())
+ Constant.Component.Name.ZOOKEEPER.toLowerCase()
+ "-"
+ compConf.getVersion());
} else {
JmxUtil jmxUtil = null;
String zookeeperHost = compConf
.getAdvanceConfStringProperty(ZookeeperConstant.Keys.Advance_Conf_Keys.HOST);
int jmxPort = compConf
.getAdvanceConfIntegerProperty(ZookeeperConstant.Keys.JMX_PORT);
try {
logger.info(
"Getting all the zookeeper nodes from the given host-"
+ zookeeperHost, this.componentName);
String patternStr = "org.apache.ZooKeeperService:name0=*";
jmxUtil = new JmxUtil(zookeeperHost, jmxPort);
jmxUtil.connect();
Set<ObjectName> objectNameSet;
String quorumAddress = null;
if ((objectNameSet = jmxUtil
.getObjectSetFromPatternString(patternStr)) != null) {
for (ObjectName objName : objectNameSet) {
if (objName.toString().contains(
ZookeeperConstant.Keys.STANDALONESERVER_PORT_1)) {
quorumAddress = zookeeperHost;
// skip adding node in cluster for Level1
// Registration
addNodeToClusterAndComponent(compConf,
quorumAddress);
} else {
String replicaObjName = objName + ",name1=*";
objectNameSet = jmxUtil
.getObjectSetFromPatternString(replicaObjName);
for (ObjectName objName1 : objectNameSet) {
String quorumAddressStr = (String) jmxUtil
.getAttribute(objName1, "QuorumAddress");
String[] quorumAddressArray = quorumAddressStr
.split(":");
if (quorumAddressArray[0].contains("/")) {
quorumAddress = quorumAddressArray[0]
.split("/")[0];
} else {
quorumAddress = quorumAddressArray[0];
}
addNodeToClusterAndComponent(compConf,
quorumAddress);
}
}
}
} else {
throw new AnkushException("Zookeeper JMX port : " + jmxPort
+ " is not enabled on host : " + zookeeperHost);
}
} catch (AnkushException e) {
logger.error(e.getMessage(), this.componentName, zookeeperHost,
e);
clusterConfig.addError(componentName, e.getMessage());
return false;
} catch (Exception e) {
logger.error("Couldn't create configuration",
this.componentName, zookeeperHost, e);
return false;
} finally {
jmxUtil.disconnect();
}
}
return true;
}
/**
* Register Zookeeper : Adds the node to cluster and componnet depending
* upon the level of Registration for Zookeeper
*
* @param compConf
* the comp conf
* @param quorumAddress
* the quorum address
* @throws Exception
* the exception
*/
private void addNodeToClusterAndComponent(ComponentConfig compConf,
String quorumAddress) throws Exception {
if (!AnkushUtils.isMonitoredByAnkush(compConf)) {
AnkushUtils.addNodeToComponentConfig(clusterConfig,
this.componentName, quorumAddress,
new HashMap<String, Object>());
} else {
AnkushUtils
.addNodeToClusterAndComponent(
clusterConfig,
quorumAddress,
new HashSet<String>(Arrays
.asList(Constant.Role.ZOOKEEPER)), this
.getComponentName());
}
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#validate(com.impetus.ankush2
* .framework.config.ClusterConfig)
*/
@Override
public boolean validate(ClusterConfig conf) {
boolean status = false;
ComponentConfig compConf = clusterConfig.getComponents().get(
this.getComponentName());
// skip all the Validation in Level1 Registration
if (compConf.isRegister() && !AnkushUtils.isMonitoredByAnkush(compConf)) {
return true;
}
try {
final Semaphore semaphore = new Semaphore(compConf.getNodes()
.size());
for (final String host : compConf.getNodes().keySet()) {
semaphore.acquire();
final ZookeeperValidator zooValidator = new ZookeeperValidator(
clusterConfig, clusterConfig.getNodes().get(host),
this.getComponentName());
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
clusterConfig.getNodes().get(host)
.setStatus(zooValidator.validate());
} catch (Exception e) {
logger.error(
"Exception in validation of Zookeeper."
+ Constant.Strings.ExceptionsMessage.VIEW_SERVER_LOGS,
getComponentName(), e);
clusterConfig.getNodes().get(host).setStatus(false);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
// waiting for all semaphores to finish the installation.
semaphore.acquire(compConf.getNodes().size());
status = AnkushUtils.getStatus(clusterConfig, compConf.getNodes()
.keySet());
} catch (Exception e) {
status = false;
logger.error("Exception in validation of Zookeeper."
+ Constant.Strings.ExceptionsMessage.VIEW_SERVER_LOGS,
this.getComponentName(), e);
}
if (status) {
logger.info(this.getComponentName() + " validation is over.",
this.getComponentName());
} else {
logger.error("Validating " + this.getComponentName() + " failed.",
this.getComponentName());
clusterConfig.addError(getComponentName(), "Validating "
+ getComponentName() + " failed.");
}
return status;
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#deploy(com.impetus.ankush2.framework
* .config.ClusterConfig)
*/
@Override
public boolean deploy(ClusterConfig clusterConfig) {
if (!this.setClusterAndLogger(clusterConfig)) {
return false;
}
ComponentConfig compConf = clusterConfig.getComponents().get(
this.componentName);
try {
int nodeId = 0;
// iterate over node list
for (String host : compConf.getNodes().keySet()) {
nodeId++;
((Map<String, Object>) compConf.getNodes().get(host)).put(
ZookeeperConstant.Keys.NODE_ID, nodeId);
}
compConf.getAdvanceConf().put(ZookeeperConstant.Keys.LAST_NODE_ID,
nodeId);
return deployNodes(clusterConfig);
} catch (Exception e) {
logger.error(e.getMessage(), this.componentName, e);
}
return false;
}
/**
* Deploy nodes.
*
* @param clusterConfig
* the cluster config
* @return true, if successful
*/
private boolean deployNodes(ClusterConfig clusterConfig) {
logger.info("Deploying Zookeeper...", this.componentName);
ComponentConfig compConfig = clusterConfig.getComponents().get(
this.componentName);
final Semaphore semaphore = new Semaphore(compConfig.getNodes().size());
boolean status = false;
try {
for (final String host : compConfig.getNodes().keySet()) {
// acuiring the semaphore
semaphore.acquire();
final NodeConfig nodeConfig = clusterConfig.getNodes()
.get(host);
Map<String, Object> nodeAdvanceConf = compConfig.getNodes()
.get(host);
final ZookeeperWorker zookeeperWorker = new ZookeeperWorker(
this.clusterConfig, this.componentName, nodeConfig,
nodeAdvanceConf);
final ZookeeperServiceMonitor zooServiceMonitor = new ZookeeperServiceMonitor(
clusterConfig, this.componentName);
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
nodeConfig.setStatus(zookeeperWorker.createNode());
if (nodeConfig.getStatus()) {
if (!zooServiceMonitor.action(
ZookeeperConstant.Action.START,
nodeConfig.getHost())) {
logger.warn("Couldn't "
+ ZookeeperConstant.Action.START
+ " Zookeeper.", componentName,
nodeConfig.getHost());
}
} else {
logger.error("Couldn't deploy Zookeeper.",
componentName, nodeConfig.getHost());
}
} catch (Exception e) {
nodeConfig.setStatus(false);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
// waiting for all semaphores to finish the installation.
semaphore.acquire(compConfig.getNodes().size());
status = AnkushUtils.getStatus(clusterConfig, compConfig.getNodes()
.keySet());
} catch (Exception e) {
logger.error(e.getMessage(), this.componentName, e);
status = false;
}
if (status) {
logger.info("Deploying Zookeeper is over.", componentName);
} else {
logger.error("Deploying Zookeeper failed.", componentName);
clusterConfig.addError(getComponentName(),
"Deploying Zookeeper failed.");
}
return status;
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#register(com.impetus.ankush2
* .framework.config.ClusterConfig)
*/
@Override
public boolean register(ClusterConfig clusterConfig) {
ComponentConfig compConf = clusterConfig.getComponents().get(
this.componentName);
if (!AnkushUtils.isMonitoredByAnkush(compConf)) {
logger.info(
"Skipping Zookeeper service configuration for Level1 Registration",
this.componentName);
return true;
}
logger.info("Registering Zookeeper...", this.componentName);
boolean status = false;
try {
final Semaphore semaphore = new Semaphore(compConf.getNodes()
.size());
for (String host : compConf.getNodes().keySet()) {
semaphore.acquire();
final NodeConfig nodeConfig = clusterConfig.getNodes()
.get(host);
final ZookeeperWorker zookeeperWorker = new ZookeeperWorker(
clusterConfig, this.componentName, nodeConfig);
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
nodeConfig.setStatus(zookeeperWorker.register());
} catch (Exception e) {
logger.error(e.getMessage(), componentName, e);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
semaphore.acquire(compConf.getNodes().size());
status = AnkushUtils.getStatus(clusterConfig, compConf.getNodes()
.keySet());
} catch (Exception e) {
logger.error(e.getMessage(), this.componentName, e);
}
if (status) {
logger.info("Registering Zookeeper is over.", componentName);
} else {
logger.error("Registering Zookeeper failed.", componentName);
clusterConfig.addError(getComponentName(),
"Registering Zookeeper failed.");
}
return status;
}
@Override
public boolean unregister(ClusterConfig clusterConfig) {
if (!this.setClusterAndLogger(clusterConfig)) {
return false;
}
ComponentConfig compConf = clusterConfig.getComponents().get(
this.componentName);
if (compConf.isRegister() && !AnkushUtils.isMonitoredByAnkush(compConf)) {
return true;
}
logger.info("Unregistering Zookeeper...", this.componentName);
boolean status = false;
try {
final Semaphore semaphore = new Semaphore(compConf.getNodes()
.size());
for (String host : compConf.getNodes().keySet()) {
semaphore.acquire();
final NodeConfig nodeConfig = clusterConfig.getNodes()
.get(host);
final ZookeeperWorker zookeeperWorker = new ZookeeperWorker(
clusterConfig, this.componentName, nodeConfig);
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
try {
nodeConfig.setStatus(zookeeperWorker.unregister());
} catch (Exception e) {
logger.error(e.getMessage(), componentName, e);
} finally {
if (semaphore != null) {
semaphore.release();
}
}
}
});
}
semaphore.acquire(compConf.getNodes().size());
status = AnkushUtils.getStatus(clusterConfig, compConf.getNodes()
.keySet());
} catch (Exception e) {
logger.error(e.getMessage(), this.componentName, e);
}
if (status) {
logger.info("Unregistering Zookeeper is over.", componentName);
} else {
logger.error("Unregistering Zookeeper failed.", componentName);
clusterConfig.addError(getComponentName(),
"Registering Zookeeper failed.");
}
return status;
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#undeploy(com.impetus.ankush2
* .framework.config.ClusterConfig)
*/
@Override
public boolean undeploy(ClusterConfig clusterConfig) {
if (!this.setClusterAndLogger(clusterConfig)) {
return false;
}
return undeployNodes(clusterConfig);
}
/**
* Undeploy nodes.
*
* @param clusterConfig
* the cluster config
* @return true, if successful
*/
private boolean undeployNodes(ClusterConfig clusterConfig) {
logger.info("Undeploying Zookeeper...", this.componentName);
ComponentConfig compConfig = clusterConfig.getComponents().get(
this.componentName);
final Semaphore semaphore = new Semaphore(compConfig.getNodes().size());
boolean status = false;
try {
for (final String host : compConfig.getNodes().keySet()) {
// acuiring the semaphore
semaphore.acquire();
final NodeConfig nodeConfig = clusterConfig.getNodes()
.get(host);
final ZookeeperWorker zookeeperWorker = new ZookeeperWorker(
this.clusterConfig, this.componentName, nodeConfig);
final ZookeeperServiceMonitor zooServiceMonitor = new ZookeeperServiceMonitor(
clusterConfig, this.componentName);
// zooServiceMonitor.setCluster(clusterConfig,
// this.componentName);
AppStoreWrapper.getExecutor().execute(new Runnable() {
@Override
public void run() {
// logger.info("Stopping Zookeeper...", componentName);
// zookeeperWorker.action(ZookeeperConstant.Action.STOP);
zooServiceMonitor.action(ZookeeperConstant.Action.STOP,
nodeConfig.getHost());
logger.info("removing Zookeeper...", componentName);
zookeeperWorker.removeNode();
if (semaphore != null) {
semaphore.release();
}
}
});
}
// waiting for all semaphores to finish the installation.
semaphore.acquire(compConfig.getNodes().size());
status = AnkushUtils.getStatus(clusterConfig, compConfig.getNodes()
.keySet());
} catch (Exception e) {
logger.error(e.getMessage(), this.componentName, e);
}
if (status) {
logger.info("Undeploying Zookeeper is over.", componentName);
} else {
logger.error("Undeploying Zookeeper failed.", componentName);
clusterConfig.addError(getComponentName(),
"Undeploying Zookeeper failed.");
}
return status;
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#start(com.impetus.ankush2.framework
* .config.ClusterConfig)
*/
// @Override
// public boolean start(ClusterConfig clusterConfig) {
// if (!this.setClusterAndLogger(clusterConfig)) {
// return false;
// }
// boolean status = false;
// try {
// ComponentConfig compConf = clusterConfig.getComponents().get(
// this.componentName);
// final Semaphore semaphore = new Semaphore(compConf.getNodes()
// .size());
// for (String host : compConf.getNodes().keySet()) {
// semaphore.acquire();
// final NodeConfig nodeConfig = clusterConfig.getNodes()
// .get(host);
// final ZookeeperWorker zookeeperWorker = new ZookeeperWorker(
// clusterConfig, this.componentName, nodeConfig);
// AppStoreWrapper.getExecutor().execute(new Runnable() {
// @Override
// public void run() {
// logger.info("Starting Zookeeper...", componentName);
// nodeConfig.setStatus(zookeeperWorker.action("start"));
// if (semaphore != null) {
// semaphore.release();
// }
// }
// });
// semaphore.acquire(compConf.getNodes().size());
// status = AnkushUtils.getStatus(clusterConfig, compConf
// .getNodes().keySet());
// }
// } catch (Exception e) {
// logger.error(e.getMessage(), this.componentName, e);
// }
// if (status) {
// logger.info("Starting Zookeeper is over.", componentName);
// } else {
// logger.error("Starting Zookeeper failed.", componentName);
// clusterConfig.addError(getComponentName(),
// "Starting Zookeeper failed.");
// }
// return status;
// }
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#stop(com.impetus.ankush2.framework
* .config.ClusterConfig)
*/
// @Override
// public boolean stop(ClusterConfig clusterConfig) {
// if (!this.setClusterAndLogger(clusterConfig)) {
// return false;
// }
// boolean status = false;
// try {
// ComponentConfig compConf = clusterConfig.getComponents().get(
// this.componentName);
// final Semaphore semaphore = new Semaphore(compConf.getNodes()
// .size());
// for (String host : compConf.getNodes().keySet()) {
// semaphore.acquire();
// final NodeConfig nodeConfig = clusterConfig.getNodes()
// .get(host);
// final ZookeeperWorker zookeeperWorker = new ZookeeperWorker(
// clusterConfig, this.componentName, nodeConfig);
// AppStoreWrapper.getExecutor().execute(new Runnable() {
// @Override
// public void run() {
// logger.info("Stopping Zookeeper...", componentName);
// nodeConfig.setStatus(zookeeperWorker.action("stop"));
// if (semaphore != null) {
// semaphore.release();
// }
// }
// });
// semaphore.acquire(compConf.getNodes().size());
// status = AnkushUtils.getStatus(clusterConfig, compConf
// .getNodes().keySet());
// }
// } catch (Exception e) {
// logger.error(e.getMessage(), this.componentName, e);
// }
// if (status) {
// logger.info("Stopping Zookeeper is over.", componentName);
// } else {
// logger.error("Stopping Zookeeper failed.", componentName);
// clusterConfig.addError(getComponentName(),
// "Stopping Zookeeper failed.");
// }
// return status;
// }
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#addNode(com.impetus.ankush2.
* framework.config.ClusterConfig,
* com.impetus.ankush2.framework.config.ClusterConfig)
*/
@Override
public boolean addNode(ClusterConfig conf, ClusterConfig newConf) {
return false;
// For future use,when Zookeeper supports Add node.
// To be handled - from all the nodes server.serverId = host:2888:3888
// to be copied on the newly added node and new node host to be added on
// all existing nodes.
/*
* if (!this.setClusterAndLogger(clusterConfig)) { return false; }
* ComponentConfig compConf = newConf.getComponents().get(
* this.componentName); int nodeId = (Integer)
* conf.getComponents().get(this.componentName)
* .getAdvanceConf().get(ZookeeperConstant.Keys.LAST_NODE_ID); for
* (String host : compConf.getNodes().keySet()) { nodeId++;
* compConf.getNodes().get(host) .put(ZookeeperConstant.Keys.NODE_ID,
* nodeId); }
* conf.getComponents().get(this.componentName).getAdvanceConf()
* .put(ZookeeperConstant.Keys.LAST_NODE_ID, nodeId); return
* deployNodes(newConf);
*/
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#removeNode(com.impetus.ankush2
* .framework.config.ClusterConfig, java.util.Collection)
*/
@Override
public boolean removeNode(ClusterConfig clusterConfig,
Collection<String> nodes) {
if (!this.setClusterAndLogger(clusterConfig)) {
return false;
}
boolean status = false;
logger.error("Zookeeper node cann't be deleted.");
// logger.info("Undeploying Zookeeper...", this.componentName);
// final Semaphore semaphore = new Semaphore(nodes.size());
//
// boolean status = false;
// try {
// for (final String host : nodes) {
// // acuiring the semaphore
// semaphore.acquire();
// final NodeConfig nodeConfig = clusterConfig.getNodes()
// .get(host);
// final ZookeeperWorker zookeeperWorker = new ZookeeperWorker(
// this.clusterConfig, this.componentName, nodeConfig);
// final ZookeeperServiceMonitor zookeeperServiceMonitor = new
// ZookeeperServiceMonitor(
// clusterConfig, getComponentName());
// AppStoreWrapper.getExecutor().execute(new Runnable() {
// @Override
// public void run() {
// try {
// nodeConfig.setStatus(zookeeperServiceMonitor
// .action(ZookeeperConstant.Action.STOP, host));
// zookeeperWorker.removeNode();
// } catch (Exception e) {
// logger.error(e.getMessage(), componentName, e);
// } finally {
// if (semaphore != null) {
// semaphore.release();
// }
// }
// }
// });
// }
// // waiting for all semaphores to finish the installation.
// semaphore.acquire(nodes.size());
// status = AnkushUtils.getStatus(clusterConfig, nodes);
// } catch (Exception e) {
// logger.error(e.getMessage(), this.componentName, e);
// }
// if (status) {
// logger.info("Removing Zookeeper is over.", componentName);
// } else {
// logger.error("Removing Zookeeper failed.", componentName);
// clusterConfig.addError(getComponentName(),
// "Removing Zookeeper failed.");
// }
return status;
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush2.framework.Deployable#removeNode(com.impetus.ankush2
* .framework.config.ClusterConfig,
* com.impetus.ankush2.framework.config.ClusterConfig)
*/
@Override
public boolean removeNode(ClusterConfig conf, ClusterConfig newConf) {
// if (!this.setClusterAndLogger(conf)) {
// return false;
// }
return undeployNodes(newConf);
}
// @Override
// public boolean canNodeBeDeleted(ClusterConfig clusterConfig,
// Collection<String> nodes) {
// if (this.setClusterAndLogger(clusterConfig)) {
// return false;
// }
// ComponentConfig compConfig = clusterConfig.getComponents().get(
// getComponentName());
// // if all zookeeper nodes come for deletion, it cann't be deleted.
// if (nodes.size() == compConfig.getNodes().size()) {
// String errMsg =
// "Couldn't delete all the Zookeeper nodes from a Cluster.";
// logger.error(errMsg);
// clusterConfig.addError(componentName, errMsg);
// return false;
// }
// return true;
// }
}