Merge "Move nova volumes to lib/n-vol"
diff --git a/README.md b/README.md
index fd66e96..872b16b 100644
--- a/README.md
+++ b/README.md
@@ -57,6 +57,22 @@
 
 You can override environment variables used in `stack.sh` by creating file name `localrc`.  It is likely that you will need to do this to tweak your networking configuration should you need to access your cloud from a different host.
 
+# RPC Backend
+
+Multiple RPC backends are available. Currently, this
+includes RabbitMQ (default), Qpid, and ZeroMQ. Your backend of
+choice may be selected via the `localrc`.
+
+Note that selecting more than one RPC backend will result in a failure.
+
+Example (ZeroMQ):
+
+    ENABLED_SERVICES="$ENABLED_SERVICES,-rabbit,-qpid,zeromq"
+
+Example (Qpid):
+
+    ENABLED_SERVICES="$ENABLED_SERVICES,-rabbit,-zeromq,qpid"
+
 # Swift
 
 Swift is not installed by default, you can enable easily by adding this to your `localrc`:
diff --git a/exercises/aggregates.sh b/exercises/aggregates.sh
index 8a4f9c1..adc3393 100755
--- a/exercises/aggregates.sh
+++ b/exercises/aggregates.sh
@@ -125,16 +125,16 @@
 if [ "$VIRT_DRIVER" == "xenserver" ]; then
     echo "TODO(johngarbutt) add tests for add/remove host from pool aggregate"
 fi
-HOST=`nova host-list | grep compute | get_field 1`
+FIRST_HOST=`nova host-list | grep compute | get_field 1 | head -1`
 # Make sure can add two aggregates to same host
-nova aggregate-add-host $AGGREGATE_ID $HOST
-nova aggregate-add-host $AGGREGATE2_ID $HOST
-if nova aggregate-add-host $AGGREGATE2_ID $HOST; then
+nova aggregate-add-host $AGGREGATE_ID $FIRST_HOST
+nova aggregate-add-host $AGGREGATE2_ID $FIRST_HOST
+if nova aggregate-add-host $AGGREGATE2_ID $FIRST_HOST; then
     echo "ERROR could add duplicate host to single aggregate"
     exit -1
 fi
-nova aggregate-remove-host $AGGREGATE2_ID $HOST
-nova aggregate-remove-host $AGGREGATE_ID $HOST
+nova aggregate-remove-host $AGGREGATE2_ID $FIRST_HOST
+nova aggregate-remove-host $AGGREGATE_ID $FIRST_HOST
 
 # Test aggregate-delete
 # =====================
diff --git a/exercises/boot_from_volume.sh b/exercises/boot_from_volume.sh
index 7fe81ba..c967e39 100755
--- a/exercises/boot_from_volume.sh
+++ b/exercises/boot_from_volume.sh
@@ -49,6 +49,10 @@
 # Default user
 DEFAULT_INSTANCE_USER=${DEFAULT_INSTANCE_USER:-cirros}
 
+# Security group name
+SECGROUP=${SECGROUP:-boot_secgroup}
+
+
 # Launching servers
 # =================
 
@@ -72,7 +76,6 @@
 fi
 
 # Configure Security Groups
-SECGROUP=${SECGROUP:-test_secgroup}
 nova secgroup-delete $SECGROUP || true
 nova secgroup-create $SECGROUP "$SECGROUP description"
 nova secgroup-add-rule $SECGROUP icmp -1 -1 0.0.0.0/0
@@ -246,8 +249,8 @@
     die "Failure deleting instance $INSTANCE_NAME"
 
 # Wait for termination
-if ! timeout $ACTIVE_TIMEOUT sh -c "while nova show $INSTANCE_NAME; do sleep 1; done"; then
-    echo "server didn't terminate!"
+if ! timeout $TERMINATE_TIMEOUT sh -c "while nova list | grep -q $VM_UUID; do sleep 1; done"; then
+    echo "Server $NAME not deleted"
     exit 1
 fi
 
