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@1693 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-events/src/main/resources/events/cc_start/cc_start.sh b/asterix-events/src/main/resources/events/cc_start/cc_start.sh
index 37645bc..003d9cf 100755
--- a/asterix-events/src/main/resources/events/cc_start/cc_start.sh
+++ b/asterix-events/src/main/resources/events/cc_start/cc_start.sh
@@ -2,4 +2,5 @@
 then 
   mkdir -p $LOG_DIR
 fi
+cd $WORKING_DIR
 $ASTERIX_HOME/bin/asterixcc -client-net-ip-address $CLIENT_NET_IP -client-net-port 1098 -cluster-net-ip-address $CLUSTER_NET_IP -cluster-net-port 1099 -http-port 8888  &> $LOG_DIR/cc.log
diff --git a/asterix-events/src/main/resources/events/node_join/nc_join.sh b/asterix-events/src/main/resources/events/node_join/nc_join.sh
index 6b5280b..d8bbbd2 100755
--- a/asterix-events/src/main/resources/events/node_join/nc_join.sh
+++ b/asterix-events/src/main/resources/events/node_join/nc_join.sh
@@ -5,4 +5,5 @@
 then 
   mkdir -p $LOG_DIR
 fi
+cd $WORKING_DIR
 $ASTERIX_HOME/bin/asterixnc -node-id $NC_ID -cc-host $CC_HOST -cc-port 1099 -cluster-net-ip-address $IP_LOCATION  -data-ip-address $IP_LOCATION -iodevices $IO_DEVICES -result-ip-address $IP_LOCATION &> $LOG_DIR/${NC_ID}.log
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 fd0af04..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,15 +18,13 @@
 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;
 import edu.uci.ics.asterix.event.schema.cluster.Property;
-import edu.uci.ics.asterix.event.schema.cluster.WorkingDir;
 import edu.uci.ics.asterix.event.schema.pattern.Patterns;
 import edu.uci.ics.asterix.installer.driver.InstallerDriver;
 import edu.uci.ics.asterix.installer.driver.InstallerUtil;
@@ -38,95 +36,85 @@
 
 public class CreateCommand extends AbstractCommand {
 
-	private String asterixInstanceName;
-	private Cluster cluster;
+    private String asterixInstanceName;
+    private Cluster cluster;
 
-	@Override
-	protected void execCommand() throws Exception {
-		InstallerDriver.initConfig();
-		ValidateCommand validateCommand = new ValidateCommand();
-		boolean valid = validateCommand
-				.validateCluster(((CreateConfig) config).clusterPath);
-		if (!valid) {
-			throw new Exception("Cannot create an Asterix instance.");
-		}
-		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));
-		AsterixInstance asterixInstance = InstallerUtil.createAsterixInstance(
-				asterixInstanceName, cluster);
-		InstallerUtil.evaluateConflictWithOtherInstances(asterixInstance);
-		InstallerUtil.createAsterixZip(asterixInstance, true);
-		List<Property> clusterProperties = new ArrayList<Property>();
-		clusterProperties.add(new Property("ASTERIX_HOME", cluster
-				.getWorkingDir().getDir() + File.separator + "asterix"));
-		StringBuilder javaOpts = new StringBuilder();
-		if (cluster.getJavaOpts() != null) {
-			javaOpts.append(cluster.getJavaOpts());
-		}
-		clusterProperties.add(new Property("JAVA_OPTS", javaOpts.toString()));
-		clusterProperties.add(new Property("CLUSTER_NET_IP", cluster
-				.getMasterNode().getClusterIp()));
-		clusterProperties.add(new Property("CLIENT_NET_IP", cluster
-				.getMasterNode().getClientIp()));
-		clusterProperties.add(new Property("LOG_DIR", cluster.getLogdir()));
-		clusterProperties.add(new Property("JAVA_HOME", cluster.getJavaHome()));
-		clusterProperties.add(new Property("WORKING_DIR", cluster
-				.getWorkingDir().getDir()));
-		cluster.setEnv(new Env(clusterProperties));
+    @Override
+    protected void execCommand() throws Exception {
+        InstallerDriver.initConfig();
+        ValidateCommand validateCommand = new ValidateCommand();
+        boolean valid = validateCommand.validateCluster(((CreateConfig) config).clusterPath);
+        if (!valid) {
+            throw new Exception("Cannot create an Asterix instance.");
+        }
+        asterixInstanceName = ((CreateConfig) config).name;
+        InstallerUtil.validateAsterixInstanceNotExists(asterixInstanceName);
+        CreateConfig createConfig = (CreateConfig) config;
+        cluster = EventUtil.getCluster(createConfig.clusterPath);
+        AsterixInstance asterixInstance = InstallerUtil.createAsterixInstance(asterixInstanceName, cluster);
+        InstallerUtil.evaluateConflictWithOtherInstances(asterixInstance);
+        InstallerUtil.createAsterixZip(asterixInstance, true);
+        List<Property> clusterProperties = new ArrayList<Property>();
+        clusterProperties.add(new Property("ASTERIX_HOME", cluster.getWorkingDir().getDir() + File.separator
+                + "asterix"));
+        StringBuilder javaOpts = new StringBuilder();
+        if (cluster.getJavaOpts() != null) {
+            javaOpts.append(cluster.getJavaOpts());
+        }
+        clusterProperties.add(new Property("JAVA_OPTS", javaOpts.toString()));
+        clusterProperties.add(new Property("CLUSTER_NET_IP", cluster.getMasterNode().getClusterIp()));
+        clusterProperties.add(new Property("CLIENT_NET_IP", cluster.getMasterNode().getClientIp()));
+        clusterProperties.add(new Property("LOG_DIR", cluster.getLogdir()));
+        clusterProperties.add(new Property("JAVA_HOME", cluster.getJavaHome()));
+        clusterProperties.add(new Property("WORKING_DIR", cluster.getWorkingDir().getDir()));
+        cluster.setEnv(new Env(clusterProperties));
 
-		PatternCreator pc = new PatternCreator();
-		Patterns patterns = pc.getStartAsterixPattern(asterixInstanceName,
-				cluster);
-		InstallerUtil.getEventrixClient(cluster).submit(patterns);
+        EventrixClient eventrixClient = InstallerUtil.getEventrixClient(cluster);
+        PatternCreator pc = new PatternCreator();
 
-		AsterixRuntimeState runtimeState = VerificationUtil
-				.getAsterixRuntimeState(asterixInstance);
-		VerificationUtil.updateInstanceWithRuntimeDescription(asterixInstance,
-				runtimeState, true);
-		ServiceProvider.INSTANCE.getLookupService().writeAsterixInstance(
-				asterixInstance);
-		InstallerUtil.deleteDirectory(InstallerDriver.getManagixHome()
-				+ File.separator + InstallerDriver.ASTERIX_DIR + File.separator
-				+ asterixInstanceName);
-		LOGGER.info(asterixInstance.getDescription(false));
-	}
+        Patterns asterixBinarytrasnferPattern = pc.getAsterixBinaryTransferPattern(asterixInstanceName, cluster);
+        eventrixClient.submit(asterixBinarytrasnferPattern);
 
