Merge remote-tracking branch 'origin/openvpn'
diff --git a/.gitignore b/.gitignore
index 7964faa..22a7898 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 proto
 *~
+localrc
diff --git a/build_lxc.sh b/build_lxc.sh
index e8612e6..191c493 100755
--- a/build_lxc.sh
+++ b/build_lxc.sh
@@ -1,5 +1,22 @@
 #!/usr/bin/env bash
 
+# Sanity check
+if [ "$EUID" -ne "0" ]; then
+  echo "This script must be run with root privileges."
+  exit 1
+fi
+
+# Warn users who aren't on natty
+if ! grep -q natty /etc/lsb-release; then
+    echo "WARNING: this script has only been tested on natty"
+fi
+
+# Source params
+source ./stackrc
+
+# Store cwd
+CWD=`pwd`
+
 # Configurable params
 BRIDGE=${BRIDGE:-br0}
 CONTAINER=${CONTAINER:-STACK}
@@ -9,22 +26,22 @@
 CONTAINER_GATEWAY=${CONTAINER_GATEWAY:-192.168.1.1}
 NAMESERVER=${NAMESERVER:-$CONTAINER_GATEWAY}
 COPYENV=${COPYENV:-1}
+DEST=${DEST:-/opt/stack}
 
 # Param string to pass to stack.sh.  Like "EC2_DMZ_HOST=192.168.1.1 MYSQL_USER=nova"
 STACKSH_PARAMS=${STACKSH_PARAMS:-}
 
-# Warn users who aren't on natty
-if ! grep -q natty /etc/lsb-release; then
-    echo "WARNING: this script has only been tested on natty"
-fi
+# Option to use the version of devstack on which we are currently working
+USE_CURRENT_DEVSTACK=${USE_CURRENT_DEVSTACK:-1}
+
 
 # Install deps
 apt-get install -y lxc debootstrap
 
 # Install cgroup-bin from source, since the packaging is buggy and possibly incompatible with our setup
 if ! which cgdelete | grep -q cgdelete; then
-    apt-get install -y g++ bison flex libpam0g-dev
-    wget http://sourceforge.net/projects/libcg/files/libcgroup/v0.37.1/libcgroup-0.37.1.tar.bz2/download -O /tmp/libcgroup-0.37.1.tar.bz2 
+    apt-get install -y g++ bison flex libpam0g-dev make
+    wget http://sourceforge.net/projects/libcg/files/libcgroup/v0.37.1/libcgroup-0.37.1.tar.bz2/download -O /tmp/libcgroup-0.37.1.tar.bz2
     cd /tmp && bunzip2 libcgroup-0.37.1.tar.bz2  && tar xfv libcgroup-0.37.1.tar
     cd libcgroup-0.37.1
     ./configure
@@ -51,27 +68,62 @@
     cgdelete -r cpu,net_cls:$CONTAINER
 fi
 
+# git clone only if directory doesn't exist already.  Since ``DEST`` might not
+# be owned by the installation user, we create the directory and change the
+# ownership to the proper user.
+function git_clone {
+    if [ ! -d $2 ]; then
+        sudo mkdir $2
+        sudo chown `whoami` $2
+        git clone $1 $2
+        cd $2
+        # This checkout syntax works for both branches and tags
+        git checkout $3
+    fi
+}
+
+# Location of the base image directory
+CACHEDIR=/var/cache/lxc/natty/rootfs-amd64
+
+# Provide option to do totally clean install
+if [ "$CLEAR_LXC_CACHE" = "1" ]; then
+    rm -rf $CACHEDIR
+fi
 
 # Warm the base image on first install
-CACHEDIR=/var/cache/lxc/natty/rootfs-amd64
-if [ ! -d $CACHEDIR ]; then
+if [ ! -f $CACHEDIR/bootstrapped ]; then
     # by deleting the container, we force lxc-create to re-bootstrap (lxc is
     # lazy and doesn't do anything if a container already exists)
     lxc-destroy -n $CONTAINER
     # trigger the initial debootstrap
     lxc-create -n $CONTAINER -t natty -f $LXC_CONF
     chroot $CACHEDIR apt-get update
-    chroot $CACHEDIR apt-get install -y --force-yes `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server)"`
+    chroot $CACHEDIR apt-get install -y --force-yes `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server|munin-node)"`
     chroot $CACHEDIR pip install `cat files/pips/*`