@@ -256,8 +259,7 @@
     die "Failure deleting floating IP $FLOATING_IP"
 
 # Delete a secgroup
-nova secgroup-delete $SECGROUP || \
-    die "Failure deleting security group $SECGROUP"
+nova secgroup-delete $SECGROUP || die "Failure deleting security group $SECGROUP"
 
 set +o xtrace
 echo "*********************************************************************"
diff --git a/exercises/euca.sh b/exercises/euca.sh
index 9f7aed1..fb052dd 100755
--- a/exercises/euca.sh
+++ b/exercises/euca.sh
@@ -43,6 +43,9 @@
 # Boot this image, use first AMI-format image if unset
 DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ami}
 
+# Security group name
+SECGROUP=${SECGROUP:-euca_secgroup}
+
 
 # Launching a server
 # ==================
@@ -50,9 +53,6 @@
 # Find a machine image to boot
 IMAGE=`euca-describe-images | grep machine | grep ${DEFAULT_IMAGE_NAME} | cut -f2 | head -n1`
 
-# Define secgroup
-SECGROUP=euca_secgroup
-
 # Add a secgroup
 if ! euca-describe-groups | grep -q $SECGROUP; then
     euca-add-group -d "$SECGROUP description" $SECGROUP
@@ -119,14 +119,13 @@
     die "Failure terminating instance $INSTANCE"
 
 # Assure it has terminated within a reasonable time
-if ! timeout $TERMINATE_TIMEOUT sh -c "while euca-describe-instances $INSTANCE | grep -q running; do sleep 1; done"; then
+if ! timeout $TERMINATE_TIMEOUT sh -c "while euca-describe-instances $INSTANCE | grep -q $INSTANCE; do sleep 1; done"; then
     echo "server didn't terminate within $TERMINATE_TIMEOUT seconds"
     exit 1
 fi
 
 # Delete group
-euca-delete-group $SECGROUP || \
-    die "Failure deleting security group $SECGROUP"
+euca-delete-group $SECGROUP || die "Failure deleting security group $SECGROUP"
 
 set +o xtrace
 echo "*********************************************************************"
diff --git a/exercises/floating_ips.sh b/exercises/floating_ips.sh
index 02259c0..77f020e 100755
--- a/exercises/floating_ips.sh
+++ b/exercises/floating_ips.sh
@@ -200,12 +200,12 @@
 # Delete second floating IP
 nova floating-ip-delete $TEST_FLOATING_IP || die "Failure deleting floating IP $TEST_FLOATING_IP"
 
-# shutdown the server
+# Shutdown the server
 nova delete $VM_UUID || die "Failure deleting instance $NAME"
 
-# make sure the VM shuts down within a reasonable time
-if ! timeout $TERMINATE_TIMEOUT sh -c "while nova show $VM_UUID | grep status | grep -q ACTIVE; do sleep 1; done"; then
-    echo "server didn't shut down!"
+# Wait for termination
+if ! timeout $TERMINATE_TIMEOUT sh -c "while nova list | grep -q $VM_UUID; do sleep 1; done"; then
+    echo "Server $NAME not deleted"
     exit 1
 fi
 
diff --git a/exercises/volumes.sh b/exercises/volumes.sh
index 0f25355..5db10d3 100755
--- a/exercises/volumes.sh
+++ b/exercises/volumes.sh
@@ -43,6 +43,9 @@
 # Boot this image, use first AMi image if unset
 DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ami}
 
+# Security group name
+SECGROUP=${SECGROUP:-vol_secgroup}
+
 
 # Launching a server
 # ==================
@@ -62,6 +65,25 @@
 # Grab the id of the image to launch
 IMAGE=$(glance image-list | egrep " $DEFAULT_IMAGE_NAME " | get_field 1)
 
