1) Fix for issue 324: Managix creates the ClusterControllerService folder in the home directory
2) Made transfer of binaries and subsequent use (to start asterix) as separate jobs with latter dependent on successful completion of the former. This fixes the "PermissionDenied" issue.
3) replaced use of /tmp with java.io.tmpdir
4) Added java home validation for Zookeeper.
5) Added validation for password-less SSH configuration for cluster and Zookeeper nodes.



git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_lsm_stabilization_324@1692 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
index 66c0102..1721666 100644
--- a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
@@ -69,10 +69,7 @@
     }
 
     public static Cluster initializeCluster(String path) throws JAXBException, IOException {
-        File file = new File(path);
-        JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
-        Unmarshaller unmarshaller = ctx.createUnmarshaller();
-        Cluster cluster = (Cluster) unmarshaller.unmarshal(file);
+        Cluster cluster = EventUtil.getCluster(path);
         for (Property p : cluster.getEnv().getProperty()) {
             env.put(p.getKey(), p.getValue());
         }
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
index e6c58eb..0761c7f 100644
--- a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
@@ -14,6 +14,7 @@
  */
 package edu.uci.ics.asterix.event.management;
 
+import java.io.File;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.text.DateFormat;
@@ -21,6 +22,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
 import edu.uci.ics.asterix.event.driver.EventDriver;
 import edu.uci.ics.asterix.event.management.ValueType.Type;
 import edu.uci.ics.asterix.event.schema.cluster.Cluster;
@@ -42,6 +47,25 @@
 	private static final String SCRIPT = "SCRIPT";
 	private static final String ARGS = "ARGS";
 	private static final String EXECUTE_SCRIPT = "events/execute.sh";
+	private static final String LOCALHOST = "localhost";
+	private static final String LOCALHOST_IP = "127.0.0.1";
+
+    public static Cluster getCluster(String clusterConfigurationPath)
+			throws JAXBException {
+		File file = new File(clusterConfigurationPath);
+		JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
+		Unmarshaller unmarshaller = ctx.createUnmarshaller();
+		Cluster cluster = (Cluster) unmarshaller.unmarshal(file);
+		if (cluster.getMasterNode().getClusterIp().equals(LOCALHOST)) {
+			cluster.getMasterNode().setClusterIp(LOCALHOST_IP);
+		}
+		for (Node node : cluster.getNode()) {
+			if (node.getClusterIp().equals(LOCALHOST)) {
+				node.setClusterIp(LOCALHOST_IP);
+			}
+		}
+		return cluster;
+	}
 
 	public static long parseTimeInterval(ValueType v, String unit)
 			throws IllegalArgumentException {
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/BackupCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/BackupCommand.java
index 297a168..261de22 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/BackupCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/BackupCommand.java
@@ -57,12 +57,11 @@
 
     @Override
     protected String getUsageDescription() {
-        return "\nIn an undesirable event of data loss either due to a disk/system"
-                + "\nfailure or accidental execution of a DDL statement (drop dataverse/dataset),"
-                + "\nyou may need to recover the lost data. The backup command allows you to take a"
+        return "\nThe backup command allows you to take a"
                 + "\nbackup of the data stored with an ASTERIX instance. "
-                + "\nThe backed up snapshot is stored in HDFS." + "\n\nAvailable arguments/options:"
-                + "\n-n name of the Asterix instance";
+                + "\nThe backed up snapshot is stored either in HDFS or on the local file system of each node in the ASTERIX cluster."
+                + "\nThe target location of backup can be configured in $MANAGIX_HOME/conf/managix-conf.xml"
+                + "\n\nAvailable arguments/options:" + "\n-n name of the Asterix instance";
 
     }
 
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java
index d22e6ce..e742c4e 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java
@@ -7,6 +7,7 @@
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 
+import edu.uci.ics.asterix.event.management.EventUtil;
 import edu.uci.ics.asterix.event.schema.cluster.Cluster;
 import edu.uci.ics.asterix.event.schema.cluster.WorkingDir;
 import edu.uci.ics.asterix.installer.driver.InstallerDriver;
@@ -19,10 +20,7 @@
         String localClusterPath = InstallerDriver.getManagixHome() + File.separator + "clusters" + File.separator
                 + "local" + File.separator + "local.xml";
 
-        JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
-        Unmarshaller unmarshaller = ctx.createUnmarshaller();
-        Cluster cluster = (Cluster) unmarshaller.unmarshal(new File(localClusterPath));
-
+        Cluster cluster = EventUtil.getCluster(localClusterPath);
         String workingDir = InstallerDriver.getManagixHome() + File.separator + "clusters" + File.separator + "local"
                 + File.separator + "working_dir";
         cluster.setWorkingDir(new WorkingDir(workingDir, true));
@@ -32,13 +30,14 @@
         cluster.setJavaHome(System.getenv("JAVA_HOME"));
         cluster.setJavaOpts("-Xmx1024m");
 
+        JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
         Marshaller marshaller = ctx.createMarshaller();
         marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
         marshaller.marshal(cluster, new FileOutputStream(localClusterPath));
 
         String installerConfPath = InstallerDriver.getManagixHome() + File.separator + InstallerDriver.MANAGIX_CONF_XML;
         ctx = JAXBContext.newInstance(Configuration.class);
-        unmarshaller = ctx.createUnmarshaller();
+        Unmarshaller unmarshaller = ctx.createUnmarshaller();
         Configuration configuration = (Configuration) unmarshaller.unmarshal(new File(installerConfPath));
 
         configuration.getBackup().setBackupDir(workingDir + File.separator + "backup");
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java
index 567f4d9..2de8e53 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java
@@ -18,11 +18,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.Unmarshaller;
-
 import org.kohsuke.args4j.Option;
 
+import edu.uci.ics.asterix.event.management.EventUtil;
 import edu.uci.ics.asterix.event.management.EventrixClient;
 import edu.uci.ics.asterix.event.schema.cluster.Cluster;
 import edu.uci.ics.asterix.event.schema.cluster.Env;
@@ -52,9 +50,7 @@
         asterixInstanceName = ((CreateConfig) config).name;
         InstallerUtil.validateAsterixInstanceNotExists(asterixInstanceName);
         CreateConfig createConfig = (CreateConfig) config;
-        JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
-        Unmarshaller unmarshaller = ctx.createUnmarshaller();
-        cluster = (Cluster) unmarshaller.unmarshal(new File(createConfig.clusterPath));
+        cluster = EventUtil.getCluster(createConfig.clusterPath);
         AsterixInstance asterixInstance = InstallerUtil.createAsterixInstance(asterixInstanceName, cluster);
         InstallerUtil.evaluateConflictWithOtherInstances(asterixInstance);
         InstallerUtil.createAsterixZip(asterixInstance, true);
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java
index 3d292a9..4e6460b 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java
@@ -26,242 +26,264 @@
 
 import org.kohsuke.args4j.Option;
 
+import edu.uci.ics.asterix.event.management.EventUtil;
 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.driver.InstallerUtil;
+import edu.uci.ics.asterix.installer.model.ProcessInfo;
 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" + "]";
+    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());
-		}
-	}
+    @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("Managix Configuration", validateConfiguration());
+        }
+    }
 
