changeset 59:beab47f74ee6

Agent starts its own private mongod instance - Script to start/stop mongod instance. - Startup script for agent. - build.xml improvements which substitute values as appropriate.
author Jon VanAlten <jon.vanalten@redhat.com>
date Fri, 27 Jan 2012 11:46:45 -0500
parents d091ca03cead
children a55a4ed7e6b6
files README ant-build.properties app-info.properties build.xml config/agent.properties libs.properties scripts/localmongo.sh scripts/thermostat-agent src/com/redhat/thermostat/agent/Main.java src/com/redhat/thermostat/agent/config/StartupConfiguration.java src/com/redhat/thermostat/app-info.properties src/com/redhat/thermostat/client/MongoConnection.java src/com/redhat/thermostat/common/Constants.java
diffstat 13 files changed, 432 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/README	Thu Jan 26 16:18:05 2012 -0500
+++ b/README	Fri Jan 27 11:46:45 2012 -0500
@@ -1,2 +1,16 @@
 Thank you for downloading Thermostat.
 
+REQUIREMENTS:
+
+MongoDB and associated Java driver
+http://www.mongodb.org/
+
+JFreeChart
+http://www.jfree.org/jfreechart/
+
+BUILDING THERMOSTAT:
+
+1. Read ant-build.properties, including in-line documentation, and edit as appropriate to
+   ensure required libraries can be found and the build otherwise configured to your liking.
+2. Run "ant dist".
+3. The resultant Thermostat system can now be found under the directory dist/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ant-build.properties	Fri Jan 27 11:46:45 2012 -0500
@@ -0,0 +1,23 @@
+# app-info.properties replacement values
+appinfo.version=0.0.1
+appinfo.releasedate=2012-02-02
+
+# needed libraries
+
+java.dir=/usr/share/java
+
+jcommon.dir=${java.dir}
+jcommon.ver=1.0.16
+jcommon.jar=${jcommon.dir}/jcommon.jar
+
+jfreechart.dir=${java.dir}/jfreechart
+jfreechart.ver=1.0.13
+jfreechart.jar=${jfreechart.dir}/jfreechart.jar
+
+mongo.dir=${java.dir}
+mongo.ver=2.6.5
+mongo.jar=${mongo.dir}/mongo.jar
+bson.jar=${mongo.dir}/bson.jar
+
+tools.dir=${java.home}/../lib
+tools.jar=${tools.dir}/tools.jar
--- a/app-info.properties	Thu Jan 26 16:18:05 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-APP_NAME = Thermostat
-APP_VERSION = 0.0.1
-APP_EMAIL = distro-pkg-dev@icedtea.classpath.org
-APP_WEBSITE = icedtea.classpath.org/wiki/Thermostat
-APP_DESCRIPTION = A monitoring and servicability tool for OpenJDK
-APP_RELEASE_DATE = 2012-02-02
-APP_COPYRIGHT = Copyright 2012 Red Hat, Inc.
-APP_LICENSE_SUMMARY = GPLv2+ with Classpath exceptions
-
--- a/build.xml	Thu Jan 26 16:18:05 2012 -0500
+++ b/build.xml	Fri Jan 27 11:46:45 2012 -0500
@@ -4,8 +4,9 @@
         Build the thermostat project
     </description>
 
-    <property name="config.dir" value="config" />
+    <property name="config.dir" location="config" />
     <property name="src.dir" location="src" />
+    <property name="scripts.dir" location="scripts" />
     <property name="build.dir" location="build" />
     <property name="classes.dir" location="${build.dir}/classes" />
     <property name="dist.dir" location="dist" />
@@ -17,30 +18,28 @@
     <property name="test.build.dir" location="${build.dir}/test" />
     <property name="reports.dir" location="reports" />
 
-    <property name="common.classes.dir" location="${classes.dir}/common" />
-    <property name="agent.classes.dir" location="${classes.dir}/agent" />
-    <property name="client-gui.classes.dir" location="${classes.dir}/client-gui" />
-
     <property name="common.jar" location="${dist.dir}/lib/thermostat-common.jar" />
     <property name="agent.jar" location="${dist.dir}/lib/thermostat-agent.jar" />
     <property name="client-gui.jar" location="${dist.dir}/lib/thermostat-client-gui.jar" />
 
     <property name="thermostat.path.prefix" value="com/redhat/thermostat/" />
