1) Added validate command: validates a zookeeper/cluster/installer configuration 
2) Added init command: auto-genration of configuration for pseudo-distributed local mode. 
3) Added shutdown hook for ensuring graceful shutdown of NCs when an asterix instance is shut.


git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization_ioc_installer@1294 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
index a8bd499..cee5b7f 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
@@ -2,6 +2,7 @@
 
 import java.rmi.RemoteException;
 import java.rmi.server.UnicastRemoteObject;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -21,6 +22,7 @@
     private AsterixAppRuntimeContext runtimeContext;
     private String nodeId;
     private boolean isMetadataNode = false;
+    private boolean stopInitiated = false;
 
     @Override
     public void start(INCApplicationContext ncAppCtx, String[] args) throws Exception {
@@ -33,19 +35,28 @@
         runtimeContext = new AsterixAppRuntimeContext(ncApplicationContext);
         runtimeContext.initialize();
         ncApplicationContext.setApplicationObject(runtimeContext);
+        JVMShutdownHook sHook = new JVMShutdownHook(this);
+        Runtime.getRuntime().addShutdownHook(sHook);
 
     }
 
     @Override
     public void stop() throws Exception {
-        if (LOGGER.isLoggable(Level.INFO)) {
-            LOGGER.info("Stopping Asterix node controller: " + nodeId);
-        }
+        if (!stopInitiated) {
+            stopInitiated = true;
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Stopping Asterix node controller: " + nodeId);
+            }
 
-        if (isMetadataNode) {
-            MetadataBootstrap.stopUniverse();
+            if (isMetadataNode) {
+                MetadataBootstrap.stopUniverse();
+            }
+            runtimeContext.deinitialize();
+        } else {
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Duplicate attempt to stop ignored: " + nodeId);
+            }
         }
-        runtimeContext.deinitialize();
     }
 
     @Override
@@ -74,4 +85,30 @@
             LOGGER.info("Metadata node bound");
         }
     }