-    # FIXME (anthony) - provide ability to vary source locations
-    #git clone https://github.com/cloudbuilders/nova.git $CACHEDIR/opt/nova
-    bzr clone lp:~hudson-openstack/nova/milestone-proposed/ $CACHEDIR/opt/nova
-    git clone https://github.com/cloudbuilders/openstackx.git $CACHEDIR/opt/openstackx
-    git clone https://github.com/cloudbuilders/noVNC.git $CACHEDIR/opt/noVNC
-    git clone https://github.com/cloudbuilders/openstack-dashboard.git $CACHEDIR/opt/dash
-    git clone https://github.com/cloudbuilders/python-novaclient.git $CACHEDIR/opt/python-novaclient
-    git clone https://github.com/cloudbuilders/keystone.git $CACHEDIR/opt/keystone
-    git clone https://github.com/cloudbuilders/glance.git $CACHEDIR/opt/glance
+    touch $CACHEDIR/bootstrapped
+fi
+
+# Clean out code repos if directed to do so
+if [ "$CLEAN" = "1" ]; then
+    rm -rf $CACHEDIR/$DEST
+fi
+
+# Cache openstack code
+mkdir -p $CACHEDIR/$DEST
+git_clone $NOVA_REPO $CACHEDIR/$DEST/nova $NOVA_BRANCH
+git_clone $GLANCE_REPO $CACHEDIR/$DEST/glance $GLANCE_BRANCH
+git_clone $KEYSTONE_REPO $CACHEDIR/$DESTkeystone $KEYSTONE_BRANCH
+git_clone $NOVNC_REPO $CACHEDIR/$DEST/novnc $NOVNC_BRANCH
+git_clone $DASH_REPO $CACHEDIR/$DEST/dash $DASH_BRANCH $DASH_TAG
+git_clone $NIXON_REPO $CACHEDIR/$DEST/nixon $NIXON_BRANCH
+git_clone $NOVACLIENT_REPO $CACHEDIR/$DEST/python-novaclient $NOVACLIENT_BRANCH
+git_clone $OPENSTACKX_REPO $CACHEDIR/$DEST/openstackx $OPENSTACKX_BRANCH
+git_clone $MUNIN_REPO $CACHEDIR/$DEST/openstack-munin $MUNIN_BRANCH
+
+# Use this version of devstack?
+if [ "$USE_CURRENT_DEVSTACK" = "1" ]; then
+    rm -rf $CACHEDIR/$DEST/devstack
+    cp -pr $CWD $CACHEDIR/$DEST/devstack
 fi
 
 # Destroy the old container
@@ -88,15 +140,15 @@
 # Specify where our container rootfs lives
 ROOTFS=/var/lib/lxc/$CONTAINER/rootfs/
 
-# Create a stack user that is a member of the libvirtd group so that stack 
+# Create a stack user that is a member of the libvirtd group so that stack
 # is able to interact with libvirt.
 chroot $ROOTFS groupadd libvirtd
-chroot $ROOTFS useradd stack -s /bin/bash -d /opt -G libvirtd
+chroot $ROOTFS useradd stack -s /bin/bash -d $DEST -G libvirtd
 
 # a simple password - pass
 echo stack:pass | chroot $ROOTFS chpasswd
 
-# and has sudo ability (in the future this should be limited to only what 
+# and has sudo ability (in the future this should be limited to only what
 # stack requires)
 echo "stack ALL=(ALL) NOPASSWD: ALL" >> $ROOTFS/etc/sudoers
 
@@ -108,25 +160,25 @@
 # Gracefully cp only if source file/dir exists
 function cp_it {
     if [ -e $1 ] || [ -d $1 ]; then
-        cp -pr $1 $2
+        cp -pRL $1 $2
     fi
 }
 
 # Copy over your ssh keys and env if desired
 if [ "$COPYENV" = "1" ]; then
-    cp_it ~/.ssh $ROOTFS/opt/.ssh
-    cp_it ~/.ssh/id_rsa.pub $ROOTFS/opt/.ssh/authorized_keys
-    cp_it ~/.gitconfig $ROOTFS/opt/.gitconfig
-    cp_it ~/.vimrc $ROOTFS/opt/.vimrc
-    cp_it ~/.bashrc $ROOTFS/opt/.bashrc
+    cp_it ~/.ssh $ROOTFS/$DEST/.ssh
+    cp_it ~/.ssh/id_rsa.pub $ROOTFS/$DEST/.ssh/authorized_keys
+    cp_it ~/.gitconfig $ROOTFS/$DEST/.gitconfig
+    cp_it ~/.vimrc $ROOTFS/$DEST/.vimrc
+    cp_it ~/.bashrc $ROOTFS/$DEST/.bashrc
 fi
 
 # Make our ip address hostnames look nice at the command prompt
-echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/opt/.bashrc
+echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/$DEST/.bashrc
 echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/etc/profile
 
-# Give stack ownership over /opt so it may do the work needed
-chroot $ROOTFS chown -R stack /opt
+# Give stack ownership over $DEST so it may do the work needed
+chroot $ROOTFS chown -R stack $DEST
 
 # Configure instance network
 INTERFACES=$ROOTFS/etc/network/interfaces