+# Security Groups
+# ---------------
+
+# List of secgroups:
+nova secgroup-list
+
+# Create a secgroup
+if ! nova secgroup-list | grep -q $SECGROUP; then
+    nova secgroup-create $SECGROUP "$SECGROUP description"
+    if ! timeout $ASSOCIATE_TIMEOUT sh -c "while ! nova secgroup-list | grep -q $SECGROUP; do sleep 1; done"; then
+        echo "Security group not created"
+        exit 1
+    fi
+fi
+
+# Configure Security Group Rules
+nova secgroup-add-rule $SECGROUP icmp -1 -1 0.0.0.0/0
+nova secgroup-add-rule $SECGROUP tcp 22 22 0.0.0.0/0
+
 # determinine instance type
 # -------------------------
 
@@ -171,8 +193,17 @@
     exit 1
 fi
 
-# shutdown the server
-nova delete $NAME || die "Failure deleting instance $NAME"
+# Shutdown the server
+nova delete $VM_UUID || die "Failure deleting instance $NAME"
+
+# Wait for termination
+if ! timeout $TERMINATE_TIMEOUT sh -c "while nova list | grep -q $VM_UUID; do sleep 1; done"; then
+    echo "Server $NAME not deleted"
+    exit 1
+fi
+
+# Delete a secgroup
+nova secgroup-delete $SECGROUP || die "Failure deleting security group $SECGROUP"
 
 set +o xtrace
 echo "*********************************************************************"
diff --git a/functions b/functions
index af154b0..fa7c805 100644
--- a/functions
+++ b/functions
@@ -585,6 +585,52 @@
 }
 
 
+# Helper to launch a service in a named screen
+# screen_it service "command-line"
+function screen_it {
+    NL=`echo -ne '\015'`
+    SCREEN_NAME=${SCREEN_NAME:-stack}
+    if is_service_enabled $1; then
+        # Append the service to the screen rc file
+        screen_rc "$1" "$2"
+
+        screen -S $SCREEN_NAME -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
+        # bash isn't running by the time we send the command, nothing happens
+        sleep 1.5
+
+        if [[ -n ${SCREEN_LOGDIR} ]]; then
+            screen -S $SCREEN_NAME -p $1 -X logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log
+            screen -S $SCREEN_NAME -p $1 -X log on
+            ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
+        fi
+        screen -S $SCREEN_NAME -p $1 -X stuff "$2$NL"
+    fi
+}
+
+
+# Screen rc file builder
+# screen_rc service "command-line"
+function screen_rc {
+    SCREEN_NAME=${SCREEN_NAME:-stack}
+    SCREENRC=$TOP_DIR/$SCREEN_NAME-screenrc
+    if [[ ! -e $SCREENRC ]]; then
+        # Name the screen session
+        echo "sessionname $SCREEN_NAME" > $SCREENRC
+        # Set a reasonable statusbar
+        echo "hardstatus alwayslastline '$SCREEN_HARDSTATUS'" >> $SCREENRC
+        echo "screen -t shell bash" >> $SCREENRC
+    fi
+    # If this service doesn't already exist in the screenrc file
+    if ! grep $1 $SCREENRC 2>&1 > /dev/null; then
+        NL=`echo -ne '\015'`
+        echo "screen -t $1 bash" >> $SCREENRC
+        echo "stuff \"$2$NL\"" >> $SCREENRC
+    fi
+}
+
+
 # ``pip install`` the dependencies of the package before ``setup.py develop``
 # so pip and not distutils processes the dependency chain
 # Uses globals ``TRACK_DEPENDES``, ``*_proxy`
diff --git a/lib/cinder b/lib/cinder
index 1bad5c0..5f0b255 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -115,6 +115,8 @@
 
     if is_service_enabled qpid ; then
         iniset $CINDER_CONF DEFAULT rpc_backend cinder.openstack.common.rpc.impl_qpid
+    elif is_service_enabled zeromq; then
+        iniset $CINDER_CONF DEFAULT rpc_backend nova.openstack.common.rpc.impl_zmq
     elif [ -n "$RABBIT_HOST" ] &&  [ -n "$RABBIT_PASSWORD" ]; then
         iniset $CINDER_CONF DEFAULT rabbit_host $RABBIT_HOST
         iniset $CINDER_CONF DEFAULT rabbit_password $RABBIT_PASSWORD