+
+    /**
+     * Shutdown hook that invokes {@link NCApplicationEntryPoint#stop() stop} method.
+     */
+    private static class JVMShutdownHook extends Thread {
+
+        private final NCApplicationEntryPoint ncAppEntryPoint;
+
+        public JVMShutdownHook(NCApplicationEntryPoint ncAppEntryPoint) {
+            this.ncAppEntryPoint = ncAppEntryPoint;
+        }
+
+        public void run() {
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Shutdown hook in progress");
+            }
+            try {
+                ncAppEntryPoint.stop();
+            } catch (Exception e) {
+                if (LOGGER.isLoggable(Level.WARNING)) {
+                    LOGGER.warning("Exception in executing shutdown hook" + e);
+                }
+            }
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/asterix-events/src/main/resources/events/node_failure/nc_failure.sh b/asterix-events/src/main/resources/events/node_failure/nc_failure.sh
index fc4a0be..3ca083c 100755
--- a/asterix-events/src/main/resources/events/node_failure/nc_failure.sh
+++ b/asterix-events/src/main/resources/events/node_failure/nc_failure.sh
@@ -4,4 +4,4 @@
 PARENT_ID=`echo  $INFO | cut -d " "  -f2`
 PID_INFO=`ps -ef |  grep asterix | grep -v grep | grep -v nc_join |  grep $PARENT_ID`
 PID=`echo $PID_INFO | cut -d " " -f2`
-kill -9 $PID
+kill -15 $PID
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java
index 179412f..3f07e71 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java
@@ -46,6 +46,12 @@
             case STOP:
                 cmd = new StopCommand();
                 break;
+            case VALIDATE:
+                cmd = new ValidateCommand();
+                break;
+            case INIT:
+                cmd = new InitializeCommand();
+                break;
         }
         cmd.execute(args);
     }
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 48016a5..38c542f 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
@@ -42,6 +42,11 @@
 
     @Override
     protected void execCommand() throws Exception {
+        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;
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java
index 2822337..0c13db6 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java
@@ -17,7 +17,7 @@
 public interface ICommand {
 
 	public enum CommandType {
-		CREATE, DELETE, START, STOP, BACKUP, RESTORE, DESCRIBE, ALTER
+		CREATE, DELETE, START, STOP, BACKUP, RESTORE, DESCRIBE, ALTER, VALIDATE, INIT
 	}
 
 	public void execute(String args[]) throws Exception;
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/InitializeCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/InitializeCommand.java
new file mode 100644
index 0000000..c175410
--- /dev/null
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/InitializeCommand.java
@@ -0,0 +1,72 @@
+package edu.uci.ics.asterix.installer.command;
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+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.WorkingDir;
+import edu.uci.ics.asterix.installer.driver.InstallerDriver;
+import edu.uci.ics.asterix.installer.schema.conf.Configuration;
+
+public class InitializeCommand extends AbstractCommand {
+
+    @Override
+    protected void execCommand() throws Exception {
+        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));
+
+        String workingDir = InstallerDriver.getManagixHome() + File.separator + "clusters" + File.separator + "local"
+                + File.separator + "working_dir";
+        cluster.setWorkingDir(new WorkingDir(workingDir, true));
+        cluster.setStore(workingDir + File.separator + "storage");
+        cluster.setLogdir(workingDir + File.separator + "logs");
+        cluster.setJavaHome(System.getenv("JAVA_HOME"));
+
+        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();
+        Configuration configuration = (Configuration) unmarshaller.unmarshal(new File(installerConfPath));
+
+        configuration.getZookeeper().setHomeDir(workingDir + File.separator + "zookeeper");
+        marshaller = ctx.createMarshaller();
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+        marshaller.marshal(configuration, new FileOutputStream(installerConfPath));
+
+    }
+
+    @Override
+    protected String getUsageDescription() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    protected CommandConfig getCommandConfig() {
+        return new InitializeConfig();
+    }
+
+    public static void main(String args[]) throws Exception {
+        new InitializeCommand().execCommand();
+    }
+}
+
+class InitializeConfig implements CommandConfig {
+
+    @Option(name = "-h", required = false, usage = "Help")
+    public boolean help = false;
+
+}
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
new file mode 100644
index 0000000..574bfc7
--- /dev/null
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java
@@ -0,0 +1,244 @@
+/*
+ * 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;
+import edu.uci.ics.asterix.installer.service.ILookupService;
+import edu.uci.ics.asterix.installer.service.ServiceProvider;
+
+public class ValidateCommand extends AbstractCommand {
+
+    private static final String OK = " [" + "\u2713" + "]";
+    private static final String ERROR = " [" + "x" + "]";
+    private static final String WARNING = " [" + "!" + "]";
+
+    @Override
+    protected void execCommand() throws Exception {
+        ValidateConfig vConfig = (ValidateConfig) config;
+        logValidationResult("Enviornment", 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 null;
+    }
+
+    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;
+        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 = (Cluster) unmarshaller.unmarshal(new File(clusterPath));
+            validateClusterProperties(cluster);
+
+            Set<String> servers = new HashSet<String>();
+            Set<String> serverIds = new HashSet<String>();
+            servers.add(cluster.getMasterNode().getIp());
+            serverIds.add(cluster.getMasterNode().getId());
+
+            MasterNode masterNode = cluster.getMasterNode();
+            Node master = new Node(masterNode.getId(), masterNode.getIp(), masterNode.getRam(),
+                    masterNode.getJavaHome(), masterNode.getLogdir(), null);
+
+            valid = valid & validateNodeConfiguration(master, cluster);
+
+            for (Node node : cluster.getNode()) {
+                servers.add(node.getIp());
+                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.getStore() != null && checkTemporaryPath(cluster.getStore())) {
+            tempDirs.add("Store directory: " + cluster.getStore());
+        }
+
+        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.getIp());
+        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 || cluster.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.getRam() == null || node.getRam().length() == 0) {
+            if (cluster.getRam() == null || cluster.getRam().length() == 0) {
+                valid = false;
+                LOGGER.fatal("ram 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 implements CommandConfig {
+
+    @Option(name = "-h", required = false, usage = "Help")
+    public boolean help = false;
+
+    @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/driver/InstallerDriver.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/driver/InstallerDriver.java
index f435b8d..1c2f8fd 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/driver/InstallerDriver.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/driver/InstallerDriver.java
@@ -24,6 +24,7 @@
 import org.apache.log4j.Logger;
 
 import edu.uci.ics.asterix.installer.command.CommandHandler;
+import edu.uci.ics.asterix.installer.command.ICommand.CommandType;
 import edu.uci.ics.asterix.installer.schema.conf.Configuration;
 import edu.uci.ics.asterix.installer.service.ILookupService;
 import edu.uci.ics.asterix.installer.service.ServiceProvider;
@@ -38,8 +39,8 @@
     public static final String EVENTS_DIR = "events";
 
     private static final Logger LOGGER = Logger.getLogger(InstallerDriver.class.getName());
-    private static final String ENV_MANAGIX_HOME = "MANAGIX_HOME";
-    private static final String MANAGIX_CONF_XML = "conf" + File.separator + "installer-conf.xml";
+    public static final String ENV_MANAGIX_HOME = "MANAGIX_HOME";
+    public static final String MANAGIX_CONF_XML = "conf" + File.separator + "installer-conf.xml";
 
     private static Configuration conf;
     private static String managixHome;
@@ -54,7 +55,6 @@
     }
 
     private static void initConfig() throws Exception {
-        managixHome = System.getenv(ENV_MANAGIX_HOME);
         File configFile = new File(managixHome + File.separator + MANAGIX_CONF_XML);
         JAXBContext configCtx = JAXBContext.newInstance(Configuration.class);
         Unmarshaller unmarshaller = configCtx.createUnmarshaller();
@@ -100,7 +100,11 @@
     public static void main(String args[]) {
         try {
             if (args.length != 0) {
-                initConfig();
+                managixHome = System.getenv(ENV_MANAGIX_HOME);
+                CommandType cmdType = CommandType.valueOf(args[0].toUpperCase());
+                if (!cmdType.equals(CommandType.VALIDATE)) {
+                    initConfig();
+                }
                 CommandHandler cmdHandler = new CommandHandler();
                 cmdHandler.processCommand(args);
             } else {
@@ -125,6 +129,9 @@
         buffer.append("restore  " + ":" + " Restores an asterix instance" + "\n");
         buffer.append("alter    " + ":" + " Alters the configuration for an existing asterix instance" + "\n");
         buffer.append("describe " + ":" + " Describes an existing asterix instance" + "\n");
+        buffer.append("validate " + ":" + " Validates the installer/cluster configuration" + "\n");
+        buffer.append("init     " + ":"
+                + " Initialize the installer/cluster configuration for local psedu-distributed cluster." + "\n");
         LOGGER.info(buffer.toString());
     }
 }
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 a35da73..cbd9a7f 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
@@ -23,6 +23,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.log4j.Logger;
 import org.apache.zookeeper.CreateMode;
@@ -103,6 +104,12 @@
         }
         Runtime.getRuntime().exec(cmdBuffer.toString());
         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);
+        }
         msgQ.take();
         createRootIfNotExist();
     }
diff --git a/asterix-installer/src/main/resources/conf/asterix.conf b/asterix-installer/src/main/resources/clusters/local/conf/asterix.conf
similarity index 100%
rename from asterix-installer/src/main/resources/conf/asterix.conf
rename to asterix-installer/src/main/resources/clusters/local/conf/asterix.conf
diff --git a/asterix-installer/src/main/resources/clusters/local.xml b/asterix-installer/src/main/resources/clusters/local/local.xml
similarity index 100%
rename from asterix-installer/src/main/resources/clusters/local.xml
rename to asterix-installer/src/main/resources/clusters/local/local.xml
diff --git a/asterix-installer/src/main/resources/conf/log4j.properties b/asterix-installer/src/main/resources/conf/log4j.properties
index b951c14..fedf941 100644
--- a/asterix-installer/src/main/resources/conf/log4j.properties
+++ b/asterix-installer/src/main/resources/conf/log4j.properties
@@ -3,7 +3,7 @@
 log4j.appender.A1=org.apache.log4j.ConsoleAppender
 log4j.appender.A1.layout=org.apache.log4j.PatternLayout
 # Print the date in ISO 8601 format
-log4j.appender.A1.layout.ConversionPattern=%d %-p: %n%m%n
+log4j.appender.A1.layout.ConversionPattern=%-p: %m%n
 
 log4j.logger.edu.uci.ics.asterix.event.management=error
 log4j.logger.org.apache.zookeeper=error
diff --git a/asterix-installer/src/main/resources/zookeeper/zk.init b/asterix-installer/src/main/resources/zookeeper/zk.init
index 9b554b1..937d8b3 100755
--- a/asterix-installer/src/main/resources/zookeeper/zk.init
+++ b/asterix-installer/src/main/resources/zookeeper/zk.init
@@ -1,11 +1,11 @@
 ZK_HOME=$1
 shift 1
-cd $MANAGIX_HOME/.managix/zookeeper
+cd $MANAGIX_HOME/.installer/zookeeper
 tar cf zk.pkg.tar *
 zk_server_id=1
 for zk_host in  $@
 do
-  ssh $zk_host "mkdir $ZK_HOME"
+  ssh $zk_host "mkdir -p $ZK_HOME"
   scp ./zk.pkg.tar $zk_host:$ZK_HOME/
   ssh $zk_host "cd $ZK_HOME && tar xf $ZK_HOME/zk.pkg.tar && chmod +x $ZK_HOME/bin/start_zk.sh"
   ssh $zk_host "$ZK_HOME/bin/start_zk.sh $ZK_HOME $zk_server_id" &