+    <property name="common.path.prefix" value="${thermostat.path.prefix}common/" />
+    <property name="agent.path.prefix" value="${thermostat.path.prefix}agent/" />
+    <property name="backend.path.prefix" value="${thermostat.path.prefix}backend/" />
+    <property name="client-gui.path.prefix" value="${thermostat.path.prefix}client/" />
     <property name="agent-main-class" value="com.redhat.thermostat.agent.Main" />
     <property name="client-gui-main-class" value="com.redhat.thermostat.client.Main" />
 
     <property name="junit.out.xml.dir" location="${reports.dir}/junit/xml" />
     <property name="junit.out.html.dir" location="${reports.dir}/junit/html" />
 
-
-    <!-- allow users/packagers to override our default directories -->
-    <property file="custom-libs.properties" />
-    <!-- default locations for libraries -->
-    <property file="libs.properties" />
+    <!-- allow users/packagers to change default paths and other parameters -->
+    <property file="ant-build.properties" />
 
     <path id="agent.classpath" >
-        <pathelement path="${mongo.jar}"/>
-        <pathelement path="${tools.jar}"/>
+        <pathelement path="${mongo.jar}" />
+        <pathelement path="${bson.jar}" />
+        <pathelement path="${tools.jar}" />
     </path>
 
     <path id="client-gui.classpath">
@@ -59,59 +58,51 @@
     </target>
 
     <target name="build-common-classes">
-        <mkdir dir="${common.classes.dir}"/>
-        <javac srcdir="${src.dir}" destdir="${common.classes.dir}">
-            <include name="com/redhat/thermostat/common/**" />
+        <mkdir dir="${classes.dir}"/>
+        <javac srcdir="${src.dir}" destdir="${classes.dir}" debug="true">
+            <include name="${common.path.prefix}**" />
         </javac>
     </target>
 
-    <target name="common-jar" depends="build-common-classes">
+    <target name="common-jar" depends="build-common-classes,replace-properties">
         <mkdir dir="${dist.dir}" />
         <jar destfile="${common.jar}" duplicate="fail">
-            <fileset dir="${common.classes.dir}">
-                <include name="**/*.class" />
+            <fileset dir="${classes.dir}/">
+                <include name="${common.path.prefix}**/*.class" />
+                <include name="${common.path.prefix}**/*.properties" />
             </fileset>
-            <fileset dir="${src.dir}">
-                <include name="com/redhat/thermostat/common/**/*.properties" />
-            </fileset>
-            <zipfileset fullpath="${thermostat.path.prefix}${app-info.file}"
-                        dir="."
-                        includes="${app-info.file}" />
          </jar>
     </target>
 
     <target name="build-agent-classes" depends="build-common-classes">
-        <mkdir dir="${agent.classes.dir}"/>
-        <javac srcdir="${src.dir}" destdir="${agent.classes.dir}">
-            <include name="com/redhat/thermostat/agent/**" />
+        <mkdir dir="${classes.dir}"/>
+        <javac srcdir="${src.dir}" destdir="${classes.dir}" debug="true">
+            <include name="${agent.path.prefix}**" />
             <classpath>
-                <path location="${common.classes.dir}" />
+                <path location="${classes.dir}" />
                 <path refid="agent.classpath" />
             </classpath>
         </javac>
     </target>
 
-    <target name="agent-jar" depends="build-agent-classes">
+    <target name="agent-jar" depends="build-agent-classes,replace-properties">
         <mkdir dir="${dist.dir}" />
         <jar destfile="${agent.jar}" duplicate="fail">
-            <fileset dir="${agent.classes.dir}">
-                <include name="**/*.class" />
-            </fileset>
-            <fileset dir="${src.dir}">
-                <include name="com/redhat/thermostat/agent/**/*.properties" />
-            </fileset>
-            <fileset dir="${src.dir}">
-                <include name="com/redhat/thermostat/backend/**/*.properties" />
+            <fileset dir="${classes.dir}">
+                <include name="${agent.path.prefix}**/*.class" />
+                <include name="${backend.path.prefix}**/*.class" />
+                <include name="${agent.path.prefix}**/*.properties" />
+                <include name="${backend.path.prefix}**/*.properties" />
             </fileset>
          </jar>
     </target>
 
     <target name="build-client-gui-classes" depends="build-common-classes">
