Merge "Add ovs-ofctl to the sudo command list"
diff --git a/AUTHORS b/AUTHORS
index dc12105..b147827 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,6 +7,7 @@
 Dean Troyer <dtroyer@gmail.com>
 Devin Carlen <devin.carlen@gmail.com>
 Eddie Hebert <edhebert@gmail.com>
+Eoghan Glynn <eglynn@redhat.com>
 Jake Dahn <admin@jakedahn.com>
 James E. Blair <james.blair@rackspace.com>
 Jason Cannavale <jason.cannavale@rackspace.com>
diff --git a/files/apts/glance b/files/apts/glance
index 1e87d58..71230c4 100644
--- a/files/apts/glance
+++ b/files/apts/glance
@@ -6,3 +6,4 @@
 python-wsgiref
 python-pastedeploy
 python-xattr
+python-iso8601
diff --git a/files/apts/nova b/files/apts/nova
index bc0c23b..f2059ba 100644
--- a/files/apts/nova
+++ b/files/apts/nova
@@ -41,3 +41,4 @@
 python-boto
 python-kombu
 python-feedparser
+python-iso8601
diff --git a/files/keystone.conf b/files/keystone.conf
index 45044f7..b26e70d 100644
--- a/files/keystone.conf
+++ b/files/keystone.conf
@@ -89,4 +89,4 @@
 [composite:admin]
 use = egg:Paste#urlmap
 /v2.0 = admin_api
-/ = admin_version_service
+/ = admin_version_api
diff --git a/stack.sh b/stack.sh
index f2c47cf..6da985d 100755
--- a/stack.sh
+++ b/stack.sh
@@ -200,14 +200,13 @@
 # cases unless you are working on multi-zone mode.
 SCHEDULER=${SCHEDULER:-nova.scheduler.simple.SimpleScheduler}
 
+HOST_IP_IFACE=${HOST_IP_IFACE:-eth0}
 # Use the eth0 IP unless an explicit is set by ``HOST_IP`` environment variable
-if [ ! -n "$HOST_IP" ]; then
-    HOST_IP=`LC_ALL=C /sbin/ifconfig eth0 | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'`
+if [ -z "$HOST_IP" -o "$HOST_IP" == "dhcp" ]; then
+    HOST_IP=`LC_ALL=C /sbin/ifconfig ${HOST_IP_IFACE} | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'`
     if [ "$HOST_IP" = "" ]; then
         echo "Could not determine host ip address."
-        echo "If this is not your first run of stack.sh, it is "
-        echo "possible that nova moved your eth0 ip address to the FLAT_NETWORK_BRIDGE."
-        echo "Please specify your HOST_IP in your localrc."
+        echo "Either localrc specified dhcp on ${HOST_IP_IFACE} or defaulted to eth0"
         exit 1
     fi
 fi
@@ -264,6 +263,27 @@
     set -o xtrace
 }
 