-	private void logValidationResult(String prefix, boolean isValid) {
-		if (!isValid) {
-			LOGGER.fatal(prefix + ERROR);
-		} else {
-			LOGGER.info(prefix + OK);
-		}
-	}
+    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 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>";
-	}
+    @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 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);
+    public boolean validateCluster(String clusterPath) throws Exception {
+        boolean valid = true;
+        Cluster cluster = null;
+        File f = new File(clusterPath);
+        List<String> ipAddresses = new ArrayList<String>();
+        if (!f.exists() || !f.isFile()) {
+            LOGGER.error(" Invalid path " + f.getAbsolutePath() + ERROR);
+            valid = false;
+        } else {
+            cluster = EventUtil.getCluster(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());
+            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);
+            MasterNode masterNode = cluster.getMasterNode();
+            Node master = new Node(masterNode.getId(), masterNode.getClusterIp(), masterNode.getJavaOpts(),
+                    masterNode.getJavaHome(), masterNode.getLogdir(), null, null, null);
+            ipAddresses.add(masterNode.getClusterIp());
 
-			valid = valid & validateNodeConfiguration(master, cluster);
+            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);
-				}
-			}
-		}
+            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);
+                    if (!ipAddresses.contains(node.getClusterIp())) {
+                        ipAddresses.add(node.getClusterIp());
+                    }
+                }
+            }
+        }
 