diff --git a/lib/template b/lib/template
index d70f218..78b848d 100644
--- a/lib/template
+++ b/lib/template
@@ -65,7 +65,7 @@
 }
 
 # start_XXXX() - Start running processes, including screen
-function start_XXXX()
+function start_XXXX() {
     # screen_it XXXX "cd $XXXX_DIR && $XXXX_DIR/bin/XXXX-bin"
     :
 }
diff --git a/samples/local.sh b/samples/local.sh
index 2c54b10..eb9bc24 100755
--- a/samples/local.sh
+++ b/samples/local.sh
@@ -7,9 +7,10 @@
 # work properly.
 
 # This is a collection of some of the things we have found to be useful to run
-# after stack.sh to tweak the OpenStack configuration that DevStack produces.
+# after ``stack.sh`` to tweak the OpenStack configuration that DevStack produces.
 # These should be considered as samples and are unsupported DevStack code.
 
+
 # Keep track of the devstack directory
 TOP_DIR=$(cd $(dirname "$0") && pwd)
 
@@ -34,7 +35,7 @@
 
 # Add first keypair found in localhost:$HOME/.ssh
 for i in $HOME/.ssh/id_rsa.pub $HOME/.ssh/id_dsa.pub; do
-    if [[ -f $i ]]; then
+    if [[ -r $i ]]; then
         nova keypair-add --pub_key=$i `hostname`
         break
     fi
@@ -55,8 +56,9 @@
 if [[ -z $(nova flavor-list | grep $MI_NAME) ]]; then
     nova flavor-create $MI_NAME 6 128 0 1
 fi
+
+
 # Other Uses
 # ----------
 
-# Add tcp/22 to default security group
-
+# Add tcp/22 and icmp to default security group
diff --git a/samples/localrc b/samples/localrc
index 4fb093d..bcaa788 100644
--- a/samples/localrc
+++ b/samples/localrc
@@ -1,9 +1,10 @@
 # Sample ``localrc`` for user-configurable variables in ``stack.sh``
 
-# NOTE: Copy this file to the root ``devstack`` directory for it to work properly.
+# NOTE: Copy this file to the root ``devstack`` directory for it to
+# work properly.
 
-# ``localrc`` is a user-maintained setings file that is sourced at the end of
-# ``stackrc``. This gives it the ability to override any variables set in ``stackrc``.
+# ``localrc`` is a user-maintained setings file that is sourced from ``stackrc``.
+# This gives it the ability to override any variables set in ``stackrc``.
 # Also, most of the settings in ``stack.sh`` are written to only be set if no
 # value has already been set; this lets ``localrc`` effectively override the
 # default values.
@@ -21,40 +22,51 @@
 # there are a few minimal variables set:
 
 # If the ``*_PASSWORD`` variables are not set here you will be prompted to enter
-# values for them by ``stack.sh``.
+# values for them by ``stack.sh`` and they will be added to ``localrc``.
 ADMIN_PASSWORD=nomoresecrete
 MYSQL_PASSWORD=stackdb
 RABBIT_PASSWORD=stackqueue
 SERVICE_PASSWORD=$ADMIN_PASSWORD
 
-# HOST_IP should be set manually for best results.  It is auto-detected during the
-# first run of ``stack.sh`` but often is indeterminate on later runs due to the IP
-# being moved from an Ethernet interface to a bridge on the host. Setting it here
-# also makes it available for ``openrc`` to include when setting ``OS_AUTH_URL``.
+# ``HOST_IP`` should be set manually for best results if the NIC configuration
+# of the host is unusual, i.e. ``eth1`` has the default route but ``eth0`` is the
+# public interface.  It is auto-detected in ``stack.sh`` but often is indeterminate
+# on later runs due to the IP moving from an Ethernet interface to a bridge on
+# the host. Setting it here also makes it available for ``openrc`` to include
+# when setting ``OS_AUTH_URL``.
 # ``HOST_IP`` is not set by default.