+# This function will check if the service(s) specified in argument is
+# enabled by the user in ENABLED_SERVICES.
+#
+# If there is multiple services specified as argument it will act as a
+# boolean OR or if any of the services specified on the command line
+# return true.
+#
+# There is a special cases for some 'catch-all' services :
+#      nova would catch if any service enabled start by n-
+#    glance would catch if any service enabled start by g-
+#   quantum would catch if any service enabled start by q-
+function is_service_enabled() {
+    services=$@
+    for service in ${services}; do
+        [[ ,${ENABLED_SERVICES}, =~ ,${service}, ]] && return 0
+        [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && return 0
+        [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && return 0
+        [[ ${service} == "quantum" && ${ENABLED_SERVICES} =~ "q-" ]] && return 0
+    done
+    return 1
+}
 
 # Nova Network Configuration
 # --------------------------
@@ -384,7 +404,7 @@
 SWIFT_PARTITION_POWER_SIZE=${SWIFT_PARTITION_POWER_SIZE:-9}
 
 # We only ask for Swift Hash if we have enabled swift service.
-if [[ "$ENABLED_SERVICES" =~ "swift" ]]; then
+if is_service_enabled swift; then
     # SWIFT_HASH is a random unique string for a swift cluster that
     # can never change.
     read_password SWIFT_HASH "ENTER A RANDOM SWIFT HASH."
@@ -537,44 +557,40 @@
 git_clone $NOVACLIENT_REPO $NOVACLIENT_DIR $NOVACLIENT_BRANCH
 
 # glance, swift middleware and nova api needs keystone middleware
-if [[ "$ENABLED_SERVICES" =~ "key" ||
-      "$ENABLED_SERVICES" =~ "g-api" ||
-      "$ENABLED_SERVICES" =~ "n-api" ||
-      "$ENABLED_SERVICES" =~ "swift" ]]; then
+if is_service_enabled key g-api n-api swift; then
     # unified auth system (manages accounts/tokens)
     git_clone $KEYSTONE_REPO $KEYSTONE_DIR $KEYSTONE_BRANCH
 fi
-if [[ "$ENABLED_SERVICES" =~ "swift" ]]; then
+if is_service_enabled swift; then
     # storage service
     git_clone $SWIFT_REPO $SWIFT_DIR $SWIFT_BRANCH
     # swift + keystone middleware
     git_clone $SWIFT_KEYSTONE_REPO $SWIFT_KEYSTONE_DIR $SWIFT_KEYSTONE_BRANCH
 fi
-if [[ "$ENABLED_SERVICES" =~ "g-api" ||
-      "$ENABLED_SERVICES" =~ "n-api" ]]; then
+if is_service_enabled g-api n-api; then
     # image catalog service
     git_clone $GLANCE_REPO $GLANCE_DIR $GLANCE_BRANCH
 fi
-if [[ "$ENABLED_SERVICES" =~ "n-novnc" ]]; then
+if is_service_enabled n-novnc; then
     # a websockets/html5 or flash powered VNC console for vm instances
     git_clone $NOVNC_REPO $NOVNC_DIR $NOVNC_BRANCH
 fi
-if [[ "$ENABLED_SERVICES" =~ "horizon" ]]; then
+if is_service_enabled horizon; then
     # django powered web control panel for openstack
     git_clone $HORIZON_REPO $HORIZON_DIR $HORIZON_BRANCH $HORIZON_TAG
 fi
-if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then
+if is_service_enabled q-svc; then
     # quantum
     git_clone $QUANTUM_REPO $QUANTUM_DIR $QUANTUM_BRANCH
     git_clone $QUANTUM_CLIENT_REPO $QUANTUM_CLIENT_DIR $QUANTUM_CLIENT_BRANCH
 fi
 
-if [[ "$ENABLED_SERVICES" =~ "m-svc" ]]; then
+if is_service_enabled m-svc; then
     # melange
     git_clone $MELANGE_REPO $MELANGE_DIR $MELANGE_BRANCH
 fi
 
-if [[ "$ENABLED_SERVICES" =~ "melange" ]]; then
+if is_service_enabled melange; then
     git_clone $MELANGECLIENT_REPO $MELANGECLIENT_DIR $MELANGECLIENT_BRANCH
 fi
 
@@ -586,32 +602,28 @@
 # allowing ``import nova`` or ``import glance.client``
 cd $KEYSTONECLIENT_DIR; sudo python setup.py develop
 cd $NOVACLIENT_DIR; sudo python setup.py develop
-if [[ "$ENABLED_SERVICES" =~ "key" ||
-      "$ENABLED_SERVICES" =~ "g-api" ||
-      "$ENABLED_SERVICES" =~ "n-api" ||
-      "$ENABLED_SERVICES" =~ "swift" ]]; then
+if is_service_enabled key g-api n-api swift; then
     cd $KEYSTONE_DIR; sudo python setup.py develop
 fi
-if [[ "$ENABLED_SERVICES" =~ "swift" ]]; then
+if is_service_enabled swift; then
     cd $SWIFT_DIR; sudo python setup.py develop
     cd $SWIFT_KEYSTONE_DIR; sudo python setup.py develop
 fi
-if [[ "$ENABLED_SERVICES" =~ "g-api" ||
-      "$ENABLED_SERVICES" =~ "n-api" ]]; then
+if is_service_enabled g-api n-api; then
     cd $GLANCE_DIR; sudo python setup.py develop
 fi
 cd $NOVA_DIR; sudo python setup.py develop
-if [[ "$ENABLED_SERVICES" =~ "horizon" ]]; then
+if is_service_enabled horizon; then
     cd $HORIZON_DIR/horizon; sudo python setup.py develop
     cd $HORIZON_DIR/openstack-dashboard; sudo python setup.py develop
 fi
-if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then
+if is_service_enabled q-svc; then
     cd $QUANTUM_DIR; sudo python setup.py develop
 fi
-if [[ "$ENABLED_SERVICES" =~ "m-svc" ]]; then
+if is_service_enabled m-svc; then
     cd $MELANGE_DIR; sudo python setup.py develop
 fi
-if [[ "$ENABLED_SERVICES" =~ "melange" ]]; then
+if is_service_enabled melange; then
     cd $MELANGECLIENT_DIR; sudo python setup.py develop
 fi
 
@@ -640,7 +652,7 @@
 # Rabbit
 # ---------
 
-if [[ "$ENABLED_SERVICES" =~ "rabbit" ]]; then
+if is_service_enabled rabbit; then
     # Install and start rabbitmq-server
     # the temp file is necessary due to LP: #878600
     tfile=$(mktemp)
@@ -654,7 +666,7 @@
 # Mysql
 # ---------
 
-if [[ "$ENABLED_SERVICES" =~ "mysql" ]]; then
+if is_service_enabled mysql; then
 
     # Seed configuration with mysql password so that apt-get install doesn't
     # prompt us for a password upon install.
@@ -693,7 +705,7 @@
 
 # Setup the django horizon application to serve via apache/wsgi
 
-if [[ "$ENABLED_SERVICES" =~ "horizon" ]]; then
+if is_service_enabled horizon; then
 
     # Install apache2, which is NOPRIME'd
     apt_get install apache2 libapache2-mod-wsgi
@@ -710,7 +722,7 @@
     cp $FILES/horizon_settings.py $local_settings
 
     # Enable quantum in dashboard, if requested
-    if [[ "$ENABLED_SERVICES" =~ "quantum" ]]; then
+    if is_service_enabled quantum; then
         sudo sed -e "s,QUANTUM_ENABLED = False,QUANTUM_ENABLED = True,g" -i $local_settings
     fi
 
@@ -736,7 +748,7 @@
 # Glance
 # ------
 
-if [[ "$ENABLED_SERVICES" =~ "g-reg" ]]; then
+if is_service_enabled g-reg; then
     GLANCE_IMAGE_DIR=$DEST/glance/images
     # Delete existing images
     rm -rf $GLANCE_IMAGE_DIR
@@ -772,9 +784,6 @@
         GLANCE_REGISTRY_PASTE_INI=$GLANCE_DIR/etc/glance-registry-paste.ini
         cp $FILES/glance-registry-paste.ini $GLANCE_REGISTRY_PASTE_INI
         glance_config $GLANCE_REGISTRY_PASTE_INI
-        # During the transition for Glance to the split config files
-        # we cat them together to handle both pre- and post-merge
-        cat $GLANCE_REGISTRY_PASTE_INI >>$GLANCE_REGISTRY_CONF
     fi
 
     GLANCE_API_CONF=$GLANCE_DIR/etc/glance-api.conf
@@ -785,9 +794,6 @@
         GLANCE_API_PASTE_INI=$GLANCE_DIR/etc/glance-api-paste.ini
         cp $FILES/glance-api-paste.ini $GLANCE_API_PASTE_INI
         glance_config $GLANCE_API_PASTE_INI
-        # During the transition for Glance to the split config files
-        # we cat them together to handle both pre- and post-merge
-        cat $GLANCE_API_PASTE_INI >>$GLANCE_API_CONF
     fi
 fi
 
@@ -801,7 +807,7 @@
 fi
 sudo chown `whoami` $NOVA_CONF
 
-if [[ "$ENABLED_SERVICES" =~ "n-api" ]]; then
+if is_service_enabled n-api; then
     # We are going to use a sample http middleware configuration based on the
     # one from the keystone project to launch nova.  This paste config adds
     # the configuration required for nova to validate keystone tokens.
@@ -834,7 +840,7 @@
     sudo iptables -S -v -t nat | sed "s/-c [0-9]* [0-9]* //g" | grep "nova" |  grep "\-N" | sed "s/-N/-X/g" | awk '{print "sudo iptables -t nat",$0}' | bash
 }
 
-if [[ "$ENABLED_SERVICES" =~ "n-cpu" ]]; then
+if is_service_enabled n-cpu; then
 
     # Virtualization Configuration
     # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -915,7 +921,7 @@
     sudo rm -rf $NOVA_DIR/instances/*
 fi
 
-if [[ "$ENABLED_SERVICES" =~ "n-net" ]]; then
+if is_service_enabled n-net; then
     # Delete traces of nova networks from prior runs
     sudo killall dnsmasq || true
     clean_iptables
@@ -924,7 +930,7 @@
 fi
 
 # Storage Service
-if [[ "$ENABLED_SERVICES" =~ "swift" ]]; then
+if is_service_enabled swift; then
     # We first do a bit of setup by creating the directories and
     # changing the permissions so we can run it as our user.
 
@@ -983,7 +989,7 @@
    # By default Swift will be installed with the tempauth middleware
    # which has some default username and password if you have
    # configured keystone it will checkout the directory.
-   if [[ "$ENABLED_SERVICES" =~ "key" ]]; then
+   if is_service_enabled key; then
        swift_auth_server=keystone
 
        # We install the memcache server as this is will be used by the
@@ -1060,7 +1066,7 @@
 # Volume Service
 # --------------
 
-if [[ "$ENABLED_SERVICES" =~ "n-vol" ]]; then
+if is_service_enabled n-vol; then
     #
     # Configure a default volume group called 'nova-volumes' for the nova-volume
     # service if it does not yet exist.  If you don't wish to use a file backed
@@ -1111,21 +1117,21 @@
 add_nova_flag "--scheduler_driver=$SCHEDULER"
 add_nova_flag "--dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf"
 add_nova_flag "--fixed_range=$FIXED_RANGE"
-if [[ "$ENABLED_SERVICES" =~ "n-obj" ]]; then
+if is_service_enabled n-obj; then
     add_nova_flag "--s3_host=$SERVICE_HOST"
 fi
-if [[ "$ENABLED_SERVICES" =~ "quantum" ]]; then
+if is_service_enabled quantum; then
     add_nova_flag "--network_manager=nova.network.quantum.manager.QuantumManager"
     add_nova_flag "--quantum_connection_host=$Q_HOST"
     add_nova_flag "--quantum_connection_port=$Q_PORT"
 
-    if [[ "$ENABLED_SERVICES" =~ "melange" ]]; then
+    if is_service_enabled melange; then
         add_nova_flag "--quantum_ipam_lib=nova.network.quantum.melange_ipam_lib"
         add_nova_flag "--use_melange_mac_generation"
         add_nova_flag "--melange_host=$M_HOST"
         add_nova_flag "--melange_port=$M_PORT"
     fi
-    if [[ "$ENABLED_SERVICES" =~ "q-svc" && "$Q_PLUGIN" = "openvswitch" ]]; then
+    if is_service_enabled q-svc && [[ "$Q_PLUGIN" = "openvswitch" ]]; then
         add_nova_flag "--libvirt_vif_type=ethernet"
         add_nova_flag "--libvirt_vif_driver=nova.virt.libvirt.vif.LibvirtOpenVswitchDriver"
         add_nova_flag "--linuxnet_interface_driver=nova.network.linux_net.LinuxOVSInterfaceDriver"
@@ -1134,7 +1140,7 @@
 else
     add_nova_flag "--network_manager=nova.network.manager.$NET_MAN"
 fi
-if [[ "$ENABLED_SERVICES" =~ "n-vol" ]]; then
+if is_service_enabled n-vol; then
     add_nova_flag "--volume_group=$VOLUME_GROUP"
     add_nova_flag "--volume_name_template=${VOLUME_NAME_PREFIX}%08x"
     # oneiric no longer supports ietadm
@@ -1149,7 +1155,7 @@
 add_nova_flag "--instance_name_template=${INSTANCE_NAME_PREFIX}%08x"
 # All nova-compute workers need to know the vnc configuration options
 # These settings don't hurt anything if n-xvnc and n-novnc are disabled
-if [[ "$ENABLED_SERVICES" =~ "n-cpu" ]]; then
+if is_service_enabled n-cpu; then
     NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:6080/vnc_auto.html"}
     add_nova_flag "--novncproxy_base_url=$NOVNCPROXY_URL"
     XVPVNCPROXY_URL=${XVPVNCPROXY_URL:-"http://$SERVICE_HOST:6081/console"}
@@ -1221,7 +1227,7 @@
 # All nova components talk to a central database.  We will need to do this step
 # only once for an entire cluster.
 
-if [[ "$ENABLED_SERVICES" =~ "mysql" ]]; then
+if is_service_enabled mysql; then
     # (re)create nova database
     mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS nova;'
     mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE nova;'
@@ -1241,7 +1247,7 @@
 # our screen helper to launch a service in a hidden named screen
 function screen_it {
     NL=`echo -ne '\015'`
-    if [[ "$ENABLED_SERVICES" =~ "$1" ]]; then
+    if is_service_enabled $1; then
         screen -S stack -X screen -t $1
         # sleep to allow bash to be ready to be send the command - we are
         # creating a new window in screen and then sends characters, so if
@@ -1258,12 +1264,12 @@
 screen -r stack -X hardstatus alwayslastline "%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%< %= %H"
 
 # launch the glance registry service
-if [[ "$ENABLED_SERVICES" =~ "g-reg" ]]; then
+if is_service_enabled g-reg; then
     screen_it g-reg "cd $GLANCE_DIR; bin/glance-registry --config-file=etc/glance-registry.conf"
 fi
 
 # launch the glance api and wait for it to answer before continuing
-if [[ "$ENABLED_SERVICES" =~ "g-api" ]]; then
+if is_service_enabled g-api; then
     screen_it g-api "cd $GLANCE_DIR; bin/glance-api --config-file=etc/glance-api.conf"
     echo "Waiting for g-api ($GLANCE_HOSTPORT) to start..."
     if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://$GLANCE_HOSTPORT; do sleep 1; done"; then
@@ -1272,7 +1278,7 @@
     fi
 fi
 
-if [[ "$ENABLED_SERVICES" =~ "key" ]]; then
+if is_service_enabled key; then
     # (re)create keystone database
     mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS keystone;'
     mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE keystone;'
@@ -1301,7 +1307,7 @@
 fi
 
 # launch the keystone and wait for it to answer before continuing
-if [[ "$ENABLED_SERVICES" =~ "key" ]]; then
+if is_service_enabled key; then
     screen_it key "cd $KEYSTONE_DIR && $KEYSTONE_DIR/bin/keystone-all --config-file $KEYSTONE_CONF $KEYSTONE_LOG_CONFIG -d --debug"
     echo "Waiting for keystone to start..."
     if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/; do sleep 1; done"; then
@@ -1321,7 +1327,7 @@
 
 
 # launch the nova-api and wait for it to answer before continuing
-if [[ "$ENABLED_SERVICES" =~ "n-api" ]]; then
+if is_service_enabled n-api; then
     screen_it n-api "cd $NOVA_DIR && $NOVA_DIR/bin/nova-api"
     echo "Waiting for nova-api to start..."
     if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://127.0.0.1:8774; do sleep 1; done"; then
@@ -1331,13 +1337,13 @@
 fi
 
 # Quantum service
-if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then
+if is_service_enabled q-svc; then
     if [[ "$Q_PLUGIN" = "openvswitch" ]]; then
         # Install deps
         # FIXME add to files/apts/quantum, but don't install if not needed!
         apt_get install openvswitch-switch openvswitch-datapath-dkms
         # Create database for the plugin/agent
-        if [[ "$ENABLED_SERVICES" =~ "mysql" ]]; then
+        if is_service_enabled mysql; then
             mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS ovs_quantum;'
             mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE IF NOT EXISTS ovs_quantum;'
         else
@@ -1352,7 +1358,7 @@
 fi
 
 # Quantum agent (for compute nodes)
-if [[ "$ENABLED_SERVICES" =~ "q-agt" ]]; then
+if is_service_enabled q-agt; then
     if [[ "$Q_PLUGIN" = "openvswitch" ]]; then
         # Set up integration bridge
         OVS_BRIDGE=${OVS_BRIDGE:-br-int}
@@ -1369,8 +1375,8 @@
 fi
 
 # Melange service
-if [[ "$ENABLED_SERVICES" =~ "m-svc" ]]; then
-    if [[ "$ENABLED_SERVICES" =~ "mysql" ]]; then
+if is_service_enabled m-svc; then
+    if is_service_enabled mysql; then
         mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS melange;'
         mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE melange;'
     else
@@ -1392,11 +1398,11 @@
 
 # If we're using Quantum (i.e. q-svc is enabled), network creation has to
 # happen after we've started the Quantum service.
-if [[ "$ENABLED_SERVICES" =~ "mysql" ]]; then
+if is_service_enabled mysql; then
     # create a small network
     $NOVA_DIR/bin/nova-manage network create private $FIXED_RANGE 1 $FIXED_NETWORK_SIZE
 
-    if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then
+    if is_service_enabled q-svc; then
         echo "Not creating floating IPs (not supported by QuantumManager)"
     else
         # create some floating ips
@@ -1419,16 +1425,16 @@
 screen_it n-vol "cd $NOVA_DIR && $NOVA_DIR/bin/nova-volume"
 screen_it n-net "cd $NOVA_DIR && $NOVA_DIR/bin/nova-network"
 screen_it n-sch "cd $NOVA_DIR && $NOVA_DIR/bin/nova-scheduler"
-if [[ "$ENABLED_SERVICES" =~ "n-novnc" ]]; then
+if is_service_enabled n-novnc; then
     screen_it n-novnc "cd $NOVNC_DIR && ./utils/nova-novncproxy --flagfile $NOVA_DIR/bin/nova.conf --web ."
 fi
-if [[ "$ENABLED_SERVICES" =~ "n-xvnc" ]]; then
+if is_service_enabled n-xvnc; then
     screen_it n-xvnc "cd $NOVA_DIR && ./bin/nova-xvpvncproxy --flagfile $NOVA_DIR/bin/nova.conf"
 fi
-if [[ "$ENABLED_SERVICES" =~ "n-cauth" ]]; then
+if is_service_enabled n-cauth; then
     screen_it n-cauth "cd $NOVA_DIR && ./bin/nova-consoleauth"
 fi
-if [[ "$ENABLED_SERVICES" =~ "horizon" ]]; then
+if is_service_enabled horizon; then
     screen_it horizon "cd $HORIZON_DIR && sudo tail -f /var/log/apache2/error.log"
 fi
 
@@ -1448,7 +1454,7 @@
 #  * **natty**: http://uec-images.ubuntu.com/natty/current/natty-server-cloudimg-amd64.tar.gz
 #  * **oneiric**: http://uec-images.ubuntu.com/oneiric/current/oneiric-server-cloudimg-amd64.tar.gz
 
-if [[ "$ENABLED_SERVICES" =~ "g-reg" ]]; then
+if is_service_enabled g-reg; then
     # Create a directory for the downloaded image tarballs.
     mkdir -p $FILES/images
 
@@ -1539,12 +1545,12 @@
 
 # If you installed the horizon on this server, then you should be able
 # to access the site using your browser.
-if [[ "$ENABLED_SERVICES" =~ "horizon" ]]; then
+if is_service_enabled horizon; then
     echo "horizon is now available at http://$SERVICE_HOST/"
 fi
 
 # If keystone is present, you can point nova cli to this server
-if [[ "$ENABLED_SERVICES" =~ "key" ]]; then
+if is_service_enabled key; then
     echo "keystone is serving at $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/"
     echo "examples on using novaclient command line is in exercise.sh"
     echo "the default users are: admin and demo"
diff --git a/stackrc b/stackrc
index 2274e62..a20426b 100644
--- a/stackrc
+++ b/stackrc
@@ -16,7 +16,7 @@
 
 # unified auth system (manages accounts/tokens)
 KEYSTONE_REPO=https://github.com/openstack/keystone.git
-KEYSTONE_BRANCH=redux
+KEYSTONE_BRANCH=master
 
 # a websockets/html5 or flash powered VNC console for vm instances
 NOVNC_REPO=https://github.com/cloudbuilders/noVNC.git
diff --git a/tools/xen/build_domU.sh b/tools/xen/build_domU.sh
index cd28f15..455ad26 100755
--- a/tools/xen/build_domU.sh
+++ b/tools/xen/build_domU.sh
@@ -31,57 +31,91 @@
     wget http://git-core.googlecode.com/files/git-1.7.7.tar.gz
     tar xfv git-1.7.7.tar.gz
     cd $GITDIR
-    ./configure
+    ./configure --with-curl --with-expat
     make install
     cd $TOP_DIR
 fi
 
 # Helper to create networks
+# Uses echo trickery to return network uuid
 function create_network() {
-    if ! xe network-list | grep bridge | grep -q $1; then
-        echo "Creating bridge $1"
-        xe network-create name-label=$1
+    br=$1
+    dev=$2
+    vlan=$3
+    netname=$4
+    if [ -z $br ]
+    then
+        pif=$(xe pif-list --minimal device=$dev VLAN=$vlan)
+        if [ -z $pif ]
+        then
+            net=$(xe network-create name-label=$netname)
+        else
+            net=$(xe network-list --minimal PIF-uuids=$pif)
+        fi
+        echo $net
+        return 0
+    fi
+    if [ ! $(xe network-list --minimal params=bridge | grep -w --only-matching $br) ]
+    then
+        echo "Specified bridge $br does not exist"
+        echo "If you wish to use defaults, please keep the bridge name empty"
+        exit 1
+    else
+        net=$(xe network-list --minimal bridge=$br)
+        echo $net
+    fi
+}
+
+function errorcheck() {
+    rc=$?
+    if [ $rc -ne 0 ]
+    then
+        exit $rc
     fi
 }
 
 # Create host, vm, mgmt, pub networks
-create_network xapi0
-create_network $VM_BR
-create_network $MGT_BR
-create_network $PUB_BR
-
-# Get the uuid for our physical (public) interface
-PIF=`xe pif-list --minimal device=eth0`
-
-# Create networks/bridges for vm and management
-VM_NET=`xe network-list --minimal bridge=$VM_BR`
-MGT_NET=`xe network-list --minimal bridge=$MGT_BR`
+VM_NET=$(create_network "$VM_BR" "$VM_DEV" "$VM_VLAN" "vmbr")
+errorcheck
+MGT_NET=$(create_network "$MGT_BR" "$MGT_DEV" "$MGT_VLAN" "mgtbr")
+errorcheck
+PUB_NET=$(create_network "$PUB_BR" "$PUB_DEV" "$PUB_VLAN" "pubbr")
+errorcheck
 
 # Helper to create vlans
 function create_vlan() {
-    pif=$1
+    dev=$1
     vlan=$2
     net=$3
-    if ! xe vlan-list | grep tag | grep -q $vlan; then
-        xe vlan-create pif-uuid=$pif vlan=$vlan network-uuid=$net
+    # VLAN -1 refers to no VLAN (physical network)
+    if [ $vlan -eq -1 ]
+    then
+        return
+    fi
+    if [ -z $(xe vlan-list --minimal tag=$vlan) ]
+    then
+        pif=$(xe pif-list --minimal network-uuid=$net)
+        # We created a brand new network this time
+        if [ -z $pif ]
+        then
+            pif=$(xe pif-list --minimal device=$dev VLAN=-1)
+            xe vlan-create pif-uuid=$pif vlan=$vlan network-uuid=$net
+        else
+            echo "VLAN does not exist but PIF attached to this network"
+            echo "How did we reach here?"
+            exit 1
+        fi
     fi
 }
 
 # Create vlans for vm and management
-create_vlan $PIF $VM_VLAN $VM_NET
-create_vlan $PIF $MGT_VLAN $MGT_NET
+create_vlan $PUB_DEV $PUB_VLAN $PUB_NET
+create_vlan $VM_DEV $VM_VLAN $VM_NET
+create_vlan $MGT_DEV $MGT_VLAN $MGT_NET
 
 # dom0 ip
 HOST_IP=${HOST_IP:-`ifconfig xenbr0 | grep "inet addr" | cut -d ":" -f2 | sed "s/ .*//"`}
 
-# Setup host-only nat rules
-HOST_NET=169.254.0.0/16
-if ! iptables -L -v -t nat | grep -q $HOST_NET; then
-    iptables -t nat -A POSTROUTING -s $HOST_NET -j SNAT --to-source $HOST_IP
-    iptables -I FORWARD 1 -s $HOST_NET -j ACCEPT
-    /etc/init.d/iptables save
-fi
-
 # Set up ip forwarding
 if ! grep -q "FORWARD_IPV4=YES" /etc/sysconfig/network; then
     # FIXME: This doesn't work on reboot!
@@ -107,7 +141,7 @@
 
 # Checkout nova
 if [ ! -d $TOP_DIR/nova ]; then
-    git clone $NOVA_REPO
+    env GIT_SSL_NO_VERIFY=true git clone $NOVA_REPO
     cd $TOP_DIR/nova
     git checkout $NOVA_BRANCH
 fi 
@@ -139,7 +173,16 @@
 fi
 
 # Start guest
-$TOP_DIR/scripts/install-os-vpx.sh -f $XVA -v $VM_BR -m $MGT_BR -p $PUB_BR
+if [ -z $VM_BR ]; then
+    VM_BR=$(xe network-list --minimal uuid=$VM_NET params=bridge)
+fi
+if [ -z $MGT_BR ]; then
+    MGT_BR=$(xe network-list --minimal uuid=$MGT_NET params=bridge)
+fi
+if [ -z $PUB_BR ]; then
+    PUB_BR=$(xe network-list --minimal uuid=$PUB_NET params=bridge)
+fi
+$TOP_DIR/scripts/install-os-vpx.sh -f $XVA -v $VM_BR -m $MGT_BR -p $PUB_BR -l $GUEST_NAME -w
 
 # If we have copied our ssh credentials, use ssh to monitor while the installation runs
 WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1}