@@ -142,7 +194,7 @@
 EOF
 
 # Configure the runner
-RUN_SH=$ROOTFS/opt/run.sh
+RUN_SH=$ROOTFS/$DEST/run.sh
 cat > $RUN_SH <<EOF
 #!/usr/bin/env bash
 # Make sure dns is set up
@@ -155,10 +207,13 @@
 # Install and run stack.sh
 sudo apt-get update
 sudo apt-get -y --force-yes install git-core vim-nox sudo
-if [ ! -d "/opt/devstack" ]; then
-    git clone git://github.com/cloudbuilders/devstack.git /opt/devstack
+if [ ! -d "$DEST/devstack" ]; then
+    git clone git://github.com/cloudbuilders/devstack.git $DEST/devstack
 fi
-cd /opt/devstack && $STACKSH_PARAMS ./stack.sh > /opt/run.sh.log
+cd $DEST/devstack && $STACKSH_PARAMS ./stack.sh > /$DEST/run.sh.log
+echo >> /$DEST/run.sh.log
+echo >> /$DEST/run.sh.log
+echo "All done! Time to start clicking." >> /$DEST/run.sh.log
 EOF
 
 # Make the run.sh executable
@@ -168,7 +223,7 @@
 RC_LOCAL=$ROOTFS/etc/rc.local
 cat > $RC_LOCAL <<EOF
 #!/bin/sh -e
-su -c "/opt/run.sh" stack
+su -c "$DEST/run.sh" stack
 EOF
 
 # Configure cgroup directory
@@ -179,3 +234,20 @@
 
 # Start our container
 lxc-start -d -n $CONTAINER
+
+# Done creating the container, let's tail the log
+echo
+echo "============================================================="
+echo "                          -- YAY! --"
+echo "============================================================="
+echo
+echo "We're done creating the container, about to start tailing the"
+echo "stack.sh log. It will take a second or two to start."
+echo
+echo "Just CTRL-C at any time to stop tailing."
+
+while [ ! -e "$ROOTFS/$DEST/run.sh.log" ]; do
+  sleep 1
+done
+
+tail -F $ROOTFS/$DEST/run.sh.log
diff --git a/build_nfs.sh b/build_nfs.sh
index 59a3609..fa3e3ef 100755
--- a/build_nfs.sh
+++ b/build_nfs.sh
@@ -1,5 +1,8 @@
 #!/bin/bash
 
+# Source params
+source ./stackrc
+
 # TODO: make dest not hardcoded
 
 NAME=$1
@@ -15,13 +18,15 @@
     chroot proto apt-get update
     chroot proto apt-get install -y `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server)"`
     chroot proto pip install `cat files/pips/*`
-    git clone https://github.com/cloudbuilders/nova.git proto/opt/nova
-    git clone https://github.com/cloudbuilders/openstackx.git proto/opt/openstackx
-    git clone https://github.com/cloudbuilders/noVNC.git proto/opt/noVNC
-    git clone https://github.com/cloudbuilders/openstack-dashboard.git proto/opt/dash
-    git clone https://github.com/cloudbuilders/python-novaclient.git proto/opt/python-novaclient
-    git clone https://github.com/cloudbuilders/keystone.git proto/opt/keystone
-    git clone https://github.com/cloudbuilders/glance.git proto/opt/glance
+    git_clone $NOVA_REPO proto/opt/nova $NOVA_BRANCH
+    git_clone $GLANCE_REPO proto/opt/glance $GLANCE_BRANCH
+    git_clone $KEYSTONE_REPO proto/opt/keystone $KEYSTONE_BRANCH
+    git_clone $NOVNC_REPO proto/opt/novnc $NOVNC_BRANCH
+    git_clone $DASH_REPO proto/opt/dash $DASH_BRANCH $DASH_TAG
+    git_clone $NIXON_REPO proto/opt/nixon $NIXON_BRANCH
+    git_clone $NOVACLIENT_REPO proto/opt/python-novaclient $NOVACLIENT_BRANCH
+    git_clone $OPENSTACKX_REPO proto/opt/openstackx $OPENSTACKX_BRANCH
+    git_clone $MUNIN_REPO proto/opt/openstack-munin $MUNIN_BRANCH
     chroot proto mkdir -p /opt/files
     wget -c http://images.ansolabs.com/tty.tgz -O proto/opt/files/tty.tgz
 fi