-        <mkdir dir="${client-gui.classes.dir}"/>
-        <javac srcdir="${src.dir}" destdir="${client-gui.classes.dir}">
-            <include name="com/redhat/thermostat/client/**" />
+        <mkdir dir="${classes.dir}"/>
+        <javac srcdir="${src.dir}" destdir="${classes.dir}" debug="true">
+            <include name="${client.path.prefix}**" />
             <classpath>
-                <path location="${common.classes.dir}" />
+                <path location="${classes.dir}" />
                 <path refid="client-gui.classpath" />
             </classpath>
         </javac>
@@ -120,17 +111,61 @@
     <target name="client-gui-jar" depends="build-client-gui-classes">
         <mkdir dir="${dist.dir}" />
         <jar destfile="${client-gui.jar}" duplicate="fail">
-            <fileset dir="${client-gui.classes.dir}">
-                <include name="**/*.class" />
-            </fileset>
-            <fileset dir="${src.dir}">
-                <include name="com/redhat/thermostat/client/**/*.properties" />
+            <fileset dir="${classes.dir}">
+                <include name="${client.path.prefix}**/*.class" />
+                <include name="${client.path.prefix}**/*.properties" />
             </fileset>
          </jar>
     </target>
 
+    <target name="replace-scripts">
+    	<property name="scripts.dest" location="${dist.dir}/scripts" />
+    	<mkdir dir="${scripts.dest}" />
+        <copy todir="${scripts.dest}">
+            <fileset dir="${scripts.dir}" />
+            <filterset>
+                <filter token="JAVA_DIR" value="${java.dir}" />
+                <filter token="JAVA_HOME" value="${java.home}" />
+                <filter token="AGENT_CLASSPATH" value="${agent.classpath}" />
+                <filter token="AGENT_PROPERTIES" value="${agent.properties}" />
+                <filter token="CLIENT_GUI_CLASSPATH" value="${client-gui.classpath}" />
+                <filter token="CONFIG_DIR" value="${config.dir}" />
+            </filterset>
+        </copy>
+        <chmod perm="a+x" type="file">
+        	<fileset dir="${scripts.dest}" />
+        </chmod>
+    </target>
+
+    <target name="replace-properties">
+        <copy todir="${classes.dir}">
+            <fileset dir="${src.dir}">
+                <include name="**/*.properties" />
+            </fileset>
+        	<filterset>
+                <filter token="DATE" value="${appinfo.releasedate}" />
+                <filter token="VERSION" value="{appinfo.version}" />
+        	</filterset>
+        </copy>
+    </target>
+
+    <target name="replace-config">
+        <property name="config.dest" location="${dist.dir}/config" />
+        <mkdir dir="${config.dest}" />
+        <copy todir="${config.dest}">
+            <fileset dir="${config.dir}" />
+            <filterset>
+        		<!-- FIXME this works only for the case of running things from ${dist.dir}.
+        		     If the dir is copied to some other system dir (aka 'installed') this
+        		     breaks.  Probably need an ant install target to make this work properly
+        		 -->
+        		<filter token="THERM_INSTALL_DIR" value="${dist.dir}" />
+            </filterset>
+        </copy>
+    </target>
+
     <target name="build-all"
-            depends="common-jar,agent-jar,client-gui-jar"
+            depends="common-jar,agent-jar,client-gui-jar,replace-scripts,replace-config"
             description="build all jars" />
 
     <target name="javadoc" description="generate javadoc">
@@ -140,10 +175,6 @@
     </target>
 
     <target name="dist" depends="build-all,javadoc" description="build everything">
-        <mkdir dir="${config.dir}" />
-        <copy todir="${dist.dir}/${config.dir}">
-            <fileset dir="${config.dir}" />
-        </copy>
     </target>
 
     <target name="all"
@@ -154,7 +185,6 @@
     <target name="build-test">
         <mkdir dir="${test.build.dir}" />
         <javac srcdir="${test.src.dir}" destdir="${test.build.dir}" debug="true">
-            <!-- <include name="**" /> -->
             <classpath>
                 <path refid="test.classpath" />
             </classpath>