diff --git a/tools/xen/build_domU_multi.sh b/tools/xen/build_domU_multi.sh
index 130bec5..0285f42 100755
--- a/tools/xen/build_domU_multi.sh
+++ b/tools/xen/build_domU_multi.sh
@@ -17,19 +17,19 @@
 COMMON_VARS="$STACKSH_PARAMS MYSQL_HOST=$HEAD_MGT_IP RABBIT_HOST=$HEAD_MGT_IP GLANCE_HOSTPORT=$HEAD_MGT_IP:9292 FLOATING_RANGE=$FLOATING_RANGE"
 
 # Helper to launch containers
-function build_domU {
-    GUEST_NAME=$1 PUB_IP=$2 MGT_IP=$3 DO_SHUTDOWN=$4 TERMINATE=$TERMINATE STACKSH_PARAMS="$COMMON_VARS $5" ./build_domU.sh
+function build_xva {
+    GUEST_NAME=$1 PUB_IP=$2 MGT_IP=$3 DO_SHUTDOWN=$4 TERMINATE=$TERMINATE STACKSH_PARAMS="$COMMON_VARS $5" ./build_xva.sh
 }
 
 # Launch the head node - headnode uses a non-ip domain name,
 # because rabbit won't launch with an ip addr hostname :(
-build_domU HEADNODE $HEAD_PUB_IP $HEAD_MGT_IP 1 "ENABLED_SERVICES=g-api,g-reg,key,n-api,n-sch,n-vnc,horizon,mysql,rabbit"
+build_xva HEADNODE $HEAD_PUB_IP $HEAD_MGT_IP 1 "ENABLED_SERVICES=g-api,g-reg,key,n-api,n-sch,n-vnc,horizon,mysql,rabbit"
 
 # Wait till the head node is up
-while ! curl -L http://$HEAD_PUB_IP | grep -q username; do
-    echo "Waiting for head node ($HEAD_PUB_IP) to start..."
-    sleep 5
-done
+#while ! curl -L http://$HEAD_PUB_IP | grep -q username; do
+#    echo "Waiting for head node ($HEAD_PUB_IP) to start..."
+#    sleep 5
+#done
 
 # Build the HA compute host
-build_domU $COMPUTE_PUB_IP $COMPUTE_PUB_IP $COMPUTE_MGT_IP 0 "ENABLED_SERVICES=n-cpu,n-net,n-api"
+build_xva COMPUTENODE $COMPUTE_PUB_IP $COMPUTE_MGT_IP 0 "ENABLED_SERVICES=n-cpu,n-net,n-api"
diff --git a/tools/xen/build_xva.sh b/tools/xen/build_xva.sh
index e4de2a1..4eb4b91 100755
--- a/tools/xen/build_xva.sh
+++ b/tools/xen/build_xva.sh
@@ -62,7 +62,7 @@
 mkdir -p $XVA_DIR
 
 # Path to xva
-XVA=$XVA_DIR/$GUEST_NAME.xva 
+XVA=$XVA_DIR/$GUEST_NAME.xva
 
 # Setup fake grub
 rm -rf $STAGING_DIR/boot/grub/
@@ -102,7 +102,9 @@
 
 # Run devstack on launch
 cat <<EOF >$STAGING_DIR/etc/rc.local
-GUEST_PASSWORD=$GUEST_PASSWORD STAGING_DIR=/ DO_TGZ=0 bash /opt/stack/devstack/tools/xen/prepare_guest.sh
+# network restart required for getting the right gateway
+/etc/init.d/networking restart
+GUEST_PASSWORD=$GUEST_PASSWORD STAGING_DIR=/ DO_TGZ=0 bash /opt/stack/devstack/tools/xen/prepare_guest.sh > /opt/stack/prepare_guest.log 2>&1
 su -c "/opt/stack/run.sh > /opt/stack/run.sh.log" stack
 exit 0
 EOF
@@ -122,12 +124,36 @@
 # Configure the network
 INTERFACES=$STAGING_DIR/etc/network/interfaces
 cp $TEMPLATES_DIR/interfaces.in  $INTERFACES
-sed -e "s,@ETH1_IP@,$VM_IP,g" -i $INTERFACES
-sed -e "s,@ETH1_NETMASK@,$VM_NETMASK,g" -i $INTERFACES
-sed -e "s,@ETH2_IP@,$MGT_IP,g" -i $INTERFACES
-sed -e "s,@ETH2_NETMASK@,$MGT_NETMASK,g" -i $INTERFACES
-sed -e "s,@ETH3_IP@,$PUB_IP,g" -i $INTERFACES
-sed -e "s,@ETH3_NETMASK@,$PUB_NETMASK,g" -i $INTERFACES
+if [ $VM_IP == "dhcp" ]; then
+    echo 'eth1 on dhcp'
+    sed -e "s,iface eth1 inet static,iface eth1 inet dhcp,g" -i $INTERFACES
+    sed -e '/@ETH1_/d' -i $INTERFACES
+else
+    sed -e "s,@ETH1_IP@,$VM_IP,g" -i $INTERFACES
+    sed -e "s,@ETH1_NETMASK@,$VM_NETMASK,g" -i $INTERFACES
+fi
+
+if [ $MGT_IP == "dhcp" ]; then
+    echo 'eth2 on dhcp'
+    sed -e "s,iface eth2 inet static,iface eth2 inet dhcp,g" -i $INTERFACES
+    sed -e '/@ETH2_/d' -i $INTERFACES
+else
+    sed -e "s,@ETH2_IP@,$MGT_IP,g" -i $INTERFACES
+    sed -e "s,@ETH2_NETMASK@,$MGT_NETMASK,g" -i $INTERFACES
+fi
+
+if [ $PUB_IP == "dhcp" ]; then
+    echo 'eth3 on dhcp'
+    sed -e "s,iface eth3 inet static,iface eth3 inet dhcp,g" -i $INTERFACES
+    sed -e '/@ETH3_/d' -i $INTERFACES
+else
+    sed -e "s,@ETH3_IP@,$PUB_IP,g" -i $INTERFACES
+    sed -e "s,@ETH3_NETMASK@,$PUB_NETMASK,g" -i $INTERFACES
+fi
+
+if [ -h $STAGING_DIR/sbin/dhclient3 ]; then
+    rm -f $STAGING_DIR/sbin/dhclient3
+fi
 
 # Gracefully cp only if source file/dir exists
 function cp_it {
@@ -151,7 +177,7 @@
 #!/bin/bash
 cd /opt/stack/devstack
 killall screen
-UPLOAD_LEGACY_TTY=yes HOST_IP=$PUB_IP VIRT_DRIVER=xenserver FORCE=yes MULTI_HOST=1 $STACKSH_PARAMS ./stack.sh
+UPLOAD_LEGACY_TTY=yes HOST_IP=$PUB_IP VIRT_DRIVER=xenserver FORCE=yes MULTI_HOST=1 HOST_IP_IFACE=$HOST_IP_IFACE $STACKSH_PARAMS ./stack.sh
 EOF
 chmod 755 $STAGING_DIR/opt/stack/run.sh
 
diff --git a/tools/xen/install_domU_multi.sh b/tools/xen/install_domU_multi.sh
new file mode 100755
index 0000000..91129c5
--- /dev/null
+++ b/tools/xen/install_domU_multi.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+# Echo commands
+set -o xtrace
+
+# Head node host, which runs glance, api, keystone
+HEAD_PUB_IP=${HEAD_PUB_IP:-192.168.1.57}
+HEAD_MGT_IP=${HEAD_MGT_IP:-172.16.100.57}
+
+COMPUTE_PUB_IP=${COMPUTE_PUB_IP:-192.168.1.58}
+COMPUTE_MGT_IP=${COMPUTE_MGT_IP:-172.16.100.58}
+
+# Networking params
+FLOATING_RANGE=${FLOATING_RANGE:-192.168.1.196/30}
+
+# Variables common amongst all hosts in the cluster
+COMMON_VARS="$STACKSH_PARAMS MYSQL_HOST=$HEAD_MGT_IP RABBIT_HOST=$HEAD_MGT_IP GLANCE_HOSTPORT=$HEAD_MGT_IP:9292 FLOATING_RANGE=$FLOATING_RANGE"
+
+# Helper to launch containers
+function install_domU {
+    GUEST_NAME=$1 PUB_IP=$2 MGT_IP=$3 DO_SHUTDOWN=$4 TERMINATE=$TERMINATE STACKSH_PARAMS="$COMMON_VARS $5" ./build_domU.sh
+}
+
+# Launch the head node - headnode uses a non-ip domain name,
+# because rabbit won't launch with an ip addr hostname :(
+install_domU HEADNODE $HEAD_PUB_IP $HEAD_MGT_IP 1 "ENABLED_SERVICES=g-api,g-reg,key,n-api,n-sch,n-vnc,horizon,mysql,rabbit"
+
+if [ $HEAD_PUB_IP == "dhcp" ]
+then
+    guestnet=$(xe vm-list --minimal name-label=HEADNODE params=networks)
+    HEAD_PUB_IP=$(echo $guestnet | grep -w -o --only-matching "3/ip: [0-9,.]*;" | cut -d ':' -f2 | cut -d ';' -f 1)
+fi
+# Wait till the head node is up
+while ! curl -L http://$HEAD_PUB_IP | grep -q username; do
+    echo "Waiting for head node ($HEAD_PUB_IP) to start..."
+    sleep 5
+done
+
+# Build the HA compute host
+install_domU COMPUTENODE $COMPUTE_PUB_IP $COMPUTE_MGT_IP 0 "ENABLED_SERVICES=n-cpu,n-net,n-api"
diff --git a/tools/xen/prepare_dom0.sh b/tools/xen/prepare_dom0.sh
index ce16ada..d28a07f 100755
--- a/tools/xen/prepare_dom0.sh
+++ b/tools/xen/prepare_dom0.sh
@@ -1,9 +1,9 @@
-#!/bin/sh
+#i!/bin/sh
 set -o xtrace
 set -o errexit
 
 # Install basics for vi and git
-yum -y  --enablerepo=base install gcc make vim-enhanced zlib-devel openssl-devel
+yum -y  --enablerepo=base install gcc make vim-enhanced zlib-devel openssl-devel curl-devel.i386
 
 # Simple but usable vimrc
 if [ ! -e /root/.vimrc ]; then
@@ -30,12 +30,7 @@
     wget http://git-core.googlecode.com/files/git-1.7.7.tar.gz
     tar xfv git-1.7.7.tar.gz
     cd $GITDIR
-    ./configure
+    ./configure --with-curl --with-expat
     make install
 fi
 
-# Clone devstack
-DEVSTACK=/root/devstack
-if [ ! -d $DEVSTACK ]; then
-    git clone git://github.com/cloudbuilders/devstack.git $DEVSTACK
-fi
diff --git a/tools/xen/prepare_guest.sh b/tools/xen/prepare_guest.sh
index 2f19b9d..77ce54a 100644
--- a/tools/xen/prepare_guest.sh
+++ b/tools/xen/prepare_guest.sh
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+set -x
+
 # Configurable nuggets
 GUEST_PASSWORD=${GUEST_PASSWORD:-secrete}
 STAGING_DIR=${STAGING_DIR:-stage}
diff --git a/tools/xen/scripts/install-os-vpx.sh b/tools/xen/scripts/install-os-vpx.sh
index 9aebb13..f0dc3c2 100755
--- a/tools/xen/scripts/install-os-vpx.sh
+++ b/tools/xen/scripts/install-os-vpx.sh
@@ -38,7 +38,7 @@
 cat << EOF
 
   Usage: $0 [-f FILE_PATH] [-d DISK_SIZE] [-v BRIDGE_NAME] [-m BRIDGE_NAME] [-p BRIDGE_NAME]
-            [-k PARAMS] [-r RAM] [-i|-c] [-w] [-b]
+            [-k PARAMS] [-r RAM] [-i|-c] [-w] [-b] [-l NAME_LABEL]
 
   Installs XenServer OpenStack VPX.
 
@@ -60,6 +60,7 @@
      -k params    Specifies kernel parameters.
      -r MiB       Specifies RAM used by the VPX, in MiB.
                   By default it will take the value from the XVA.
+     -l name      Specifies the name label for the VM.
 
   EXAMPLES:
 
@@ -87,7 +88,7 @@
 
 get_params()
 {
-  while getopts "hicwbf:d:v:m:p:k:r:" OPTION; 
+  while getopts "hicwbf:d:v:m:p:k:r:l:" OPTION; 
   do
     case $OPTION in
       h) usage
@@ -126,6 +127,9 @@
       v)
          BRIDGE_V=$OPTARG
          ;;
+     l)
+         NAME_LABEL=$OPTARG
+         ;;
       ?)
          usage
          exit