-HOST_IP=w.x.y.z
+#HOST_IP=w.x.y.z
 
 
-# Set DevStack Install Directory
-# ------------------------------
+# Logging
+# -------
 
-# The DevStack install directory is set by the ``DEST`` variable. By setting it
-# early in ``localrc`` you can reference it in later variables. The default value
-# is ``/opt/stack``. It can be useful to set it even though it is not changed from
-# the default value.
-DEST=/opt/stack
+# By default ``stack.sh`` output only goes to the terminal where it runs.  It can
+# be configured to additionally log to a file by setting ``LOGFILE`` to the full
+# path of the destination log file.  A timestamp will be appended to the given name.
+LOGFILE=$DEST/logs/stack.sh.log
+
+# Old log files are automatically removed after 7 days to keep things neat.  Change
+# the number of days by setting ``LOGDAYS``.
+LOGDAYS=2
+
+# Nova logs will be colorized if ``SYSLOG`` is not set; turn this off by setting
+# ``LOG_COLOR`` false.
+#LOG_COLOR=False
 
 
 # Using milestone-proposed branches
 # ---------------------------------
 
 # Uncomment these to grab the milestone-proposed branches from the repos:
+#CINDER_BRANCH=milestone-proposed
 #GLANCE_BRANCH=milestone-proposed
 #HORIZON_BRANCH=milestone-proposed
 #KEYSTONE_BRANCH=milestone-proposed
 #KEYSTONECLIENT_BRANCH=milestone-proposed
 #NOVA_BRANCH=milestone-proposed
 #NOVACLIENT_BRANCH=milestone-proposed
+#QUANTUM_BRANCH=milestone-proposed
 #SWIFT_BRANCH=milestone-proposed
 
 
diff --git a/stack.sh b/stack.sh
index ac675e8..40daeff 100755
--- a/stack.sh
+++ b/stack.sh
@@ -134,14 +134,32 @@
     exit 1
 fi
 
+SCREEN_NAME=${SCREEN_NAME:-stack}
 # Check to see if we are already running DevStack
-if type -p screen >/dev/null && screen -ls | egrep -q "[0-9].stack"; then
+if type -p screen >/dev/null && screen -ls | egrep -q "[0-9].$SCREEN_NAME"; then
     echo "You are already running a stack.sh session."
     echo "To rejoin this session type 'screen -x stack'."
     echo "To destroy this session, type './unstack.sh'."
     exit 1
 fi
 
+# Make sure we only have one rpc backend enabled.
+rpc_backend_cnt=0
+for svc in qpid zeromq rabbit; do
+    is_service_enabled $svc &&
+        ((rpc_backend_cnt++))
+done
+if [ "$rpc_backend_cnt" -gt 1 ]; then
+    echo "ERROR: only one rpc backend may be enabled,"
+    echo "       set only one of 'rabbit', 'qpid', 'zeromq'"
+    echo "       via ENABLED_SERVICES."
+elif [ "$rpc_backend_cnt" == 0 ]; then
+    echo "ERROR: at least one rpc backend must be enabled,"
+    echo "       set one of 'rabbit', 'qpid', 'zeromq'"
+    echo "       via ENABLED_SERVICES."
+fi
+unset rpc_backend_cnt
+
 # Make sure we only have one volume service enabled.
 if is_service_enabled cinder && is_service_enabled n-vol; then
     echo "ERROR: n-vol and cinder must not be enabled at the same time"
@@ -656,6 +674,12 @@
     else
         install_package qpidd
     fi
+elif is_service_enabled zeromq; then
+    if [[ "$os_PACKAGE" = "rpm" ]]; then
+        install_package zeromq python-zmq
+    else
+        install_package libzmq1 python-zmq
+    fi
 fi
 
 if is_service_enabled mysql; then
@@ -894,8 +918,8 @@
 fi
 
 
-# Rabbit or Qpid
-# --------------
+# Finalize queue instllation
+# --------------------------
 
 if is_service_enabled rabbit; then
     # Start rabbitmq-server
