Merge pull request #67 from dtroyer/7-stack-home

stack home dir
diff --git a/exercise.sh b/exercise.sh
index dc8163f..f35adef 100755
--- a/exercise.sh
+++ b/exercise.sh
@@ -19,6 +19,9 @@
 # Settings
 # ========
 
+# Use stackrc and localrc for settings
+source ./stackrc
+
 HOST=${HOST:-localhost}
 
 # Nova original used project_id as the *account* that owned resources (servers,
@@ -33,7 +36,7 @@
 export NOVA_USERNAME=${USERNAME:-demo}
 
 # With Keystone you pass the keystone password instead of an api key.
-export NOVA_API_KEY=${PASSWORD:-secrete}
+export NOVA_API_KEY=${ADMIN_PASSWORD:-secrete}
 
 # With the addition of Keystone, to use an openstack cloud you should 
 # authenticate against keystone, which returns a **Token** and **Service 
@@ -82,6 +85,15 @@
 # Let's grab the id of the first AMI image to launch
 IMAGE=`glance -A $TOKEN index | egrep ami | cut -d" " -f1`
 
+# Security Groups
+# ---------------
+SECGROUP=test_secgroup
+
+# List of secgroups:
+nova secgroup-list
+
+# Create a secgroup
+nova secgroup-create $SECGROUP "test_secgroup description"
 
 # Flavors
 # -------
@@ -92,9 +104,9 @@
 # and grab the first flavor in the list to launch
 FLAVOR=`nova flavor-list | head -n 4 | tail -n 1 | cut -d"|" -f2`
 
-NAME="firstpost"
+NAME="myserver"
 
-nova boot --flavor $FLAVOR --image $IMAGE $NAME
+nova boot --flavor $FLAVOR --image $IMAGE $NAME --security_groups=$SECGROUP
 
 # let's give it 10 seconds to launch
 sleep 10
@@ -113,10 +125,47 @@
 sleep 5
 
 ping -c1 -w1 $IP 
+# allow icmp traffic
+nova secgroup-add-rule $SECGROUP icmp -1 -1 0.0.0.0/0
+
+# List rules for a secgroup
+nova secgroup-list-rules $SECGROUP
+
+# allocate a floating ip
+nova floating-ip-create
+
+# store  floating address
+FIP=`nova floating-ip-list | grep None | head -1 | cut -d '|' -f2 | sed 's/ //g'`
+
+# add floating ip to our server
+nova add-floating-ip $NAME $FIP
+
+# sleep for a smidge
+sleep 1
+
+# ping our fip
+ping -c1 -w1 $FIP
+
+# dis-allow icmp traffic
+nova secgroup-delete-rule $SECGROUP icmp -1 -1 0.0.0.0/0
+
+# sleep for a smidge
+sleep 1
+
+# ping our fip
+if ( ping -c1 -w1 $FIP); then
+    print "Security group failure - ping should not be allowed!"
+    exit 1
+fi
+
+# de-allocate the floating ip
+nova floating-ip-delete $FIP
 
 # shutdown the server
 nova delete $NAME
 
+# Delete a secgroup
+nova secgroup-delete $SECGROUP
+
 # FIXME: validate shutdown within 5 seconds 
 # (nova show $NAME returns 1 or status != ACTIVE)?
-
diff --git a/stack.sh b/stack.sh
index 8e116a9..61c0f57 100755
--- a/stack.sh
+++ b/stack.sh
@@ -30,18 +30,19 @@
     fi
 fi
 
+# Keep track of the current devstack directory.
+TOP_DIR=$(cd $(dirname "$0") && pwd)
+
 # stack.sh keeps the list of **apt** and **pip** dependencies in external
 # files, along with config templates and other useful files.  You can find these
 # in the ``files`` directory (next to this script).  We will reference this
 # directory using the ``FILES`` variable in this script.
-FILES=`pwd`/files
+FILES=$TOP_DIR/files
 if [ ! -d $FILES ]; then
     echo "ERROR: missing devstack/files - did you grab more than just stack.sh?"
     exit 1
 fi
 