@@ -443,7 +447,7 @@
 
   renumber_system_disk "$vm_uuid"
 
-  nl=$(xe_min vm-list params=name-label uuid=$vm_uuid)
+  nl=${NAME_LABEL:-$(xe_min vm-list params=name-label uuid=$vm_uuid)}
   xe vm-param-set \
     "name-label=${nl/ import/}" \
     other-config:os-vpx=true \
diff --git a/tools/xen/templates/interfaces.in b/tools/xen/templates/interfaces.in
index 49c3d68..e315a8c 100644
--- a/tools/xen/templates/interfaces.in
+++ b/tools/xen/templates/interfaces.in
@@ -1,8 +1,15 @@
 auto lo
 iface lo inet loopback
 
-auto eth0
-iface eth0 inet dhcp
+# If eth3 is static, the order should not matter
+# and eth0 will have the default gateway. If not,
+# we probably want the default gateway to be
+# what is on the public interface. Hence changed
+# the order here.
+auto eth3
+iface eth3 inet static
+        address @ETH3_IP@
+        netmask @ETH3_NETMASK@
 
 auto eth1
 iface eth1 inet static
@@ -15,7 +22,5 @@
         address @ETH2_IP@
         netmask @ETH2_NETMASK@
 
-auto eth3
-iface eth3 inet static
-        address @ETH3_IP@
-        netmask @ETH3_NETMASK@
+auto eth0
+iface eth0 inet dhcp
diff --git a/tools/xen/xenrc b/tools/xen/xenrc
index 246ac16..73f9c02 100644
--- a/tools/xen/xenrc
+++ b/tools/xen/xenrc
@@ -9,24 +9,31 @@
 # VM Password
 GUEST_PASSWORD=${GUEST_PASSWORD:-secrete}
 