--- a/config/agent.properties	Thu Jan 26 16:18:05 2012 -0500
+++ b/config/agent.properties	Fri Jan 27 11:46:45 2012 -0500
@@ -1,6 +1,7 @@
 ## Mongo storage configuration
 # To be used when agent is running with --local argument
 mongod_port=27518
+mongo_launch_script=@THERM_INSTALL_DIR@/scripts/localmongo.sh
 # To be used when connecting on localhost without --local argument (cluster)
 mongos_port=27517
 ### Below settings are used only by the mongo launch script
--- a/libs.properties	Thu Jan 26 16:18:05 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-# needed libraries
-
-default.java.dir=/usr/share/java
-
-jcommon.dir=${default.java.dir}
-jcommon.ver=1.0.16
-jcommon.jar=${jcommon.dir}/jcommon.jar
-
-jfreechart.dir=${default.java.dir}/jfreechart
-jfreechart.ver=1.0.13
-jfreechart.jar=${jfreechart.dir}/jfreechart.jar
-
-mongo.dir=${default.java.dir}
-mongo.ver=2.6.5
-mongo.jar=${mongo.dir}/mongo.jar
-
-tools.dir=${java.home}/../lib
-tools.jar=${tools.dir}/tools.jar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/localmongo.sh	Fri Jan 27 11:46:45 2012 -0500
@@ -0,0 +1,102 @@
+#!/bin/bash
+#
+# Copyright 2012 Red Hat, Inc.
+#
+# This file is part of Thermostat.
+#
+# Thermostat is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 2, or (at your
+# option) any later version.
+#
+# Thermostat is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Thermostat; see the file COPYING.  If not see
+# <http://www.gnu.org/licenses/>.
+#
+# Linking this code with other modules is making a combined work
+# based on this code.  Thus, the terms and conditions of the GNU
+# General Public License cover the whole combination.
+#
+# As a special exception, the copyright holders of this code give
+# you permission to link this code with independent modules to
+# produce an executable, regardless of the license terms of these
+# independent modules, and to copy and distribute the resulting
+# executable under terms of your choice, provided that you also
+# meet, for each linked independent module, the terms and conditions
+# of the license of that module.  An independent module is a module
+# which is not derived from or based on this code.  If you modify
+# this code, you may extend this exception to your version of the
+# library, but you are not obligated to do so.  If you do not wish
+# to do so, delete this exception statement from your version.
+#
+#####################################################################
+#
+# Find the directory where thermostat is installed.
+# Note this will not work if there are symlinks to resolve that
+# are not full paths.
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
+THERM_DIR=`dirname "$( cd -P "$( dirname "$SOURCE" )" && pwd )"`
+# Some variables are sourced from properties file
+. "${THERM_DIR}/config/agent.properties"
+# Other relevant directory/file locations
+USER_THERM_DIR="${HOME}/.thermostat"
+MONGO_DIR="${USER_THERM_DIR}/mongod"
+MONGO_PIDDIR="${MONGO_DIR}/run"
+MONGO_PIDFILE="${MONGO_PIDDIR}/mongod.pid"
+MONGO_PID=`cat ${MONGO_PIDFILE}`
+MONGO_LOGDIR="${MONGO_DIR}/log"
+MONGO_LOGFILE="${MONGO_LOGDIR}/mongod.log"
+# FIXME noauth is not really appropriate.
+MONGO_ARGS="--quiet --fork --nojournal --noauth --bind_ip 127.0.0.1 \
+    --dbpath ${MONGO_DIR} --logpath ${MONGO_LOGFILE} \
+    --pidfilepath ${MONGO_PIDFILE} --port ${mongod_port}"
+
+function make_directories {
+  mkdir -p "${MONGO_PIDDIR}"
+  mkdir -p "${MONGO_LOGDIR}"
+}
+
+function do_start {
+  if [ ! -z ${MONGO_PID} ]; then
+    echo "Private mongo instance already running"
+    exit -1
+  fi
+  make_directories
+  mongod ${MONGO_ARGS}
+}
+
+function do_stop {
+  if [ -z ${MONGO_PID} ]; then
+    echo "Private mongo instance not running"
+    exit -1
+  fi
+  MONGO_PID=`cat ${MONGO_PIDFILE}`
+  kill ${MONGO_PID}
+  rm -f ${MONGO_PIDFILE}
+}
+
+function usage {
+  echo "Usage:"
+  echo "  localmongo.sh <start|stop>"
+}
+
+if [ $# != 1 ]; then
+  usage
+  exit -1
+fi
+
+if [ $1 = "start" ]; then
+  do_start
+elif [ $1 = "stop" ]; then
+  do_stop
+else
+  usage
+  exit -1
+fi
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/thermostat-agent	Fri Jan 27 11:46:45 2012 -0500
@@ -0,0 +1,99 @@
+#!/bin/bash
+#
+# Copyright 2012 Red Hat, Inc.
+#
+# This file is part of Thermostat.
+#
+# Thermostat is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 2, or (at your
+# option) any later version.
+#
+# Thermostat is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Thermostat; see the file COPYING.  If not see
+# <http://www.gnu.org/licenses/>.
+#
+# Linking this code with other modules is making a combined work
+# based on this code.  Thus, the terms and conditions of the GNU
+# General Public License cover the whole combination.
+#
+# As a special exception, the copyright holders of this code give
+# you permission to link this code with independent modules to
+# produce an executable, regardless of the license terms of these
+# independent modules, and to copy and distribute the resulting
+# executable under terms of your choice, provided that you also
+# meet, for each linked independent module, the terms and conditions
+# of the license of that module.  An independent module is a module
+# which is not derived from or based on this code.  If you modify
+# this code, you may extend this exception to your version of the
+# library, but you are not obligated to do so.  If you do not wish
+# to do so, delete this exception statement from your version.
+#
+#####################################################################
+#
+# Some necessary variables.
+JAVA_DIR="@JAVA_DIR@"
+JAVA_EXE="@JAVA_HOME@/bin/java"
+JCOMMON_JAR="${JAVA_DIR}/jcommon.jar"
+JFREECHART_JAR="${JAVA_DIR}/jfreechart/jfreechart.jar"
+MONGO_JAR="${JAVA_DIR}/mongo.jar"
+BSON_JAR="${JAVA_DIR}/bson.jar"
+TOOLS_JAR="@JAVA_HOME@/../lib/tools.jar"
+AGENT_CLASSPATH="${JCOMMON_JAR}:${JFREECHART_JAR}:${MONGO_JAR}:${BSON_JAR}:${TOOLS_JAR}"
+# Find the directory where thermostat is installed.
+# Note this will not work if there are symlinks to resolve that
+# are not full paths.
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
+THERM_DIR=`dirname "$( cd -P "$( dirname "$SOURCE" )" && pwd )"`
+# Some other necessary variables.
+AGENT_CLASSPATH="${AGENT_CLASSPATH}:${THERM_DIR}/lib/thermostat-agent.jar:${THERM_DIR}/lib/thermostat-common.jar"
+AGENT_MAIN="com.redhat.thermostat.agent.Main"
+
+AGENT_ARGS="--local --properties ${THERM_DIR}/config/agent.properties"
+
+function usage {
+  echo "Usage:"
+  echo "  thermostat-agent <--local|--remote|--cluster>"
+}
+
+function run_agent {
+  ${JAVA_EXE} -cp ${AGENT_CLASSPATH} ${AGENT_MAIN} ${AGENT_ARGS}
+}
+
+function run_local {
+  AGENT_ARGS="${AGENT_ARGS} --local"
+  run_agent
+  exit $?
+}
+
+function run_remote {
+  echo "Remote agent not yet supported."
+  exit -1
+}
+
+function run_cluster {
+  echo "Cluster agent not yet supported."
+  exit -1
+}
+
+if [ $# != 1 ]; then
+  usage
+  exit -1
+fi
+
+if [ $1 = "--local" ]; then
+  run_local
+elif [ $1 = "--remote" ]; then
+  run_remote
+elif [ $1 = "--cluster" ]; then
+  run_cluster
+else
+  usage
+  exit -1
+fi
--- a/src/com/redhat/thermostat/agent/Main.java	Thu Jan 26 16:18:05 2012 -0500
+++ b/src/com/redhat/thermostat/agent/Main.java	Fri Jan 27 11:46:45 2012 -0500
@@ -36,13 +36,11 @@
 
 package com.redhat.thermostat.agent;
 
-import java.io.FileReader;
 import java.io.IOException;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Properties;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -73,20 +71,9 @@
         LoggingUtils.setGlobalLogLevel(Level.ALL);
         Logger logger = LoggingUtils.getLogger(Main.class);
 
-        Properties props = null;
-        try {
-            props = new Properties();
-            props.load(new FileReader(Constants.AGENT_PROPERTIES_FILE));
-        } catch (IOException ioe) {
-            logger.log(Level.SEVERE,
-                    "Unable to read properties file at " + Constants.AGENT_PROPERTIES_FILE,
-                    ioe);
-            System.exit(Constants.EXIT_UNABLE_TO_READ_PROPERTIES);
-        }
-
         StartupConfiguration config = null;
         try {
-            config = new StartupConfiguration(startTimestamp, argsAsList.toArray(new String[0]), props);
+            config = new StartupConfiguration(startTimestamp, argsAsList.toArray(new String[0]));
         } catch (LaunchException le) {
             logger.log(Level.SEVERE,
                     "Unable to instantiate startup configuration.",
@@ -95,6 +82,26 @@
         }
 
         LoggingUtils.setGlobalLogLevel(config.getLogLevel());
+
+        String mongoScript = config.getMongoLaunchScript();
+        if (config.getLocalMode()) {
+            try {
+                logger.fine("Starting private mongod instance.");
+                logger.finest("Mongo launch script at: " + mongoScript);
+                Process mongodStarter = Runtime.getRuntime().exec(mongoScript + " start");
+                int result = mongodStarter.waitFor();
+                if (result != 0) {
+                    logger.severe("Error starting local mongod instance.");
+                    System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE);
+                }
+            } catch (IOException e) {
+                logger.log(Level.SEVERE, "Unable to execute script to start local mongod instance.", e);
+                System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE);
+            } catch (InterruptedException e) {
+                logger.log(Level.SEVERE, "Interrupted while starting local mongod instance.", e);
+                System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE);
+            }
+        }
         Storage storage = new MongoStorage();
         try {
             storage.connect(config.getDatabaseURIAsString());
@@ -113,7 +120,6 @@
         }
 
         Agent agent = new Agent(backendRegistry, config, storage);