-	@Override
-	protected CommandConfig getCommandConfig() {
-		return new CreateConfig();
-	}
+        Patterns patterns = pc.getStartAsterixPattern(asterixInstanceName, cluster);
+        eventrixClient.submit(patterns);
 
-	public Cluster getCluster() {
-		return cluster;
-	}
+        AsterixRuntimeState runtimeState = VerificationUtil.getAsterixRuntimeState(asterixInstance);
+        VerificationUtil.updateInstanceWithRuntimeDescription(asterixInstance, runtimeState, true);
+        ServiceProvider.INSTANCE.getLookupService().writeAsterixInstance(asterixInstance);
+        InstallerUtil.deleteDirectory(InstallerDriver.getManagixHome() + File.separator + InstallerDriver.ASTERIX_DIR
+                + File.separator + asterixInstanceName);
+        LOGGER.info(asterixInstance.getDescription(false));
+    }
 
-	public String getAsterixInstanceName() {
-		return asterixInstanceName;
-	}
+    @Override
+    protected CommandConfig getCommandConfig() {
+        return new CreateConfig();
+    }
 
-	@Override
-	protected String getUsageDescription() {
-		return "\nCreates an ASTERIX instance with a specified name."
-				+ "\n\nPost creation, the instance is in ACTIVE state, indicating its "
-				+ "\navailability for executing statements/queries."
-				+ "\n\nUsage arguments/options:"
-				+ "\n-n Name of the ASTERIX instance."
-				+ "\n-c Path to the cluster configuration file";
-	}
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    public String getAsterixInstanceName() {
+        return asterixInstanceName;
+    }
+
+    @Override
+    protected String getUsageDescription() {
+        return "\nCreates an ASTERIX instance with a specified name."
+                + "\n\nPost creation, the instance is in ACTIVE state, indicating its "
+                + "\navailability for executing statements/queries." + "\n\nUsage arguments/options:"
+                + "\n-n Name of the ASTERIX instance." + "\n-c Path to the cluster configuration file";
+    }
 
 }
 
 class CreateConfig extends CommandConfig {
 
-	@Option(name = "-n", required = true, usage = "Name of Asterix Instance")
-	public String name;
+    @Option(name = "-n", required = true, usage = "Name of Asterix Instance")
+    public String name;
 
-	@Option(name = "-c", required = true, usage = "Path to cluster configuration")
-	public String clusterPath;
+    @Option(name = "-c", required = true, usage = "Path to cluster configuration")
+    public String clusterPath;
 
 }
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/StartCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/StartCommand.java
index 38bcf33..01fdda4 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/StartCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/StartCommand.java
@@ -18,6 +18,7 @@
 
 import org.kohsuke.args4j.Option;
 