-# Keep track of the current devstack directory.
-TOP_DIR=$(cd $(dirname "$0") && pwd)
 
 
 # Settings
@@ -229,16 +230,15 @@
 # use an existing server, you can pass in the user/password/host parameters.
 # You will need to send the same ``MYSQL_PASSWORD`` to every host if you are doing
 # a multi-node devstack installation.
+MYSQL_HOST=${MYSQL_HOST:-localhost}
 MYSQL_USER=${MYSQL_USER:-root}
 read_password MYSQL_PASSWORD "ENTER A PASSWORD TO USE FOR MYSQL."
-MYSQL_HOST=${MYSQL_HOST:-localhost}
 
 # don't specify /db in this string, so we can use it for multiple services
 BASE_SQL_CONN=${BASE_SQL_CONN:-mysql://$MYSQL_USER:$MYSQL_PASSWORD@$MYSQL_HOST}
 
 # Rabbit connection info
 RABBIT_HOST=${RABBIT_HOST:-localhost}
-RABBIT_PASSWORD=${RABBIT_PASSWORD:-`openssl rand -hex 12`}
 read_password RABBIT_PASSWORD "ENTER A PASSWORD TO USE FOR RABBIT."
 
 # Glance connection info.  Note the port must be specified.
@@ -270,8 +270,11 @@
 # an error.  It is also useful for following along as the install occurs.
 set -o xtrace
 
+# create the destination directory and ensure it is writable by the user
 sudo mkdir -p $DEST
-sudo chown `whoami` $DEST
+if [ ! -w $DEST ]; then
+    sudo chown `whoami` $DEST
+fi
 
 # Install Packages
 # ================
@@ -290,9 +293,16 @@
 # be owned by the installation user, we create the directory and change the
 # ownership to the proper user.
 function git_clone {
+    # if there is an existing checkout, move it out of the way
+    if [[ "$RECLONE" == "yes" ]]; then
+        # FIXME(ja): if we were smarter we could speed up RECLONE by
+        # using the old git repo as the basis of our new clone...
+        if [ -d $2 ]; then
+            mv $2 /tmp/stack.`date +%s`
+        fi
+    fi
+
     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
@@ -322,10 +332,10 @@
 
 # setup our checkouts so they are installed into python path
 # allowing ``import nova`` or ``import glance.client``
-cd $NOVA_DIR; sudo python setup.py develop
-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 $NOVACLIENT_DIR; sudo python setup.py develop
+cd $NOVA_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
@@ -401,6 +411,8 @@
     # ``local_settings.py`` is used to override dashboard default settings.
     cp $FILES/dash_settings.py $DASH_DIR/openstack-dashboard/local/local_settings.py
 
+    # Initialize the dashboard database (it stores sessions and notices shown to
+    # users).  The user system is external (keystone).
     cd $DASH_DIR/openstack-dashboard
     dashboard/manage.py syncdb
 
@@ -428,7 +440,8 @@
     # (re)create glance database
     mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS glance;'
     mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE glance;'
-    # Copy over our glance-registry.conf
+
+    # Copy over our glance configurations and update them
     GLANCE_CONF=$GLANCE_DIR/etc/glance-registry.conf
     cp $FILES/glance-registry.conf $GLANCE_CONF
     sudo sed -e "s,%SQL_CONN%,$BASE_SQL_CONN/glance,g" -i $GLANCE_CONF
@@ -447,7 +460,7 @@
 # We are going to use the sample http middleware configuration from the keystone
 # project to launch nova.  This paste config adds the configuration required
 # for nova to validate keystone tokens - except we need to switch the config
-# to use our admin token instead (instead of the token from their sample data).
+# to use our service token instead (instead of the invalid token 999888777666).
 sudo sed -e "s,999888777666,$SERVICE_TOKEN,g" -i $KEYSTONE_DIR/examples/paste/nova-api-paste.ini
 
 if [[ "$ENABLED_SERVICES" =~ "n-cpu" ]]; then
@@ -458,9 +471,9 @@
     # attempt to load modules: network block device - used to manage qcow images
     sudo modprobe nbd || true
 
-    # Check for kvm (hardware based virtualization).  If unable to load kvm, 
-    # set the libvirt type to qemu.  Note: many systems come with hardware 
-    # virtualization disabled in BIOS.
+    # Check for kvm (hardware based virtualization).  If unable to initialize 
+    # kvm, we drop back to the slower emulation mode (qemu).  Note: many systems 
+    # come with hardware virtualization disabled in BIOS.
     if [[ "$LIBVIRT_TYPE" == "kvm" ]]; then
         sudo modprobe kvm || true
         if [ ! -e /dev/kvm ]; then
@@ -474,7 +487,8 @@
     # to simulate multiple systems.
     if [[ "$LIBVIRT_TYPE" == "lxc" ]]; then
         sudo apt-get install lxc -y
-        # lxc requires cgroups to be configured on /cgroup
+        # lxc uses cgroups (a kernel interface via virtual filesystem) configured
+        # and mounted to ``/cgroup``
         sudo mkdir -p /cgroup
         if ! grep -q cgroup /etc/fstab; then
             echo none /cgroup cgroup cpuacct,memory,devices,cpu,freezer,blkio 0 0 | sudo tee -a /etc/fstab
@@ -484,9 +498,12 @@
         fi
     fi
 
-    # User needs to be member of libvirtd group for nova-compute to use libvirt.
+    # The user that nova runs as needs to be member of libvirtd group otherwise
+    # nova-compute will be unable to use libvirt.
     sudo usermod -a -G libvirtd `whoami`
-    # if kvm wasn't running before we need to restart libvirt to enable it
+    # libvirt detects various settings on startup, as we potentially changed 
+    # the system configuration (modules, filesystems), we need to restart
+    # libvirt to detect those changes.
     sudo /etc/init.d/libvirt-bin restart
 
 
@@ -496,12 +513,14 @@
     # Nova stores each instance in its own directory.
     mkdir -p $NOVA_DIR/instances
 
-    # if there is a partition labeled nova-instances use it (ext filesystems
-    # can be labeled via e2label)
-    ## FIXME: if already mounted this blows up...
+    # You can specify a different disk to be mounted and used for backing the
+    # virtual machines.  If there is a partition labeled nova-instances we 
+    # mount it (ext filesystems can be labeled via e2label).
     if [ -L /dev/disk/by-label/nova-instances ]; then
-        sudo mount -L nova-instances $NOVA_DIR/instances
-        sudo chown -R `whoami` $NOVA_DIR/instances
+        if ! mount -n | grep -q nova-instances; then
+            sudo mount -L nova-instances $NOVA_DIR/instances
+            sudo chown -R `whoami` $NOVA_DIR/instances
+        fi
     fi
 
     # Clean out the instances directory.
@@ -668,10 +687,10 @@
 # TTY also uses cloud-init, supporting login via keypair and sending scripts as
 # userdata.  See https://help.ubuntu.com/community/CloudInit for more on cloud-init
 #
-# Override IMAGE_URLS if you would to launch a different image(s).  
-# Specify IMAGE_URLS as a comma-separated list of uec urls.  Some other options include:
-#   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
+# Override ``IMAGE_URLS`` with a comma-seperated list of uec images.
+#
+#  * **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
     # Create a directory for the downloaded image tarballs.
diff --git a/stackrc b/stackrc
index e1b65c3..aaee6ec 100644
--- a/stackrc
+++ b/stackrc
@@ -16,7 +16,7 @@
 
 # django powered web control panel for openstack
 DASH_REPO=https://github.com/cloudbuilders/openstack-dashboard.git
-DASH_BRANCH=master
+DASH_BRANCH=diablo
 
 # python client library to nova that dashboard (and others) use
 NOVACLIENT_REPO=https://github.com/cloudbuilders/python-novaclient.git
diff --git a/tools/build_lxc.sh b/tools/build_lxc.sh
index 42bd328..df9e32e 100755
--- a/tools/build_lxc.sh
+++ b/tools/build_lxc.sh
@@ -32,7 +32,7 @@
 CONTAINER_CIDR=${CONTAINER_CIDR:-$CONTAINER_IP/24}
 CONTAINER_NETMASK=${CONTAINER_NETMASK:-255.255.255.0}
 CONTAINER_GATEWAY=${CONTAINER_GATEWAY:-192.168.1.1}
-NAMESERVER=${NAMESERVER:-$CONTAINER_GATEWAY}
+NAMESERVER=${NAMESERVER:-`cat /etc/resolv.conf | grep nameserver | head -1 | cut -d " " -f2`}
 COPYENV=${COPYENV:-1}
 DEST=${DEST:-/opt/stack}
 WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1}
@@ -119,12 +119,15 @@
     lxc-destroy -n $CONTAINER
     # trigger the initial debootstrap
     create_lxc
-    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 pip install `cat files/pips/*`
     touch $CACHEDIR/bootstrapped
 fi
 
+# Make sure that base requirements are installed
+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 --download-only rabbitmq-server libvirt-bin mysql-server
+chroot $CACHEDIR pip install `cat files/pips/*`
+
 # Clean out code repos if directed to do so
 if [ "$CLEAN" = "1" ]; then
     rm -rf $CACHEDIR/$DEST
@@ -135,10 +138,12 @@
 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 $NOVNC_REPO $CACHEDIR/$DEST/noVNC $NOVNC_BRANCH
 git_clone $DASH_REPO $CACHEDIR/$DEST/dash $DASH_BRANCH $DASH_TAG
 git_clone $NOVACLIENT_REPO $CACHEDIR/$DEST/python-novaclient $NOVACLIENT_BRANCH
 git_clone $OPENSTACKX_REPO $CACHEDIR/$DEST/openstackx $OPENSTACKX_BRANCH
+git_clone $KEYSTONE_REPO $CACHEDIR/$DEST/keystone $KEYSTONE_BRANCH
+git_clone $NOVNC_REPO $CACHEDIR/$DEST/novnc $NOVNC_BRANCH
 
 # Use this version of devstack?
 if [ "$USE_CURRENT_DEVSTACK" = "1" ]; then
@@ -282,6 +287,7 @@
     TAIL_PID=$!
 
     function kill_tail() {
+        kill $TAIL_PID
         exit 1
     }
  
diff --git a/tools/build_usb_boot.sh b/tools/build_usb_boot.sh
index ac49848..332c869 100755
--- a/tools/build_usb_boot.sh
+++ b/tools/build_usb_boot.sh
@@ -21,22 +21,25 @@
     # We have a block device, install syslinux and mount it
     DEST_DEV=$DEST_DIR
     DEST_DIR=`mktemp -d mntXXXXXX`
+    mount $DEST_DEV $DEST_DIR
+
+    if [ ! -d $DEST_DIR/syslinux ]; then
+        mkdir -p $DEST_DIR/syslinux
+    fi
 
     # Install syslinux on the device
     syslinux --install --directory syslinux $DEST_DEV
-
-    mount $DEST_DEV $DEST_DIR
 else
     # We have a directory (for sanity checking output)
-	DEST_DEV=""
-	if [ ! -d $DEST_DIR/syslinux ]; then
-	    mkdir -p $DEST_DIR/syslinux
-	fi
+    DEST_DEV=""
+    if [ ! -d $DEST_DIR/syslinux ]; then
+        mkdir -p $DEST_DIR/syslinux
+    fi
 fi
 
 # Get some more stuff from syslinux
 for i in memdisk menu.c32; do
-	cp -p /usr/lib/syslinux/$i $DEST_DIR/syslinux
+    cp -p /usr/lib/syslinux/$i $DEST_DIR/syslinux
 done
 
 CFG=$DEST_DIR/syslinux/syslinux.cfg