-        config.setAgent(agent);
         storage.setAgentId(agent.getId());
         try {
             logger.fine("Starting agent.");
@@ -134,5 +140,19 @@
 
         agent.stop();
         logger.fine("Agent stopped.");
+        if (config.getLocalMode()) {
+            logger.fine("Stopping private mongod instance.");
+            try {
+                Process mongodStopper = Runtime.getRuntime().exec(mongoScript + " stop");
+                int result = mongodStopper.waitFor();
+                if (result != 0) {
+                    logger.severe("Error stopping local mongod instance.");
+                }
+            } catch (IOException e) {
+                logger.log(Level.WARNING, "Unable to execute script to stop private mongod instance.", e);
+            } catch (InterruptedException e) {
+                logger.log(Level.SEVERE, "Interrupted while stopping local mongod instance.", e);
+            }
+        }
     }
 }
--- a/src/com/redhat/thermostat/agent/config/StartupConfiguration.java	Thu Jan 26 16:18:05 2012 -0500
+++ b/src/com/redhat/thermostat/agent/config/StartupConfiguration.java	Fri Jan 27 11:46:45 2012 -0500
@@ -36,6 +36,8 @@
 
 package com.redhat.thermostat.agent.config;
 
+import java.io.FileReader;
+import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
@@ -48,7 +50,6 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import com.redhat.thermostat.agent.Agent;
 import com.redhat.thermostat.agent.Defaults;
 import com.redhat.thermostat.common.Constants;
 import com.redhat.thermostat.common.LaunchException;