diff --git a/build_pxe_ramdisk.sh b/build_pxe_ramdisk.sh
new file mode 100755
index 0000000..648fc3b
--- /dev/null
+++ b/build_pxe_ramdisk.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+
+if [ ! "$#" -eq "1" ]; then
+    echo "$0 builds a gziped natty openstack install"
+    echo "usage: $0 dest"
+    exit 1
+fi
+
+# Source params
+source ./stackrc
+
+# clean install of natty
+if [ ! -d natty-base ]; then
+    debootstrap natty natty-base
+    # copy kernel modules...  
+    # NOTE(ja): is there a better way to do this?
+    cp -pr /lib/modules/`uname -r` natty-base/lib/modules
+    cp files/sources.list natty-base/etc/apt/sources.list
+    chroot natty-base apt-get update
+fi
+
+# prime natty with as many apt/pips as we can
+if [ ! -d primed ]; then
+    rsync -azH natty-base/ primed/
+    chroot primed apt-get install -y `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server)"`
+    chroot primed pip install `cat files/pips/*`
+
+    # Create a stack user that is a member of the libvirtd group so that stack 
+    # is able to interact with libvirt.
+    chroot primed groupadd libvirtd
+    chroot primed useradd stack -s /bin/bash -d /opt -G libvirtd
+
+    # a simple password - pass
+    echo stack:pass | chroot primed chpasswd
+
+    # and has sudo ability (in the future this should be limited to only what 
+    # stack requires)
+    echo "stack ALL=(ALL) NOPASSWD: ALL" >> primed/etc/sudoers
+fi
+
+# clone git repositories onto the system
+# ======================================
+
+if [ ! -d cloned ]; then
+    rsync -azH primed/ cloned/
+fi
+
+# git clone only if directory doesn't exist already.  Since ``DEST`` might not
+# be owned by the installation user, we create the directory and change the
+# ownership to the proper user.
+function git_clone {
+
+    # clone new copy or fetch latest changes
+    CHECKOUT=cloned$2
+    if [ ! -d $CHECKOUT ]; then
+        mkdir -p $CHECKOUT
+        git clone $1 $CHECKOUT
+    else
+        pushd $CHECKOUT
+        git fetch
+        popd
+    fi
+
+    # FIXME(ja): checkout specified version (should works for branches and tags)
+
+    pushd $CHECKOUT
+    # checkout the proper branch/tag
+    git checkout $3
+    # force our local version to be the same as the remote version
+    git reset --hard origin/$3
+    popd
+
+    # give ownership to the stack user
+    chroot cloned/ chown -R stack $2
+}
+
+git_clone $NOVA_REPO /opt/stack/nova $NOVA_BRANCH
+git_clone $GLANCE_REPO /opt/stack/glance $GLANCE_BRANCH
+git_clone $KEYSTONE_REPO /opt/stack/keystone $KEYSTONE_BRANCH
+git_clone $NOVNC_REPO /opt/stack/novnc $NOVNC_BRANCH
+git_clone $DASH_REPO /opt/stack/dash $DASH_BRANCH
+git_clone $NIXON_REPO /opt/stack/nixon $NIXON_BRANCH
+git_clone $NOVACLIENT_REPO /opt/stack/python-novaclient $NOVACLIENT_BRANCH
+git_clone $OPENSTACKX_REPO /opt/stack/openstackx $OPENSTACKX_BRANCH
+git_clone $MUNIN_REPO /opt/stack/openstack-munin $MUNIN_BRANCH
+
+# build a new image
+BASE=build.$$
+IMG=$BASE.img
+MNT=$BASE/
+
+# (quickly) create a 2GB blank filesystem
+dd bs=1 count=1 seek=$((2*1024*1024*1024)) if=/dev/zero of=$IMG
+# force it to be initialized as ext2
+mkfs.ext2 -F $IMG
+
+# mount blank image loopback and load it
+mkdir -p $MNT
+mount -o loop $IMG $MNT
+rsync -azH cloned/ $MNT
+
+# umount and cleanup
+umount $MNT
+rmdir $MNT
+
+# gzip into final location
+gzip -1 $IMG -c > $1
+
diff --git a/exercise.sh b/exercise.sh
index b7c42d7..7f7be49 100755
--- a/exercise.sh
+++ b/exercise.sh
@@ -25,7 +25,7 @@
 # ip address, ...)   With the addition of Keystone we have standardized on the
 # term **tenant** as the entity that owns the resources.  **novaclient** still
 # uses the old deprecated terms project_id.
-export NOVA_PROJECT_ID=${TENANT:-demo}
+export NOVA_PROJECT_ID=${TENANT:-2}
 
 # In addition to the owning entity (tenant), nova stores the entity performing
 # the action as the **user**.
@@ -48,6 +48,9 @@
 # needs to match the config of your catalog returned by Keystone.
 export NOVA_VERSION=1.1
 
+# FIXME - why does this need to be specified?
+export NOVA_REGION_NAME=RegionOne
+
 
 # Launching a server
 # ==================
diff --git a/files/000-default.template b/files/000-default.template
index 64251f0..4e4b5c4 100644
--- a/files/000-default.template
+++ b/files/000-default.template
@@ -1,6 +1,8 @@
 <VirtualHost *:80>
     WSGIScriptAlias / %DASH_DIR%/openstack-dashboard/dashboard/wsgi/django.wsgi