+import edu.uci.ics.asterix.event.management.EventrixClient;
 import edu.uci.ics.asterix.event.schema.pattern.Patterns;
 import edu.uci.ics.asterix.installer.driver.InstallerDriver;
 import edu.uci.ics.asterix.installer.driver.InstallerUtil;
@@ -37,8 +38,13 @@
         AsterixInstance instance = InstallerUtil.validateAsterixInstanceExists(asterixInstanceName, State.INACTIVE);
         InstallerUtil.createAsterixZip(instance, false);
         PatternCreator pc = new PatternCreator();
+        EventrixClient client = InstallerUtil.getEventrixClient(instance.getCluster());
+        Patterns asterixBinaryTransferPattern = pc.getAsterixBinaryTransferPattern(asterixInstanceName,
+                instance.getCluster());
+        client.submit(asterixBinaryTransferPattern);
+
         Patterns patterns = pc.getStartAsterixPattern(asterixInstanceName, instance.getCluster());
-        InstallerUtil.getEventrixClient(instance.getCluster()).submit(patterns);
+        client.submit(patterns);
         InstallerUtil.deleteDirectory(InstallerDriver.getManagixHome() + File.separator + InstallerDriver.ASTERIX_DIR
                 + File.separator + asterixInstanceName);
         AsterixRuntimeState runtimeState = VerificationUtil.getAsterixRuntimeState(instance);
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/events/PatternCreator.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/events/PatternCreator.java
index f6aeafe..7612ca2 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/events/PatternCreator.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/events/PatternCreator.java
@@ -50,27 +50,37 @@
         p.setDelay(d);
     }
 
-    public Patterns getStartAsterixPattern(String asterixInstanceName, Cluster cluster) throws Exception {
-        String ccLocationId = cluster.getMasterNode().getId();
+    public Patterns getAsterixBinaryTransferPattern(String asterixInstanceName, Cluster cluster) throws Exception {
         String ccLocationIp = cluster.getMasterNode().getClusterIp();
-
         String destDir = cluster.getWorkingDir().getDir() + File.separator + "asterix";
         List<Pattern> ps = new ArrayList<Pattern>();
 
         Pattern copyHyracks = createCopyHyracksPattern(asterixInstanceName, cluster, ccLocationIp, destDir);
         ps.add(copyHyracks);
 
-        Pattern createCC = createCCStartPattern(ccLocationId);
-        addInitialDelay(createCC, 3, "sec");
-        ps.add(createCC);
-
         boolean copyHyracksToNC = !cluster.getWorkingDir().isNFS();
+
         for (Node node : cluster.getNode()) {
             if (copyHyracksToNC) {
                 Pattern copyHyracksForNC = createCopyHyracksPattern(asterixInstanceName, cluster, node.getClusterIp(),
                         destDir);
                 ps.add(copyHyracksForNC);
             }
+        }
+        ps.addAll(createHadoopLibraryTransferPattern(cluster).getPattern());
+        Patterns patterns = new Patterns(ps);
+        return patterns;
+    }
+
+    public Patterns getStartAsterixPattern(String asterixInstanceName, Cluster cluster) throws Exception {
+        String ccLocationId = cluster.getMasterNode().getId();
+        List<Pattern> ps = new ArrayList<Pattern>();
+
+        Pattern createCC = createCCStartPattern(ccLocationId);
+        addInitialDelay(createCC, 3, "sec");
+        ps.add(createCC);
+
+        for (Node node : cluster.getNode()) {
             String iodevices = node.getIodevices() == null ? cluster.getIodevices() : node.getIodevices();
             Pattern createNC = createNCStartPattern(cluster.getMasterNode().getClusterIp(), node.getId(),
                     asterixInstanceName + "_" + node.getId(), iodevices);
@@ -79,7 +89,6 @@
         }
 
         Patterns patterns = new Patterns(ps);
-        patterns.getPattern().addAll(createHadoopLibraryTransferPattern(cluster).getPattern());
         return patterns;
     }
 
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..b43fcdf 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("\n2) 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/managix b/asterix-installer/src/main/resources/scripts/managix
index cd0794e..3d2ac10 100755
--- a/asterix-installer/src/main/resources/scripts/managix
+++ b/asterix-installer/src/main/resources/scripts/managix
@@ -4,7 +4,6 @@
    exit 1
 fi
 
-VERSION=0.0.4-SNAPSHOT
 
 for jar in `ls $MANAGIX_HOME/lib/*.jar`
   do 
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