@@ -954,51 +978,11 @@
     SCREEN_HARDSTATUS='%{= .} %-Lw%{= .}%> %n%f %t*%{= .}%+Lw%< %-=%{g}(%{d}%H/%l%{g})'
 fi
 
-# Our screenrc file builder
-function screen_rc {
-    SCREENRC=$TOP_DIR/stack-screenrc
-    if [[ ! -e $SCREENRC ]]; then
-        # Name the screen session
-        echo "sessionname stack" > $SCREENRC
-        # Set a reasonable statusbar
-        echo "hardstatus alwayslastline '$SCREEN_HARDSTATUS'" >> $SCREENRC
-        echo "screen -t stack bash" >> $SCREENRC
-    fi
-    # If this service doesn't already exist in the screenrc file
-    if ! grep $1 $SCREENRC 2>&1 > /dev/null; then
-        NL=`echo -ne '\015'`
-        echo "screen -t $1 bash" >> $SCREENRC
-        echo "stuff \"$2$NL\"" >> $SCREENRC
-    fi
-}
-
-# Our screen helper to launch a service in a hidden named screen
-function screen_it {
-    NL=`echo -ne '\015'`
-    if is_service_enabled $1; then
-        # Append the service to the screen rc file
-        screen_rc "$1" "$2"
-
-        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
-        # bash isn't running by the time we send the command, nothing happens
-        sleep 1.5
-
-        if [[ -n ${SCREEN_LOGDIR} ]]; then
-            screen -S stack -p $1 -X logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log
-            screen -S stack -p $1 -X log on
-            ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
-        fi
-        screen -S stack -p $1 -X stuff "$2$NL"
-    fi
-}
-
 # Create a new named screen to run processes in
-screen -d -m -S stack -t stack -s /bin/bash
+screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash
 sleep 1
 # Set a reasonable statusbar
-screen -r stack -X hardstatus alwayslastline "$SCREEN_HARDSTATUS"
+screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS"
 
 
 # Horizon
@@ -1275,6 +1259,8 @@
     iniset $Q_CONF_FILE DEFAULT control_exchange quantum
     if is_service_enabled qpid ; then
         iniset $Q_CONF_FILE DEFAULT rpc_backend quantum.openstack.common.rpc.impl_qpid
+    elif is_service_enabled zeromq; then
+        iniset $Q_CONF_FILE DEFAULT rpc_backend quantum.openstack.common.rpc.impl_zmq
     elif [ -n "$RABBIT_HOST" ] &&  [ -n "$RABBIT_PASSWORD" ]; then
         iniset $Q_CONF_FILE DEFAULT rabbit_host $RABBIT_HOST
         iniset $Q_CONF_FILE DEFAULT rabbit_password $RABBIT_PASSWORD
@@ -1849,7 +1835,9 @@
 add_nova_opt "api_paste_config=$NOVA_CONF_DIR/api-paste.ini"
 add_nova_opt "image_service=nova.image.glance.GlanceImageService"
 add_nova_opt "ec2_dmz_host=$EC2_DMZ_HOST"
-if is_service_enabled qpid ; then
+if is_service_enabled zeromq; then
+    add_nova_opt "rpc_backend=nova.openstack.common.rpc.impl_zmq"
+elif is_service_enabled qpid; then
     add_nova_opt "rpc_backend=nova.rpc.impl_qpid"
 elif [ -n "$RABBIT_HOST" ] &&  [ -n "$RABBIT_PASSWORD" ]; then
     add_nova_opt "rabbit_host=$RABBIT_HOST"
@@ -2093,6 +2081,8 @@
     fi
 fi
 
+screen_it zeromq "cd $NOVA_DIR && $NOVA_DIR/bin/nova-rpc-zmq-receiver"
+
 # Launch the nova-api and wait for it to answer before continuing
 if is_service_enabled n-api; then
     add_nova_opt "enabled_apis=$NOVA_ENABLED_APIS"