-    WSGIDaemonProcess dashboard user=www-data group=www-data processes=3 threads=10
+    WSGIDaemonProcess dashboard user=%USER% group=%USER% processes=3 threads=10
+    SetEnv APACHE_RUN_USER %USER%
+    SetEnv APACHE_RUN_GROUP %USER%
     WSGIProcessGroup dashboard
 
     DocumentRoot %DASH_DIR%/.blackhole/
diff --git a/files/apts/novnc b/files/apts/novnc
new file mode 100644
index 0000000..c8722b9
--- /dev/null
+++ b/files/apts/novnc
@@ -0,0 +1 @@
+python-numpy
diff --git a/files/keystone.conf b/files/keystone.conf
index 85a64a8..cd785a7 100644
--- a/files/keystone.conf
+++ b/files/keystone.conf
@@ -12,7 +12,7 @@
 
 # Log to this file. Make sure you do not set the same log
 # file for both the API and registry servers!
-log_file = /opt/keystone/keystone.log
+log_file = %DEST%/keystone/keystone.log
 
 # List of backends to be configured
 backends = keystone.backends.sqlalchemy
diff --git a/files/keystone_data.sh b/files/keystone_data.sh
index c5dd09b..1635b9d 100755
--- a/files/keystone_data.sh
+++ b/files/keystone_data.sh
@@ -22,7 +22,7 @@
 
 # Services
 $BIN_DIR/keystone-manage $* service add nova_compat nova_compat nova_compat
-$BIN_DIR/keystone-manage $* service add nova nova nova
+$BIN_DIR/keystone-manage $* service add compute compute compute
 $BIN_DIR/keystone-manage $* service add glance glance glance
 $BIN_DIR/keystone-manage $* service add identity identity identity
 
diff --git a/lxc_network_hostonlyplusnat.sh b/lxc_network_hostonlyplusnat.sh
new file mode 100755
index 0000000..4e29ed7
--- /dev/null
+++ b/lxc_network_hostonlyplusnat.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+# Print some usage info
+function usage {
+  echo "Usage: $0 [OPTION] [host_ip]"
+  echo "Set up temporary networking for LXC"
+  echo ""
+  echo "  -n, --dry-run            Just print the commands that would execute."
+  echo "  -h, --help               Print this usage message."
+  echo ""
+  exit
+}
+
+# Allow passing the ip address on the command line.
+function process_option {
+  case "$1" in
+    -h|--help) usage;;
+    -n|--dry-run) dry_run=1;;
+    *) host_ip="$1"
+  esac
+}
+
+# Set up some defaults
+host_ip=
+dry_run=0
+bridge=br0
+DRIER=
+
+# Process the args
+for arg in "$@"; do
+  process_option $arg
+done
+
+if [ $dry_run ]; then
+  DRIER=echo
+fi
+
+if [ "$UID" -ne "0" ]; then
+  echo "This script must be run with root privileges."
+  exit 1
+fi
+
+# Check for bridge-utils.
+BRCTL=`which brctl`
+if [ ! -x "$BRCTL" ]; then
+  echo "This script requires you to install bridge-utils."
+  echo "Try: sudo apt-get install bridge-utils."
+  exit 1
+fi
+
+# Scare off the nubs.
+echo "====================================================="
+echo
+echo "WARNING"
+echo
+echo "This script will modify your current network setup,"
+echo "this can be a scary thing and it is recommended that"
+echo "you have something equivalent to physical access to"
+echo "this machine before continuing in case your network"
+echo "gets all funky."
+echo
+echo "If you don't want to continue, hit CTRL-C now."
+
+if [ -z "$host_ip" ];
+then
+  echo "Otherwise, please type in your host's ip address and"
+  echo "hit enter."
+  echo
+  echo "====================================================="
+  read host_ip
+else
+  echo "Otherwise hit enter."
+  echo
+  echo "====================================================="
+  read accept
+fi
+
+
+# Add a bridge interface, this will choke if there is already
+# a bridge named $bridge
+$DRIER $BRCTL addbr $bridge
+$DRIER ip addr add 192.168.1.1/24 dev $bridge
+if [ $dry_run ]; then
+  echo "echo 1 > /proc/sys/net/ipv4/ip_forward"
+else
+  echo 1 > /proc/sys/net/ipv4/ip_forward
+fi
+$DRIER ifconfig $bridge up
+
+# Set up the NAT for the instances
+$DRIER iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source $host_ip
+$DRIER iptables -I FORWARD -s 192.168.1.0/24 -j ACCEPT
+
diff --git a/stack.sh b/stack.sh
index a3bcacd..4daa95d 100755
--- a/stack.sh
+++ b/stack.sh
@@ -13,6 +13,9 @@
 # Sanity Check
 # ============
 
