blob: 3d292a91a5208d40e27c4f3359443993d54569dc [file] [log] [blame]
/*
* Copyright 2009-2012 by The Regents of the University of California
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may obtain a copy of the License from
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.uci.ics.asterix.installer.command;
import java.io.File;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import org.kohsuke.args4j.Option;
import edu.uci.ics.asterix.event.schema.cluster.Cluster;
import edu.uci.ics.asterix.event.schema.cluster.MasterNode;
import edu.uci.ics.asterix.event.schema.cluster.Node;
import edu.uci.ics.asterix.installer.driver.InstallerDriver;
import edu.uci.ics.asterix.installer.schema.conf.Configuration;
import edu.uci.ics.asterix.installer.schema.conf.Zookeeper;
public class ValidateCommand extends AbstractCommand {
private static final String OK = " [" + "OK" + "]";
private static final String ERROR = " [" + "ERROR" + "]";
private static final String WARNING = " [" + "WARNING" + "]";
@Override
protected void execCommand() throws Exception {
ValidateConfig vConfig = (ValidateConfig) config;
logValidationResult("Environment", validateEnvironment());
if (((ValidateConfig) config).cluster != null) {
logValidationResult("Cluster configuration",
validateCluster(vConfig.cluster));
} else {
logValidationResult("Installer Configuration",
validateConfiguration());
}
}
private void logValidationResult(String prefix, boolean isValid) {
if (!isValid) {
LOGGER.fatal(prefix + ERROR);
} else {
LOGGER.info(prefix + OK);
}
}
@Override
protected CommandConfig getCommandConfig() {
return new ValidateConfig();
}
@Override
protected String getUsageDescription() {
return "\nValidate the installer's configuration or a cluster configuration"
+ "\nUsage"
+ "\nFor validating the installer configuration"
+ "\nuse managix validate"
+ "\n\nFor validating a cluster configuration"
+ "\nuse managix validate -c <path to the cluster configuration file>";
}
public boolean validateEnvironment() throws Exception {
boolean valid = true;
String managixHome = System.getenv(InstallerDriver.ENV_MANAGIX_HOME);
if (managixHome == null) {
valid = false;
LOGGER.fatal(InstallerDriver.ENV_MANAGIX_HOME + " not set " + ERROR);
} else {
File home = new File(managixHome);
if (!home.exists()) {
valid = false;
LOGGER.fatal(InstallerDriver.ENV_MANAGIX_HOME + ": "
+ home.getAbsolutePath() + " does not exist!" + ERROR);
}
}
return valid;
}
public boolean validateCluster(String clusterPath) throws Exception {
boolean valid = true;
Cluster cluster = null;
File f = new File(clusterPath);
if (!f.exists() || !f.isFile()) {
LOGGER.error(" Invalid path " + f.getAbsolutePath() + ERROR);
valid = false;
} else {
JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
Unmarshaller unmarshaller = ctx.createUnmarshaller();
cluster = (Cluster) unmarshaller.unmarshal(new File(clusterPath));
validateClusterProperties(cluster);
Set<String> servers = new HashSet<String>();
Set<String> serverIds = new HashSet<String>();
servers.add(cluster.getMasterNode().getClusterIp());
serverIds.add(cluster.getMasterNode().getId());
MasterNode masterNode = cluster.getMasterNode();
Node master = new Node(masterNode.getId(),
masterNode.getClusterIp(), masterNode.getJavaOpts(),
masterNode.getJavaHome(), masterNode.getLogdir(), null,
null, null);
valid = valid & validateNodeConfiguration(master, cluster);
for (Node node : cluster.getNode()) {
servers.add(node.getClusterIp());
if (serverIds.contains(node.getId())) {
valid = false;
LOGGER.error("Duplicate node id :" + node.getId() + ERROR);
} else {
valid = valid & validateNodeConfiguration(node, cluster);
}
}
}
return valid;
}
private void validateClusterProperties(Cluster cluster) {
List<String> tempDirs = new ArrayList<String>();
if (cluster.getLogdir() != null
&& checkTemporaryPath(cluster.getLogdir())) {
tempDirs.add("Log directory: " + cluster.getLogdir());
}
if (cluster.getIodevices() != null
&& checkTemporaryPath(cluster.getIodevices())) {
tempDirs.add("IO Device: " + cluster.getIodevices());
}
if (tempDirs.size() > 0) {
StringBuffer msg = new StringBuffer();
msg.append("The following paths are subject to be cleaned up by OS");
for (String tempDir : tempDirs) {
msg.append("\n" + tempDir + WARNING);
}
LOGGER.warn(msg);
}
}
private boolean validateNodeConfiguration(Node node, Cluster cluster) {
boolean valid = true;
valid = checkNodeReachability(node.getClusterIp());
if (node.getJavaHome() == null || node.getJavaHome().length() == 0) {
if (cluster.getJavaHome() == null
|| cluster.getJavaHome().length() == 0) {
valid = false;
LOGGER.fatal("java_home not defined at cluster/node level for node: "
+ node.getId() + ERROR);
}
}
if (node.getLogdir() == null || node.getLogdir().length() == 0) {
if (cluster.getLogdir() == null
|| cluster.getLogdir().length() == 0) {
valid = false;
LOGGER.fatal("log_dir not defined at cluster/node level for node: "
+ node.getId() + ERROR);
}
}
if (node.getStore() == null || node.getStore().length() == 0) {
if (!cluster.getMasterNode().getId().equals(node.getId())
&& (cluster.getStore() == null || cluster.getStore()
.length() == 0)) {
valid = false;
LOGGER.fatal("store not defined at cluster/node level for node: "
+ node.getId() + ERROR);
}
}
if (node.getIodevices() == null || node.getIodevices().length() == 0) {
if (!cluster.getMasterNode().getId().equals(node.getId())
&& (cluster.getIodevices() == null || cluster
.getIodevices().length() == 0)) {
valid = false;
LOGGER.fatal("iodevice(s) not defined at cluster/node level for node: "
+ node.getId() + ERROR);
}
}
return valid;
}
private boolean checkTemporaryPath(String logdir) {
return logdir.startsWith("/tmp/");
}
public boolean validateConfiguration() throws Exception {
String managixHome = System.getenv(InstallerDriver.ENV_MANAGIX_HOME);
File configFile = new File(managixHome + File.separator
+ InstallerDriver.MANAGIX_CONF_XML);
JAXBContext configCtx = JAXBContext.newInstance(Configuration.class);
Unmarshaller unmarshaller = configCtx.createUnmarshaller();
Configuration conf = (Configuration) unmarshaller.unmarshal(configFile);
return validateZookeeperConfiguration(conf);
}
private boolean validateZookeeperConfiguration(Configuration conf)
throws Exception {
boolean valid = true;
Zookeeper zk = conf.getZookeeper();
if (zk.getHomeDir() == null || zk.getHomeDir().length() == 0) {
valid = false;
LOGGER.fatal("Zookeeper home dir not configured" + ERROR);
} else if (checkTemporaryPath(zk.getHomeDir())) {
LOGGER.warn("Zookeeper home dir is subject to be cleaned up by OS"
+ WARNING);
}
if (zk.getServers().getServer().isEmpty()) {
valid = false;
LOGGER.fatal("Zookeeper servers not configured" + ERROR);
}
boolean validEnsemble = true;
for (String server : zk.getServers().getServer()) {
validEnsemble = validEnsemble && checkNodeReachability(server);
}
return valid;
}
private boolean checkNodeReachability(String server) {
boolean reachable = true;
try {
InetAddress address = InetAddress.getByName(server);
if (!address.isReachable(1000)) {
LOGGER.fatal("\n" + "Server: " + server + " unreachable"
+ ERROR);
reachable = false;
}
} catch (Exception e) {
reachable = false;
LOGGER.fatal("\n" + "Server: " + server + " Invalid address"
+ ERROR);
}
return reachable;
}
}
class ValidateConfig extends CommandConfig {
@Option(name = "-c", required = false, usage = "Path to the cluster configuration xml")
public String cluster;
}