@@ -60,24 +61,23 @@
 
     private final long startTimestamp;
 
-    private Properties props;
+    private Properties props = new Properties();
     private Level logLevel;
     private boolean localMode;
     private int mongodPort;
+    private String mongoScript;
     private int mongosPort;
     private String databaseURI;
     private String completeDatabaseURI;
+    private Arguments arguments;
 
     private String hostname;
 
-    private Agent agent;
-
-    public StartupConfiguration(long startTime, String[] args, Properties props) throws LaunchException {
-        this.props = props;
+    public StartupConfiguration(long startTime, String[] args) throws LaunchException {
 
         initFromDefaults();
+        initFromArguments(args);
         initFromProperties();
-        initFromArguments(args);
 
         if (localMode) {
             completeDatabaseURI = databaseURI + ":" + mongodPort;
@@ -102,18 +102,22 @@
         databaseURI = Defaults.DATABASE_URI;
     }
 
-    private void initFromProperties() {
+    private void initFromProperties() throws LaunchException {
         if (props.getProperty(Constants.AGENT_PROPERTY_MONGOD_PORT) != null) {
             mongodPort = Integer.valueOf(props.getProperty(Constants.AGENT_PROPERTY_MONGOD_PORT));
         }
+        if (props.getProperty(Constants.AGENT_PROPERTY_MONGO_LAUNCH_SCRIPT) != null) {
+            mongoScript = props.getProperty(Constants.AGENT_PROPERTY_MONGO_LAUNCH_SCRIPT);
+            logger.finest("Mongo launch script at: " + mongoScript);
+        } else {
+            throw new LaunchException("No mongo launch script in properties.");
+        }
         if (props.getProperty(Constants.AGENT_PROPERTY_MONGOS_PORT) != null) {
             mongosPort = Integer.valueOf(props.getProperty(Constants.AGENT_PROPERTY_MONGOS_PORT));
         }
     }
 
     private void initFromArguments(String[] args) throws LaunchException {
-        Arguments arguments;
-
         arguments = new Arguments(args);
         if (arguments.isModeSpecified()) {
             localMode = arguments.getLocalMode();
@@ -127,6 +131,10 @@
         return logLevel;
     }
 
+    public String getMongoLaunchScript() {
+        return mongoScript;
+    }
+
     public String getDatabaseURIAsString() {
         return completeDatabaseURI;
     }
@@ -135,8 +143,14 @@
         return hostname;
     }
 
-    public void setAgent(Agent agent) {
-        this.agent = agent;
+    public boolean getLocalMode() {
+        boolean local = false;
+        try {
+            local = arguments.getLocalMode();
+        } catch (IllegalStateException ise) {
+            local = false;
+        }
+        return local;
     }
 
     public List<String> getStartupBackendClassNames() {
@@ -175,7 +189,7 @@
      * <p>
      * Please check that an option was specified (using the various is*Specified() methods) before using its value.
      */
-    private static class Arguments {
+    private class Arguments {
         private final boolean localMode;
         private final boolean modeSpecified;
         private final Level logLevel;
@@ -186,6 +200,7 @@
             boolean explicitMode = false;
             Level level = null;
             boolean explicitLogLevel = false;
+            boolean noProps = true;
             for (int index = 0; index < args.length; index++) {
                 if (args[index].equals(Constants.AGENT_ARGUMENT_LOGLEVEL)) {
                     index++;
@@ -202,8 +217,26 @@
                 } else if (args[index].equals(Constants.AGENT_ARGUMENT_LOCAL)) {
                     explicitMode = true;
                     local = true;
+                } else if (args[index].equals(Constants.AGENT_ARGUMENT_PROPERTIES)) {
+                    logger.finest("Properties argument specified.");
+                    index++;
+                    if (index < args.length) {
+                        String propFile = args[index];
+                        logger.finest("Properties file: " + propFile);
+                        try {
+                            props.load(new FileReader(propFile));
+                        } catch (IOException ioe) {
+                            throw new LaunchException("Unable to read properties file at " + propFile);
+                        }
+                        noProps = false;
+                    } else {
+                        throw new LaunchException("Missing argument for " + Constants.AGENT_ARGUMENT_PROPERTIES);
+                    }
                 }
             }
+            if (noProps) {
+                throw new LaunchException("Required properties file not specified.");
+            }
             logLevel = level;
             logLevelSpecified = explicitLogLevel;
             localMode = local;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/app-info.properties	Fri Jan 27 11:46:45 2012 -0500
@@ -0,0 +1,9 @@
+APP_NAME = Thermostat
+APP_VERSION = @VERSION@
+APP_EMAIL = distro-pkg-dev@icedtea.classpath.org
+APP_WEBSITE = icedtea.classpath.org/wiki/Thermostat
+APP_DESCRIPTION = A monitoring and servicability tool for OpenJDK
+APP_RELEASE_DATE = @DATE@
+APP_COPYRIGHT = Copyright 2012 Red Hat, Inc.
+APP_LICENSE_SUMMARY = GPLv2+ with Classpath exceptions
+
--- a/src/com/redhat/thermostat/client/MongoConnection.java	Thu Jan 26 16:18:05 2012 -0500
+++ b/src/com/redhat/thermostat/client/MongoConnection.java	Fri Jan 27 11:46:45 2012 -0500
@@ -62,7 +62,7 @@
                     m = new Mongo(getMongoURI());
                     db = m.getDB(StorageConstants.THERMOSTAT_DB_NAME);
                     /* the mongo java driver does not ensure this connection is actually working */
-                    testConnnection(db);
+                    testConnection(db);
                 } catch (MongoException e) {
                     fireChanged(ConnectionStatus.FAILED_TO_CONNECT);
                     return;
@@ -85,19 +85,28 @@
         connected = true;
     }
 
-    private static void testConnnection(DB db) {
+    private static void testConnection(DB db) {
         db.getCollection("agent-config").getCount();
     }
 
     private MongoURI getMongoURI() {
-        // FIXME hardcorded address
-        startMongoAndAgent();
-        return new MongoURI("mongodb://127.0.0.1:27017");
+        MongoURI uri = new MongoURI("mongodb://127.0.0.1:27017");
+        switch (getType()) {
+            case LOCAL:
+                startLocalAgent();
+                // FIXME hardcorded address, use config/agent.properties instead.
+                uri = new MongoURI("mongodb://127.0.0.1:27518");
+            case REMOTE:
+                // TODO
+            case CLUSTER:
+                // TODO
+        }
+        return uri;
     }
 
-    private void startMongoAndAgent() {
+    private void startLocalAgent() {
         // TODO implement this
-        logger.log(Level.WARNING, "startMongoAndAgent not implemented");
+        logger.log(Level.WARNING, "startLocalAgent not implemented");
         logger.log(Level.WARNING, "please start mongodb and agent yourself");
     }
 
@@ -111,14 +120,14 @@
             m.close();
         }
         if (isLocal) {
-            stopMongoAndAgent();
+            stopLocalAgent();
         }
         connected = false;
     }
 
-    private void stopMongoAndAgent() {
+    private void stopLocalAgent() {
         // TODO implement this
-        logger.log(Level.WARNING, "startMongoAndAgent not implemented");
+        logger.log(Level.WARNING, "stopLocalAgent not implemented");
         logger.log(Level.WARNING, "please stop mongodb and agent yourself");
     }
 
--- a/src/com/redhat/thermostat/common/Constants.java	Thu Jan 26 16:18:05 2012 -0500
+++ b/src/com/redhat/thermostat/common/Constants.java	Fri Jan 27 11:46:45 2012 -0500
@@ -42,8 +42,6 @@
  */
 public class Constants {
 
-    public static final String AGENT_PROPERTIES_FILE = "config/agent.properties";
-
     public static final int EXIT_UNKNOWN_ERROR = 1;
     public static final int EXIT_UNABLE_TO_CONNECT_TO_DATABASE = 2;
     public static final int EXIT_UNABLE_TO_READ_PROPERTIES = 3;
@@ -56,9 +54,11 @@
     public static final String AGENT_ARGUMENT_LOCAL = "--local";
     public static final String AGENT_ARGUMENT_LOGLEVEL = "--loglevel";
     public static final String AGENT_ARGUMENT_DEVEL = "--devel";
+    public static final String AGENT_ARGUMENT_PROPERTIES = "--properties";
 
     public static final String AGENT_PROPERTY_MONGOS_PORT = "mongos_port";
     public static final String AGENT_PROPERTY_MONGOD_PORT = "mongod_port";
+    public static final String AGENT_PROPERTY_MONGO_LAUNCH_SCRIPT = "mongo_launch_script";
     public static final String AGENT_PROPERTY_BACKENDS = "backends";
     public static final String AGENT_PROPERTY_BACKEND_ACTIVE = "active";