+# Start our timer
+START_TIME=`python -c "import time; print time.time()"`
+
 # Warn users who aren't on natty, but allow them to override check and attempt
 # installation with ``FORCE=yes ./stack``
 if ! grep -q natty /etc/lsb-release; then
@@ -37,6 +40,15 @@
     exit 1
 fi
 
+# you need to run this as a regular user with sudo priviledges
+if [[ $EUID -eq 0 ]]; then
+   echo "This script cannot be run as root." 1>&2
+   echo "You should run this script as the user you wish openstack to run as" 1>&2
+   echo "The user will need to be a sudoer (without password)" 1>&2
+   exit 1
+fi
+
+
 # Settings
 # ========
 
@@ -48,6 +60,11 @@
 #
 # You can also pass options on a single line ``MYSQL_PASS=simple ./stack.sh``
 #
+# Additionally, you can put any local variables into a ``localrc`` file, like::
+#
+#     MYSQL_PASS=anothersecret
+#     MYSQL_USER=hellaroot
+#
 # We try to have sensible defaults, so you should be able to run ``./stack.sh``
 # in most cases.
 
@@ -59,8 +76,13 @@
 # an error.  It is also useful for following allowing as the install occurs.
 set -o xtrace
 
+# Import variables
+source ./stackrc
+
 # Destination path for installation ``DEST``
-DEST=${DEST:-/opt}
+DEST=${DEST:-/opt/stack}
+sudo mkdir -p $DEST
+sudo chown `whoami` $DEST
 
 # Set the destination directories for openstack projects
 NOVA_DIR=$DEST/nova
@@ -69,7 +91,7 @@
 GLANCE_DIR=$DEST/glance
 KEYSTONE_DIR=$DEST/keystone
 NOVACLIENT_DIR=$DEST/python-novaclient
-API_DIR=$DEST/openstackx
+OPENSTACKX_DIR=$DEST/openstackx
 NOVNC_DIR=$DEST/noVNC
 MUNIN_DIR=$DEST/openstack-munin
 
@@ -83,17 +105,19 @@
 
 # Nova network configuration
 PUBLIC_INTERFACE=${PUBLIC_INTERFACE:-eth0}
-VLAN_INTERFACE=${PUBLIC_INTERFACE:-$PUBLIC_INTERFACE}
-FLOATING_RANGE=${FLOATING_RANGE:-10.6.0.0/27}
+VLAN_INTERFACE=${VLAN_INTERFACE:-$PUBLIC_INTERFACE}
+FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.1/28}
 FIXED_RANGE=${FIXED_RANGE:-10.0.0.0/24}
-NET_MAN=${NET_MAN:-VlanManager}
+FIXED_NETWORK_SIZE=${FIXED_NETWORK_SIZE:-256}
+NET_MAN=${NET_MAN:-FlatDHCPManager}
 EC2_DMZ_HOST=${EC2_DMZ_HOST:-$HOST_IP}
 FLAT_NETWORK_BRIDGE=${FLAT_NETWORK_BRIDGE:-br100}
+SCHEDULER=${SCHEDULER:-nova.scheduler.simple.SimpleScheduler}
 
 # If you are using FlatDHCP on multiple hosts, set the ``FLAT_INTERFACE``
 # variable but make sure that the interface doesn't already have an
 # ip or you risk breaking things.
-# FLAT_INTERFACE=eth0
+FLAT_INTERFACE=${FLAT_INTERFACE:-eth0}
 
 # Nova hypervisor configuration.  We default to **kvm** but will drop back to
 # **qemu** if we are unable to load the kvm module.
@@ -139,34 +163,31 @@
         sudo mkdir $2
         sudo chown `whoami` $2
         git clone $1 $2
+        cd $2
+        # This checkout syntax works for both branches and tags
+        git checkout $3
     fi
 }
 
 # compute service
-# FIXME - need to factor out these repositories
-# git_clone https://github.com/cloudbuilders/nova.git $NOVA_DIR
-if [ ! -d $NOVA_DIR ]; then
-    bzr clone lp:~hudson-openstack/nova/milestone-proposed/ $NOVA_DIR
-fi
+git_clone $NOVA_REPO $NOVA_DIR $NOVA_BRANCH
 # image catalog service
-git_clone https://github.com/cloudbuilders/glance.git $GLANCE_DIR
+git_clone $GLANCE_REPO $GLANCE_DIR $GLANCE_BRANCH
 # unified auth system (manages accounts/tokens)
-git_clone https://github.com/cloudbuilders/keystone.git $KEYSTONE_DIR
+git_clone $KEYSTONE_REPO $KEYSTONE_DIR $KEYSTONE_BRANCH
 # a websockets/html5 or flash powered VNC console for vm instances