-# Our nova host's network info 
+# Host Interface, i.e. the public facing interface on the nova vm
+HOST_IP_IFACE=${HOST_IP_IFACE:-eth0}
+
+# Our nova host's network info
 VM_IP=${VM_IP:-10.255.255.255} # A host-only ip that let's the interface come up, otherwise unused
 MGT_IP=${MGT_IP:-172.16.100.55}
 PUB_IP=${PUB_IP:-192.168.1.55}
 
 # Public network
-PUB_BR=${PUB_BR:-xenbr0}
+PUB_BR=${PUB_BR:-"xenbr0"}
+PUB_DEV=${PUB_DEV:-eth0}
+PUB_VLAN=${PUB_VLAN:--1}
 PUB_NETMASK=${PUB_NETMASK:-255.255.255.0}
 
 # VM network params
 VM_NETMASK=${VM_NETMASK:-255.255.255.0}
-VM_BR=${VM_BR:-xapi1}
+VM_BR=${VM_BR:-""}
 VM_VLAN=${VM_VLAN:-100}
+VM_DEV=${VM_DEV:-eth0}
 
 # MGMT network params
 MGT_NETMASK=${MGT_NETMASK:-255.255.255.0}
-MGT_BR=${MGT_BR:-xapi2}
+MGT_BR=${MGT_BR:-""}
 MGT_VLAN=${MGT_VLAN:-101}
+MGT_DEV=${MGT_DEV:-eth0}
 
 # XVA Directory
 XVA_DIR=${XVA_DIR:-xvas}