-		return valid;
-	}
+        if (valid) {
+            String username = cluster.getUsername();
+            if (username == null) {
+                username = System.getProperty("user.name");
+            }
+            valid = checkPasswordLessSSHLogin(username, ipAddresses);
+        }
+        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());
-		}
+    private boolean checkPasswordLessSSHLogin(String username, List<String> ipAddresses) throws Exception {
+        String script = InstallerDriver.getManagixHome() + File.separator + InstallerDriver.MANAGIX_INTERNAL_DIR
+                + File.separator + "scripts" + File.separator + "validate_ssh.sh";
+        List<String> args = ipAddresses;
+        args.add(0, username);
+        String output = InstallerUtil.executeLocalScript(script, args);
+        ipAddresses.remove(0);
+        for (String line : output.split("\n")) {
+            ipAddresses.remove(line);
+        }
+        if (ipAddresses.size() > 0) {
+            LOGGER.error(" Password-less SSH (from user account: " + username + " )"
+                    + " not configured for the following hosts");
+            for (String failedIp : ipAddresses) {
+                System.out.println(failedIp);
+            }
+            return false;
+        }
+        return true;
+    }
 
-		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 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);
-			}
-		}
+    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.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.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.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);
-			}
-		}
+        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);
+            }
+        }
 
-		return valid;
-	}
+        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);
+            }
+        }
 
-	private boolean checkTemporaryPath(String logdir) {
-		return logdir.startsWith("/tmp/");
+        return valid;
+    }
 
-	}
+    private boolean checkTemporaryPath(String logdir) {
+        return logdir.startsWith(System.getProperty("java.io.tmpdir"));
+    }
 
-	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);
-	}
+    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();
+    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.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);
-		}
+        if (zk.getServers().getServer() == null || 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);
-		}
+        if (zk.getServers().getJavaHome() == null || zk.getServers().getJavaHome().length() == 0) {
+            valid = false;
+            LOGGER.fatal("Java home not set for Zookeeper server in " + InstallerDriver.getManagixHome()
+                    + File.separator + InstallerDriver.MANAGIX_CONF_XML);
+        }
 
-		return valid;
-	}
+        for (String server : zk.getServers().getServer()) {
+            valid = valid && checkNodeReachability(server);
+        }
 
-	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;
-	}
+        if (valid)
+            valid = valid & checkPasswordLessSSHLogin(System.getProperty("user.name"), zk.getServers().getServer());
+        {
+        }
+
+        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;
+    @Option(name = "-c", required = false, usage = "Path to the cluster configuration xml")
+    public String cluster;
 
 }
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java
index b87d721..99f74ab 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java
@@ -107,9 +107,13 @@
         zk = new ZooKeeper(zkConnectionString, ZOOKEEPER_SESSION_TIME_OUT, watcher);
         String head = msgQ.poll(10, TimeUnit.SECONDS);
         if (head == null) {
-            String msg = "Unable to start Zookeeper Service. Please verify the configuration at "
-                    + InstallerDriver.getManagixHome() + File.separator + InstallerDriver.MANAGIX_CONF_XML;
-            throw new Exception(msg);
+            StringBuilder msg = new StringBuilder(
+                    "Unable to start Zookeeper Service. This could be because of the following reasons.\n");
+            msg.append("1) Managix is incorrectly configured. Please run " + InstallerDriver.getManagixHome()
+                    + "/bin/managix validate" + " to run a validation test and correct the errors reported.");
+            msg.append("2) If validation in (1) is successful, ensure that java_home parameter is set correctly in Managix configuration ("
+                    + InstallerDriver.getManagixHome() + File.separator + InstallerDriver.MANAGIX_CONF_XML + ")");
+            throw new Exception(msg.toString());
         }
         msgQ.take();
         createRootIfNotExist();
diff --git a/asterix-installer/src/main/resources/scripts/validate_ssh.sh b/asterix-installer/src/main/resources/scripts/validate_ssh.sh
new file mode 100755
index 0000000..f6dfed9
--- /dev/null
+++ b/asterix-installer/src/main/resources/scripts/validate_ssh.sh
@@ -0,0 +1,9 @@
+USERNAME=$1
+shift 1
+numargs=$#
+for ((i=1 ; i <= numargs ; i=i+2))
+do
+ host=$1
+ ssh -l $USERNAME -oNumberOfPasswordPrompts=0 $host "echo $host"
+ shift 1
+done