-git_clone https://github.com/cloudbuilders/noVNC.git $NOVNC_DIR
+git_clone $NOVNC_REPO $NOVNC_DIR $NOVNC_BRANCH
 # django powered web control panel for openstack
-git_clone https://github.com/cloudbuilders/openstack-dashboard.git $DASH_DIR
-# FIXME - need to factor out logic like this
-cd $DASH_DIR && sudo git fetch && sudo git checkout origin/keystone_diablo
+git_clone $DASH_REPO $DASH_DIR $DASH_BRANCH $DASH_TAG
 # add nixon, will use this to show munin graphs in dashboard
-git_clone https://github.com/cloudbuilders/nixon.git $NIXON_DIR
+git_clone $NIXON_REPO $NIXON_DIR $NIXON_BRANCH
 # python client library to nova that dashboard (and others) use
-git_clone https://github.com/cloudbuilders/python-novaclient.git $NOVACLIENT_DIR
+git_clone $NOVACLIENT_REPO $NOVACLIENT_DIR $NOVACLIENT_BRANCH
 # openstackx is a collection of extensions to openstack.compute & nova
 # that is *deprecated*.  The code is being moved into python-novaclient & nova.
-git_clone https://github.com/cloudbuilders/openstackx.git $API_DIR
+git_clone $OPENSTACKX_REPO $OPENSTACKX_DIR $OPENSTACKX_BRANCH
 # openstack-munin is a collection of munin plugins for monitoring the stack
-git_clone https://github.com/cloudbuilders/openstack-munin.git $MUNIN_DIR
+git_clone $MUNIN_REPO $MUNIN_DIR $MUNIN_BRANCH
 
 # Initialization
 # ==============
@@ -178,7 +199,7 @@
 cd $NOVACLIENT_DIR; sudo python setup.py develop
 cd $KEYSTONE_DIR; sudo python setup.py develop
 cd $GLANCE_DIR; sudo python setup.py develop
-cd $API_DIR; sudo python setup.py develop
+cd $OPENSTACKX_DIR; sudo python setup.py develop
 cd $DASH_DIR/django-openstack; sudo python setup.py develop
 cd $DASH_DIR/openstack-dashboard; sudo python setup.py develop
 
@@ -237,12 +258,8 @@
 
     ## Configure apache's 000-default to run dashboard
     sudo cp $FILES/000-default.template /etc/apache2/sites-enabled/000-default
+    sudo sed -e "s,%USER%,$USER,g" -i /etc/apache2/sites-enabled/000-default
     sudo sed -e "s,%DASH_DIR%,$DASH_DIR,g" -i /etc/apache2/sites-enabled/000-default
-
-    # ``python setup.py develop`` left some files owned by root in ``DASH_DIR``
-    # and others are owned by the user you are using to run this script.
-    # We need to change the owner to apache for dashboard to run.
-    sudo chown -R www-data:www-data $DASH_DIR
 fi
 
 
@@ -346,6 +363,7 @@
 rm -f $NOVA_DIR/bin/nova.conf
 add_nova_flag "--verbose"
 add_nova_flag "--nodaemon"
+add_nova_flag "--scheduler_driver=$SCHEDULER"
 add_nova_flag "--dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf"
 add_nova_flag "--network_manager=nova.network.manager.$NET_MAN"
 add_nova_flag "--my_ip=$HOST_IP"
@@ -353,7 +371,7 @@
 add_nova_flag "--vlan_interface=$VLAN_INTERFACE"
 add_nova_flag "--sql_connection=$BASE_SQL_CONN/nova"
 add_nova_flag "--libvirt_type=$LIBVIRT_TYPE"
-add_nova_flag "--osapi_extensions_path=$API_DIR/extensions"
+add_nova_flag "--osapi_extensions_path=$OPENSTACKX_DIR/extensions"
 add_nova_flag "--vncproxy_url=http://$HOST_IP:6080"
 add_nova_flag "--vncproxy_wwwroot=$NOVNC_DIR/"
 add_nova_flag "--api_paste_config=$KEYSTONE_DIR/examples/paste/nova-api-paste.ini"
@@ -376,7 +394,7 @@
     $NOVA_DIR/bin/nova-manage db sync
 
     # create a small network
-    $NOVA_DIR/bin/nova-manage network create private $FIXED_RANGE 1 32
+    $NOVA_DIR/bin/nova-manage network create private $FIXED_RANGE 1 $FIXED_NETWORK_SIZE
 
     # create some floating ips
     $NOVA_DIR/bin/nova-manage floating create $FLOATING_RANGE
@@ -395,6 +413,7 @@
     KEYSTONE_CONF=$KEYSTONE_DIR/etc/keystone.conf
     cp $FILES/keystone.conf $KEYSTONE_CONF
     sudo sed -e "s,%SQL_CONN%,$BASE_SQL_CONN/keystone,g" -i $KEYSTONE_CONF
+    sudo sed -e "s,%DEST%,$DEST,g" -i $KEYSTONE_CONF
 
     KEYSTONE_DATA=$KEYSTONE_DIR/bin/keystone_data.sh
     cp $FILES/keystone_data.sh $KEYSTONE_DATA
@@ -460,8 +479,7 @@
 screen_it n-cpu "cd $NOVA_DIR && echo $NOVA_DIR/bin/nova-compute | newgrp libvirtd"
 screen_it n-net "cd $NOVA_DIR && $NOVA_DIR/bin/nova-network"
 screen_it n-sch "cd $NOVA_DIR && $NOVA_DIR/bin/nova-scheduler"
-# nova-vncproxy binds a privileged port, and so needs sudo
-screen_it n-vnc "cd $NOVA_DIR && sudo $NOVA_DIR/bin/nova-vncproxy"
+screen_it n-vnc "cd $NOVNC_DIR && ./utils/nova-wsproxy.py 6080 --web ."
 screen_it dash "cd $DASH_DIR && sudo /etc/init.d/apache2 restart; sudo tail -f /var/log/apache2/error.log"
 
 # Install Images
@@ -499,3 +517,11 @@
     echo "keystone is serving at http://$HOST_IP:5000/v2.0/"
     echo "examples on using novaclient command line is in exercise.sh"
 fi
+
+# Summary
+# =======
+
+# End our timer and give a timing summary
+END_TIME=`python -c "import time; print time.time()"`
+ELAPSED=`python -c "print $END_TIME - $START_TIME"`
+echo "stack.sh completed in $ELAPSED seconds."
diff --git a/stackrc b/stackrc
new file mode 100644
index 0000000..deb467b
--- /dev/null
+++ b/stackrc
@@ -0,0 +1,41 @@
+# compute service
+NOVA_REPO=https://github.com/cloudbuilders/nova.git
+NOVA_BRANCH=diablo
+
+# image catalog service
+GLANCE_REPO=https://github.com/cloudbuilders/glance.git
+GLANCE_BRANCH=diablo
+
+# unified auth system (manages accounts/tokens)
+KEYSTONE_REPO=https://github.com/cloudbuilders/keystone.git
+KEYSTONE_BRANCH=diablo
+
+# a websockets/html5 or flash powered VNC console for vm instances
+NOVNC_REPO=https://github.com/cloudbuilders/noVNC.git
+NOVNC_BRANCH=master
+
+# django powered web control panel for openstack
+DASH_REPO=https://github.com/cloudbuilders/openstack-dashboard.git
+DASH_BRANCH=master
+
+# add nixon, will use this to show munin graphs in dashboard
+NIXON_REPO=https://github.com/cloudbuilders/nixon.git
+NIXON_BRANCH=diablo
+
+# python client library to nova that dashboard (and others) use
+NOVACLIENT_REPO=https://github.com/cloudbuilders/python-novaclient.git
+NOVACLIENT_BRANCH=master
+
+# openstackx is a collection of extensions to openstack.compute & nova
+# that is *deprecated*.  The code is being moved into python-novaclient & nova.
+OPENSTACKX_REPO=https://github.com/cloudbuilders/openstackx.git
+OPENSTACKX_BRANCH=diablo
+
+# openstack-munin is a collection of munin plugins for monitoring the stack
+MUNIN_REPO=https://github.com/cloudbuilders/openstack-munin.git
+MUNIN_BRANCH=master
+
+# allow local overrides of env variables
+if [ -f ./localrc ]; then
+    source ./localrc
+fi
diff --git a/upload_image.sh b/upload_image.sh
index cf913b8..da73f16 100755
--- a/upload_image.sh
+++ b/upload_image.sh
@@ -12,6 +12,7 @@
 
 HOST=${HOST:-localhost}
 PORT=${PORT:-9292}
+DEST=${DEST:-/opt/stack}
 
 while getopts h:p: c; do
     case $c in
@@ -59,14 +60,14 @@
 
 GLANCE=`which glance`
 if [ -z "$GLANCE" ]; then
-    if [ -x "/opt/glance/bin/glance" ]; then
+    if [ -x "$DEST/glance/bin/glance" ]; then
         # Look for stack.sh's install
-        GLANCE="/opt/glance/bin/glance"
+        GLANCE="$DEST/glance/bin/glance"
     else
-        # Install Glance client in /opt
+        # Install Glance client in $DEST
         echo "Glance not found, must install client"
         OWD=`pwd`
-        cd /opt
+        cd $DEST
         sudo apt-get install python-pip python-eventlet python-routes python-greenlet python-argparse python-sqlalchemy python-wsgiref python-pastedeploy python-xattr
         sudo pip install kombu
         sudo git clone https://github.com/cloudbuilders/glance.git