Merge "Add support for Docker as Nova hypervisor"
diff --git a/files/apts/glance b/files/apts/glance
index a05e9f2..26826a5 100644
--- a/files/apts/glance
+++ b/files/apts/glance
@@ -1,5 +1,10 @@
 gcc
+libffi-dev          # testonly
+libmysqlclient-dev  # testonly
+libpq-dev           # testonly
+libssl-dev          # testonly
 libxml2-dev
+libxslt1-dev        # testonly
 python-dev
 python-eventlet
 python-routes
@@ -10,3 +15,4 @@
 python-pastedeploy
 python-xattr
 python-iso8601
+zlib1g-dev           # testonly
diff --git a/files/rpms/glance b/files/rpms/glance
index 0f113ea..dd66171 100644
--- a/files/rpms/glance
+++ b/files/rpms/glance
@@ -1,5 +1,10 @@
 gcc
+libffi-devel        # testonly
 libxml2-devel
+libxslt-devel       # testonly
+mysql-devel         # testonly
+openssl-devel       # testonly
+postgresql-devel    # testonly
 python-argparse
 python-devel
 python-eventlet
@@ -9,3 +14,4 @@
 python-sqlalchemy
 python-wsgiref
 pyxattr
+zlib-devel          # testonly
diff --git a/files/sources.list b/files/sources.list
deleted file mode 100644
index 77a1bfb..0000000
--- a/files/sources.list
+++ /dev/null
@@ -1,9 +0,0 @@
-deb http://mirror.rackspace.com/ubuntu/ %DIST% main restricted
-deb http://mirror.rackspace.com/ubuntu/ %DIST%-updates main restricted
-deb http://mirror.rackspace.com/ubuntu/ %DIST% universe
-deb http://mirror.rackspace.com/ubuntu/ %DIST%-updates universe
-deb http://mirror.rackspace.com/ubuntu/ %DIST% multiverse
-deb http://mirror.rackspace.com/ubuntu/ %DIST%-updates multiverse
-deb http://security.ubuntu.com/ubuntu %DIST%-security main restricted
-deb http://security.ubuntu.com/ubuntu %DIST%-security universe
-deb http://security.ubuntu.com/ubuntu %DIST%-security multiverse
diff --git a/functions b/functions
index 37876e0..f24cc89 100644
--- a/functions
+++ b/functions
@@ -317,16 +317,36 @@
                 continue
             fi
 
+            # Assume we want this package
+            package=${line%#*}
+            inst_pkg=1
+
+            # Look for # dist:xxx in comment
             if [[ $line =~ (.*)#.*dist:([^ ]*) ]]; then
                 # We are using BASH regexp matching feature.
                 package=${BASH_REMATCH[1]}
                 distros=${BASH_REMATCH[2]}
                 # In bash ${VAR,,} will lowecase VAR
-                [[ ${distros,,} =~ ${DISTRO,,} ]] && echo $package
-                continue
+                # Look for a match in the distro list
+                if [[ ! ${distros,,} =~ ${DISTRO,,} ]]; then
+                    # If no match then skip this package
+                    inst_pkg=0
+                fi
             fi
 
-            echo ${line%#*}
+            # Look for # testonly in comment
+            if [[ $line =~ (.*)#.*testonly.* ]]; then
+                package=${BASH_REMATCH[1]}
+                # Are we installing test packages? (test for the default value)
+                if [[ $INSTALL_TESTONLY_PACKAGES = "False" ]]; then
+                    # If not installing test packages the skip this package
+                    inst_pkg=0
+                fi
+            fi
+
+            if [[ $inst_pkg = 1 ]]; then
+                echo $package
+            fi
         done
         IFS=$OIFS
     done
@@ -912,7 +932,7 @@
     fi
 
     if [[ "$os_PACKAGE" = "deb" ]]; then
-        dpkg -l "$@" > /dev/null
+        dpkg -s "$@" > /dev/null 2> /dev/null
     elif [[ "$os_PACKAGE" = "rpm" ]]; then
         rpm --quiet -q "$@"
     else
@@ -1063,7 +1083,7 @@
             sleep 1.5
 
             NL=`echo -ne '\015'`
-            screen -S $SCREEN_NAME -p $1 -X stuff "$2 || touch \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\"$NL"
+            screen -S $SCREEN_NAME -p $1 -X stuff "$2 || echo \"$1 failed to start\" | tee \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\"$NL"
         else
             # Spawn directly without screen
             run_process "$1" "$2" >$SERVICE_DIR/$SCREEN_NAME/$service.pid
@@ -1240,7 +1260,7 @@
         return
     fi
 
-    # XenServer-ovf-format images are provided as .vhd.tgz as well
+    # XenServer-vhd-ovf-format images are provided as .vhd.tgz
     # and should not be decompressed prior to loading
     if [[ "$image_url" =~ '.vhd.tgz' ]]; then
         IMAGE="$FILES/${IMAGE_FNAME}"
@@ -1249,6 +1269,22 @@
         return
     fi
 
+    # .xen-raw.tgz suggests a Xen capable raw image inside a tgz.
+    # and should not be decompressed prior to loading.
+    # Setting metadata, so PV mode is used.
+    if [[ "$image_url" =~ '.xen-raw.tgz' ]]; then
+        IMAGE="$FILES/${IMAGE_FNAME}"
+        IMAGE_NAME="${IMAGE_FNAME%.xen-raw.tgz}"
+        glance \
+          --os-auth-token $token \
+          --os-image-url http://$GLANCE_HOSTPORT \
+          image-create \
+            --name "$IMAGE_NAME" --is-public=True \
+            --container-format=tgz --disk-format=raw \
+            --property vm_mode=xen < "${IMAGE}"
+        return
+    fi
+
     KERNEL=""
     RAMDISK=""
     DISK_FORMAT=""
diff --git a/lib/cinder b/lib/cinder
index 54cf844..826b958 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -289,12 +289,11 @@
         fi
     elif [ "$CINDER_DRIVER" == "vsphere" ]; then
         echo_summary "Using VMware vCenter driver"
-        iniset $CINDER_CONF DEFAULT enabled_backends vmware
-        iniset $CINDER_CONF vmware host_ip "$VMWAREAPI_IP"
-        iniset $CINDER_CONF vmware host_username "$VMWAREAPI_USER"
-        iniset $CINDER_CONF vmware host_password "$VMWAREAPI_PASSWORD"
-        iniset $CINDER_CONF vmware cluster_name "$VMWAREAPI_CLUSTER"
-        iniset $CINDER_CONF vmware volume_driver "cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver"
+        iniset $CINDER_CONF DEFAULT vmware_host_ip "$VMWAREAPI_IP"
+        iniset $CINDER_CONF DEFAULT vmware_host_username "$VMWAREAPI_USER"
+        iniset $CINDER_CONF DEFAULT vmware_host_password "$VMWAREAPI_PASSWORD"
+        iniset $CINDER_CONF DEFAULT vmware_cluster_name "$VMWAREAPI_CLUSTER"
+        iniset $CINDER_CONF DEFAULT volume_driver "cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver"
     fi
 
     if [[ is_fedora && $DISTRO =~ (rhel6) ]]; then
@@ -468,6 +467,7 @@
 function install_cinderclient() {
     git_clone $CINDERCLIENT_REPO $CINDERCLIENT_DIR $CINDERCLIENT_BRANCH
     setup_develop $CINDERCLIENT_DIR
+    sudo install -D -m 0644 -o $STACK_USER {$CINDERCLIENT_DIR/tools/,/etc/bash_completion.d/}cinder.bash_completion
 }
 
 # apply config.d approach for cinder volumes directory
diff --git a/lib/glance b/lib/glance
index a18189f..64d8b06 100644
--- a/lib/glance
+++ b/lib/glance
@@ -108,6 +108,10 @@
     fi
     iniset_rpc_backend glance $GLANCE_API_CONF DEFAULT
     iniset $GLANCE_API_CONF keystone_authtoken signing_dir $GLANCE_AUTH_CACHE_DIR/api
+    if [ "$VIRT_DRIVER" = 'xenserver' ]; then
+        iniset $GLANCE_API_CONF DEFAULT container_formats "ami,ari,aki,bare,ovf,tgz"
+        iniset $GLANCE_API_CONF DEFAULT disk_formats "ami,ari,aki,vhd,raw,iso"
+    fi
 
     # Store the images in swift if enabled.
     if is_service_enabled s-proxy; then
diff --git a/lib/heat b/lib/heat
index fb4002b..67509bc 100644
--- a/lib/heat
+++ b/lib/heat
@@ -31,6 +31,10 @@
 HEATCLIENT_DIR=$DEST/python-heatclient
 HEAT_AUTH_CACHE_DIR=${HEAT_AUTH_CACHE_DIR:-/var/cache/heat}
 HEAT_STANDALONE=`trueorfalse False $HEAT_STANDALONE`
+HEAT_CONF_DIR=/etc/heat
+HEAT_CONF=$HEAT_CONF_DIR/heat.conf
+HEAT_ENV_DIR=$HEAT_CONF_DIR/environment.d
+HEAT_TEMPLATES_DIR=$HEAT_CONF_DIR/templates
 
 # Functions
 # ---------
@@ -39,17 +43,20 @@
 # runs that a clean run would need to clean up
 function cleanup_heat() {
     sudo rm -rf $HEAT_AUTH_CACHE_DIR
+    sudo rm -rf $HEAT_ENV_DIR
+    sudo rm -rf $HEAT_TEMPLATES_DIR
 }
 
 # configure_heat() - Set config files, create data dirs, etc
 function configure_heat() {
     setup_develop $HEAT_DIR
 
-    HEAT_CONF_DIR=/etc/heat
     if [[ ! -d $HEAT_CONF_DIR ]]; then
         sudo mkdir -p $HEAT_CONF_DIR
     fi
     sudo chown $STACK_USER $HEAT_CONF_DIR
+    # remove old config files
+    rm -f $HEAT_CONF_DIR/heat-*.conf
 
     HEAT_API_CFN_HOST=${HEAT_API_CFN_HOST:-$SERVICE_HOST}
     HEAT_API_CFN_PORT=${HEAT_API_CFN_PORT:-8000}
@@ -64,96 +71,67 @@
 
     cp $HEAT_DIR/etc/heat/api-paste.ini $HEAT_API_PASTE_FILE
     cp $HEAT_DIR/etc/heat/policy.json $HEAT_POLICY_FILE
+    cp $HEAT_DIR/etc/heat/heat.conf.sample $HEAT_CONF
 
-    # Cloudformation API
-    HEAT_API_CFN_CONF=$HEAT_CONF_DIR/heat-api-cfn.conf
-    cp $HEAT_DIR/etc/heat/heat-api-cfn.conf $HEAT_API_CFN_CONF
-    iniset $HEAT_API_CFN_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
-    inicomment $HEAT_API_CFN_CONF DEFAULT log_file
-    iniset $HEAT_API_CFN_CONF DEFAULT use_syslog $SYSLOG
-    iniset $HEAT_API_CFN_CONF DEFAULT bind_host $HEAT_API_CFN_HOST
-    iniset $HEAT_API_CFN_CONF DEFAULT bind_port $HEAT_API_CFN_PORT
-    iniset $HEAT_API_CFN_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
-    iniset $HEAT_API_CFN_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
-    iniset $HEAT_API_CFN_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL
-    iniset $HEAT_API_CFN_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
-    iniset $HEAT_API_CFN_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
-    iniset $HEAT_API_CFN_CONF keystone_authtoken admin_user heat
-    iniset $HEAT_API_CFN_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
-    iniset $HEAT_API_CFN_CONF keystone_authtoken signing_dir $HEAT_AUTH_CACHE_DIR/api-cfn
-    iniset $HEAT_API_CFN_CONF ec2authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
-    iniset $HEAT_API_CFN_CONF ec2authtoken keystone_ec2_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/ec2tokens
-    [[ "$HEAT_STANDALONE" = "True" ]] && iniset $HEAT_API_CFN_CONF paste_deploy flavor standalone
+    # common options
+    iniset_rpc_backend heat $HEAT_CONF DEFAULT
+    iniset $HEAT_CONF DEFAULT heat_metadata_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT
+    iniset $HEAT_CONF DEFAULT heat_waitcondition_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT/v1/waitcondition
+    iniset $HEAT_CONF DEFAULT heat_watch_server_url http://$HEAT_API_CW_HOST:$HEAT_API_CW_PORT
+    iniset $HEAT_CONF DEFAULT sql_connection `database_connection_url heat`
+    iniset $HEAT_CONF DEFAULT auth_encryption_key `hexdump -n 16 -v -e '/1 "%02x"' /dev/random`
 
-    iniset_rpc_backend heat $HEAT_API_CFN_CONF DEFAULT
-
-    # OpenStack API
-    HEAT_API_CONF=$HEAT_CONF_DIR/heat-api.conf
-    cp $HEAT_DIR/etc/heat/heat-api.conf $HEAT_API_CONF
-    iniset $HEAT_API_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
-    inicomment $HEAT_API_CONF DEFAULT log_file
-    iniset $HEAT_API_CONF DEFAULT use_syslog $SYSLOG
-    iniset $HEAT_API_CONF DEFAULT bind_host $HEAT_API_HOST
-    iniset $HEAT_API_CONF DEFAULT bind_port $HEAT_API_PORT
-    iniset $HEAT_API_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
-    iniset $HEAT_API_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
-    iniset $HEAT_API_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL
-    iniset $HEAT_API_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
-    iniset $HEAT_API_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
-    iniset $HEAT_API_CONF keystone_authtoken admin_user heat
-    iniset $HEAT_API_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
-    iniset $HEAT_API_CONF keystone_authtoken signing_dir $HEAT_AUTH_CACHE_DIR/api
-    iniset $HEAT_API_CONF ec2authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
-    iniset $HEAT_API_CONF ec2authtoken keystone_ec2_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/ec2tokens
-    [[ "$HEAT_STANDALONE" = "True" ]] && iniset $HEAT_API_CONF paste_deploy flavor standalone
-    iniset_rpc_backend heat $HEAT_API_CONF DEFAULT
-
-
-    # engine
-    HEAT_ENGINE_CONF=$HEAT_CONF_DIR/heat-engine.conf
-    cp $HEAT_DIR/etc/heat/heat-engine.conf $HEAT_ENGINE_CONF
-    iniset $HEAT_ENGINE_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
-    inicomment $HEAT_ENGINE_CONF DEFAULT log_file
-    iniset $HEAT_ENGINE_CONF DEFAULT use_syslog $SYSLOG
-    iniset $HEAT_ENGINE_CONF DEFAULT bind_host $HEAT_ENGINE_HOST
-    iniset $HEAT_ENGINE_CONF DEFAULT bind_port $HEAT_ENGINE_PORT
-    iniset $HEAT_ENGINE_CONF DEFAULT heat_metadata_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT
-    iniset $HEAT_ENGINE_CONF DEFAULT heat_waitcondition_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT/v1/waitcondition
-    iniset $HEAT_ENGINE_CONF DEFAULT heat_watch_server_url http://$HEAT_API_CW_HOST:$HEAT_API_CW_PORT
-    iniset $HEAT_ENGINE_CONF DEFAULT sql_connection `database_connection_url heat`
-    iniset $HEAT_ENGINE_CONF DEFAULT auth_encryption_key `hexdump -n 16 -v -e '/1 "%02x"' /dev/random`
-
-    iniset_rpc_backend heat $HEAT_ENGINE_CONF DEFAULT
-
+    # logging
+    iniset $HEAT_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
+    iniset $HEAT_CONF DEFAULT use_syslog $SYSLOG
     if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
         # Add color to logging output
-        iniset $HEAT_ENGINE_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s%(color)s] %(instance)s%(color)s%(message)s"
-        iniset $HEAT_ENGINE_CONF DEFAULT logging_default_format_string "%(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [-%(color)s] %(instance)s%(color)s%(message)s"
-        iniset $HEAT_ENGINE_CONF DEFAULT logging_debug_format_suffix "from (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d"
-        iniset $HEAT_ENGINE_CONF DEFAULT logging_exception_prefix "%(color)s%(asctime)s.%(msecs)03d TRACE %(name)s %(instance)s"
+        iniset $HEAT_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s%(color)s] %(instance)s%(color)s%(message)s"
+        iniset $HEAT_CONF DEFAULT logging_default_format_string "%(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [-%(color)s] %(instance)s%(color)s%(message)s"
+        iniset $HEAT_CONF DEFAULT logging_debug_format_suffix "from (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d"
+        iniset $HEAT_CONF DEFAULT logging_exception_prefix "%(color)s%(asctime)s.%(msecs)03d TRACE %(name)s %(instance)s"
     fi
 
-    # Cloudwatch API
-    HEAT_API_CW_CONF=$HEAT_CONF_DIR/heat-api-cloudwatch.conf
-    cp $HEAT_DIR/etc/heat/heat-api-cloudwatch.conf $HEAT_API_CW_CONF
-    iniset $HEAT_API_CW_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
-    inicomment $HEAT_API_CW_CONF DEFAULT log_file
-    iniset $HEAT_API_CW_CONF DEFAULT use_syslog $SYSLOG
-    iniset $HEAT_API_CW_CONF DEFAULT bind_host $HEAT_API_CW_HOST
-    iniset $HEAT_API_CW_CONF DEFAULT bind_port $HEAT_API_CW_PORT
-    iniset $HEAT_API_CW_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
-    iniset $HEAT_API_CW_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
-    iniset $HEAT_API_CW_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL
-    iniset $HEAT_API_CW_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
-    iniset $HEAT_API_CW_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
-    iniset $HEAT_API_CW_CONF keystone_authtoken admin_user heat
-    iniset $HEAT_API_CW_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
-    iniset $HEAT_API_CW_CONF keystone_authtoken signing_dir $HEAT_AUTH_CACHE_DIR/api-cloudwatch
-    iniset $HEAT_API_CW_CONF ec2authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
-    iniset $HEAT_API_CW_CONF ec2authtoken keystone_ec2_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/ec2tokens
-    [[ "$HEAT_STANDALONE" = "True" ]] && iniset $HEAT_API_CW_CONF paste_deploy flavor standalone
+    # keystone authtoken
+    iniset $HEAT_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
+    iniset $HEAT_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
+    iniset $HEAT_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL
+    iniset $HEAT_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
+    iniset $HEAT_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
+    iniset $HEAT_CONF keystone_authtoken admin_user heat
+    iniset $HEAT_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
+    iniset $HEAT_CONF keystone_authtoken signing_dir $HEAT_AUTH_CACHE_DIR/api-cfn
 
-    iniset_rpc_backend heat $HEAT_API_CW_CONF DEFAULT
+    # ec2authtoken
+    iniset $HEAT_CONF ec2authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0
+    iniset $HEAT_CONF ec2authtoken keystone_ec2_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/ec2tokens
+
+    # paste_deploy
+    [[ "$HEAT_STANDALONE" = "True" ]] && iniset $HEAT_CONF paste_deploy flavor standalone
+
+    # OpenStack API
+    iniset $HEAT_CONF heat_api bind_host $HEAT_API_HOST
+    iniset $HEAT_CONF heat_api bind_port $HEAT_API_PORT
+
+    # Cloudformation API
+    iniset $HEAT_CONF heat_api_cfn bind_host $HEAT_API_CFN_HOST
+    iniset $HEAT_CONF heat_api_cfn bind_port $HEAT_API_CFN_PORT
+
+    # Cloudwatch API
+    iniset $HEAT_CONF heat_api_cloudwatch bind_host $HEAT_API_CW_HOST
+    iniset $HEAT_CONF heat_api_cloudwatch bind_port $HEAT_API_CW_PORT
+
+    # heat environment
+    sudo mkdir -p $HEAT_ENV_DIR
+    sudo chown $STACK_USER $HEAT_ENV_DIR
+    # copy the default environment
+    cp $HEAT_DIR/etc/heat/environment.d/* $HEAT_ENV_DIR/
+
+    # heat template resources.
+    sudo mkdir -p $HEAT_TEMPLATES_DIR
+    sudo chown $STACK_USER $HEAT_TEMPLATES_DIR
+    # copy the default templates
+    cp $HEAT_DIR/etc/heat/templates/* $HEAT_TEMPLATES_DIR/
 
 }
 
@@ -191,10 +169,10 @@
 
 # start_heat() - Start running processes, including screen
 function start_heat() {
-    screen_it h-eng "cd $HEAT_DIR; bin/heat-engine --config-file=$HEAT_CONF_DIR/heat-engine.conf"
-    screen_it h-api "cd $HEAT_DIR; bin/heat-api --config-dir=$HEAT_CONF_DIR/heat-api.conf"
-    screen_it h-api-cfn "cd $HEAT_DIR; bin/heat-api-cfn --config-dir=$HEAT_CONF_DIR/heat-api-cfn.conf"
-    screen_it h-api-cw "cd $HEAT_DIR; bin/heat-api-cloudwatch --config-dir=$HEAT_CONF_DIR/heat-api-cloudwatch.conf"
+    screen_it h-eng "cd $HEAT_DIR; bin/heat-engine --config-file=$HEAT_CONF"
+    screen_it h-api "cd $HEAT_DIR; bin/heat-api --config-file=$HEAT_CONF"
+    screen_it h-api-cfn "cd $HEAT_DIR; bin/heat-api-cfn --config-file=$HEAT_CONF"
+    screen_it h-api-cw "cd $HEAT_DIR; bin/heat-api-cloudwatch --config-file=$HEAT_CONF"
 }
 
 # stop_heat() - Stop running processes
diff --git a/lib/horizon b/lib/horizon
index 89bd659..f6bb9f5 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -50,7 +50,7 @@
         if [ -n "$line" ]; then
             sed -i -e "/^$section/,/^}/ s/^\( *'$option'\) *:.*$/\1: $value,/" $file
         else
-            sed -i -e "/^$section/ a\n    '$option': $value,\n" $file
+            sed -i -e "/^$section/a\    '$option': $value," $file
         fi
     else
         echo -e "\n\n$section = {\n    '$option': $value,\n}" >> $file
@@ -96,6 +96,11 @@
         _horizon_config_set $local_settings OPENSTACK_NEUTRON_NETWORK enable_lb True
     fi
 
+    # enable firewall dashboard in case service is enabled
+    if is_service_enabled q-fwaas; then
+        _horizon_config_set $local_settings OPENSTACK_NEUTRON_NETWORK enable_firewall True
+    fi
+
     # Initialize the horizon database (it stores sessions and notices shown to
     # users).  The user system is external (keystone).
     cd $HORIZON_DIR
@@ -106,13 +111,13 @@
     sudo mkdir -p $HORIZON_DIR/.blackhole
 
     HORIZON_REQUIRE=''
-    local horizon_conf=/etc/$APACHE_NAME/$APACHE_CONF_DIR/horizon
+    local horizon_conf=/etc/$APACHE_NAME/$APACHE_CONF_DIR/horizon.conf
     if is_ubuntu; then
         # Clean up the old config name
         sudo rm -f /etc/apache2/sites-enabled/000-default
         # Be a good citizen and use the distro tools here
         sudo touch $horizon_conf
-        sudo a2ensite horizon
+        sudo a2ensite horizon.conf
         # WSGI isn't enabled by default, enable it
         sudo a2enmod wsgi
     elif is_fedora; then
diff --git a/lib/keystone b/lib/keystone
index e7e0544..0a35dd5 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -289,6 +289,7 @@
 function install_keystoneclient() {
     git_clone $KEYSTONECLIENT_REPO $KEYSTONECLIENT_DIR $KEYSTONECLIENT_BRANCH
     setup_develop $KEYSTONECLIENT_DIR
+    sudo install -D -m 0644 -o $STACK_USER {$KEYSTONECLIENT_DIR/tools/,/etc/bash_completion.d/}keystone.bash_completion
 }
 
 # install_keystone() - Collect source and prepare
diff --git a/lib/neutron b/lib/neutron
index 31876de..01fe3ea 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -207,6 +207,10 @@
 # Hardcoding for 1 service plugin for now
 source $TOP_DIR/lib/neutron_plugins/services/vpn
 
+# Firewall Service Plugin functions
+# --------------------------------
+source $TOP_DIR/lib/neutron_plugins/services/firewall
+
 # Use security group or not
 if has_neutron_plugin_security_group; then
     Q_USE_SECGROUP=${Q_USE_SECGROUP:-True}
@@ -230,6 +234,9 @@
     if is_service_enabled q-vpn; then
         _configure_neutron_vpn
     fi
+    if is_service_enabled q-fwaas; then
+        _configure_neutron_fwaas
+    fi
     if is_service_enabled q-svc; then
         _configure_neutron_service
     fi
@@ -250,18 +257,18 @@
 }
 
 function create_nova_conf_neutron() {
-    iniset $NOVA_CONF DEFAULT network_api_class "nova.network.quantumv2.api.API"
-    iniset $NOVA_CONF DEFAULT quantum_admin_username "$Q_ADMIN_USERNAME"
-    iniset $NOVA_CONF DEFAULT quantum_admin_password "$SERVICE_PASSWORD"
-    iniset $NOVA_CONF DEFAULT quantum_admin_auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v2.0"
-    iniset $NOVA_CONF DEFAULT quantum_auth_strategy "$Q_AUTH_STRATEGY"
-    iniset $NOVA_CONF DEFAULT quantum_admin_tenant_name "$SERVICE_TENANT_NAME"
-    iniset $NOVA_CONF DEFAULT quantum_region_name "RegionOne"
-    iniset $NOVA_CONF DEFAULT quantum_url "http://$Q_HOST:$Q_PORT"
+    iniset $NOVA_CONF DEFAULT network_api_class "nova.network.neutronv2.api.API"
+    iniset $NOVA_CONF DEFAULT neutron_admin_username "$Q_ADMIN_USERNAME"
+    iniset $NOVA_CONF DEFAULT neutron_admin_password "$SERVICE_PASSWORD"
+    iniset $NOVA_CONF DEFAULT neutron_admin_auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v2.0"
+    iniset $NOVA_CONF DEFAULT neutron_auth_strategy "$Q_AUTH_STRATEGY"
+    iniset $NOVA_CONF DEFAULT neutron_admin_tenant_name "$SERVICE_TENANT_NAME"
+    iniset $NOVA_CONF DEFAULT neutron_region_name "RegionOne"
+    iniset $NOVA_CONF DEFAULT neutron_url "http://$Q_HOST:$Q_PORT"
 
     if [[ "$Q_USE_SECGROUP" == "True" ]]; then
         LIBVIRT_FIREWALL_DRIVER=nova.virt.firewall.NoopFirewallDriver
-        iniset $NOVA_CONF DEFAULT security_group_api quantum
+        iniset $NOVA_CONF DEFAULT security_group_api neutron
     fi
 
     # set NOVA_VIF_DRIVER and optionally set options in nova_conf
@@ -270,7 +277,7 @@
     iniset $NOVA_CONF DEFAULT libvirt_vif_driver "$NOVA_VIF_DRIVER"
     iniset $NOVA_CONF DEFAULT linuxnet_interface_driver "$LINUXNET_VIF_DRIVER"
     if is_service_enabled q-meta; then
-        iniset $NOVA_CONF DEFAULT service_quantum_metadata_proxy "True"
+        iniset $NOVA_CONF DEFAULT service_neutron_metadata_proxy "True"
     fi
 }
 
@@ -382,6 +389,7 @@
 function install_neutronclient() {
     git_clone $NEUTRONCLIENT_REPO $NEUTRONCLIENT_DIR $NEUTRONCLIENT_BRANCH
     setup_develop $NEUTRONCLIENT_DIR
+    sudo install -D -m 0644 -o $STACK_USER {$NEUTRONCLIENT_DIR/tools/,/etc/bash_completion.d/}neutron.bash_completion
 }
 
 # install_neutron_agent_packages() - Collect source and prepare
@@ -418,11 +426,17 @@
     screen_it q-agt "cd $NEUTRON_DIR && python $AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
     screen_it q-dhcp "cd $NEUTRON_DIR && python $AGENT_DHCP_BINARY --config-file $NEUTRON_CONF --config-file=$Q_DHCP_CONF_FILE"
 
-    if is_service_enabled q-vpn; then
-        screen_it q-vpn "cd $NEUTRON_DIR && $AGENT_VPN_BINARY --config-file $NEUTRON_CONF --config-file=$Q_L3_CONF_FILE"
-    else
-        screen_it q-l3 "cd $NEUTRON_DIR && python $AGENT_L3_BINARY --config-file $NEUTRON_CONF --config-file=$Q_L3_CONF_FILE"
+    L3_CONF_FILES="--config-file $NEUTRON_CONF --config-file=$Q_L3_CONF_FILE"
+
+    if is_service_enabled q-fwaas; then
+        L3_CONF_FILES="$L3_CONF_FILES --config-file $Q_FWAAS_CONF_FILE"
     fi
+    if is_service_enabled q-vpn; then
+        screen_it q-vpn "cd $NEUTRON_DIR && $AGENT_VPN_BINARY $L3_CONF_FILES"
+    else
+        screen_it q-l3 "cd $NEUTRON_DIR && python $AGENT_L3_BINARY $L3_CONF_FILES"
+    fi
+
     screen_it q-meta "cd $NEUTRON_DIR && python $AGENT_META_BINARY --config-file $NEUTRON_CONF --config-file=$Q_META_CONF_FILE"
 
     if [ "$VIRT_DRIVER" = 'xenserver' ]; then
@@ -541,6 +555,14 @@
     iniset $Q_DHCP_CONF_FILE DEFAULT use_namespaces $Q_USE_NAMESPACE
     iniset $Q_DHCP_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
 
+    # Define extra "DEFAULT" configuration options when q-dhcp is configured by
+    # defining the array ``Q_DHCP_EXTRA_DEFAULT_OPTS``.
+    # For Example: ``Q_DHCP_EXTRA_DEFAULT_OPTS=(foo=true bar=2)``
+    for I in "${Q_DHCP_EXTRA_DEFAULT_OPTS[@]}"; do
+        # Replace the first '=' with ' ' for iniset syntax
+        iniset $Q_DHCP_CONF_FILE DEFAULT ${I/=/ }
+    done
+
     _neutron_setup_interface_driver $Q_DHCP_CONF_FILE
 
     neutron_plugin_configure_dhcp_agent
@@ -554,6 +576,10 @@
     AGENT_L3_BINARY=${AGENT_L3_BINARY:-"$NEUTRON_BIN_DIR/neutron-l3-agent"}
     Q_L3_CONF_FILE=$NEUTRON_CONF_DIR/l3_agent.ini
 
+    if is_service_enabled q-fwaas; then
+        Q_FWAAS_CONF_FILE=$NEUTRON_CONF_DIR/fwaas_driver.ini
+    fi
+
     cp $NEUTRON_DIR/etc/l3_agent.ini $Q_L3_CONF_FILE
 
     iniset $Q_L3_CONF_FILE DEFAULT verbose True
@@ -577,7 +603,7 @@
     iniset $Q_META_CONF_FILE DEFAULT nova_metadata_ip $Q_META_DATA_IP
     iniset $Q_META_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
 
-    _neutron_setup_keystone $Q_META_CONF_FILE DEFAULT True True
+    _neutron_setup_keystone $Q_META_CONF_FILE DEFAULT True True True
 
 }
 
@@ -586,6 +612,11 @@
     neutron_agent_lbaas_configure_agent
 }
 
+function _configure_neutron_fwaas() {
+    neutron_fwaas_configure_common
+    neutron_fwaas_configure_driver
+}
+
 function _configure_neutron_vpn()
 {
     neutron_vpn_install_agent_packages
@@ -690,11 +721,16 @@
     local section=$2
     local use_auth_url=$3
     local skip_auth_cache=$4
+    local use_service_port=$5
+    local keystone_port=$KEYSTONE_AUTH_PORT
+    if [[ -n $use_service_port ]]; then
+        keystone_port=$KEYSTONE_SERVICE_PORT
+    fi
     if [[ -n $use_auth_url ]]; then
-        iniset $conf_file $section auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT/v2.0"
+        iniset $conf_file $section auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_AUTH_HOST:$keystone_port/v2.0"
     else
         iniset $conf_file $section auth_host $KEYSTONE_SERVICE_HOST
-        iniset $conf_file $section auth_port $KEYSTONE_AUTH_PORT
+        iniset $conf_file $section auth_port $keystone_port
         iniset $conf_file $section auth_protocol $KEYSTONE_SERVICE_PROTOCOL
     fi
     iniset $conf_file $section admin_tenant_name $SERVICE_TENANT_NAME
diff --git a/lib/neutron_plugins/services/firewall b/lib/neutron_plugins/services/firewall
new file mode 100644
index 0000000..1597e85
--- /dev/null
+++ b/lib/neutron_plugins/services/firewall
@@ -0,0 +1,27 @@
+# Neutron firewall plugin
+# ---------------------------
+
+# Save trace setting
+MY_XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+FWAAS_PLUGIN=neutron.services.firewall.fwaas_plugin.FirewallPlugin
+
+function neutron_fwaas_configure_common() {
+    if [[ $Q_SERVICE_PLUGIN_CLASSES == '' ]]; then
+        Q_SERVICE_PLUGIN_CLASSES=$FWAAS_PLUGIN
+    else
+        Q_SERVICE_PLUGIN_CLASSES="$Q_SERVICE_PLUGIN_CLASSES,$FWAAS_PLUGIN"
+    fi
+}
+
+function neutron_fwaas_configure_driver() {
+    FWAAS_DRIVER_CONF_FILENAME=/etc/neutron/fwaas_driver.ini
+    cp $NEUTRON_DIR/etc/fwaas_driver.ini $FWAAS_DRIVER_CONF_FILENAME
+
+    iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas enabled True
+    iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas driver "neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver"
+}
+
+# Restore xtrace
+$MY_XTRACE
diff --git a/lib/nova b/lib/nova
index 3486aa8..0b65f84 100644
--- a/lib/nova
+++ b/lib/nova
@@ -458,6 +458,7 @@
     if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then
         iniset $NOVA_CONF DEFAULT libvirt_type "$LIBVIRT_TYPE"
         iniset $NOVA_CONF DEFAULT libvirt_cpu_mode "none"
+        iniset $NOVA_CONF DEFAULT use_usb_tablet "False"
     fi
     iniset $NOVA_CONF DEFAULT instance_name_template "${INSTANCE_NAME_PREFIX}%08x"
     iniset $NOVA_CONF osapi_v3 enabled "True"
@@ -652,6 +653,7 @@
 function install_novaclient() {
     git_clone $NOVACLIENT_REPO $NOVACLIENT_DIR $NOVACLIENT_BRANCH
     setup_develop $NOVACLIENT_DIR
+    sudo install -D -m 0644 -o $STACK_USER {$NOVACLIENT_DIR/tools/,/etc/bash_completion.d/}nova.bash_completion
 }
 
 # install_nova() - Collect source and prepare
@@ -691,6 +693,7 @@
 
     git_clone $NOVA_REPO $NOVA_DIR $NOVA_BRANCH
     setup_develop $NOVA_DIR
+    sudo install -D -m 0644 -o $STACK_USER {$NOVA_DIR/tools/,/etc/bash_completion.d/}nova-manage.bash_completion
 }
 
 # start_nova_api() - Start the API process ahead of other things
diff --git a/lib/oslo b/lib/oslo
index 449c4de..f77a4fa 100644
--- a/lib/oslo
+++ b/lib/oslo
@@ -40,12 +40,12 @@
 
 # cleanup_oslo() - purge possibly old versions of oslo
 function cleanup_oslo() {
-    # this means we've got an old olso installed, lets get rid of it
+    # this means we've got an old oslo installed, lets get rid of it
     if ! python -c 'import oslo.config' 2>/dev/null; then
         echo "Found old oslo.config... removing to ensure consistency"
         local PIP_CMD=$(get_pip_command)
-        pip_install olso.config
-        sudo $PIP_CMD uninstall -y olso.config
+        pip_install oslo.config
+        sudo $PIP_CMD uninstall -y oslo.config
     fi
 }
 
diff --git a/lib/tempest b/lib/tempest
index 0d4f370..50289b6 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -282,6 +282,9 @@
     # Scenario
     iniset $TEMPEST_CONF scenario img_dir "$FILES/images/cirros-0.3.1-x86_64-uec"
 
+    # Large Ops Number
+    iniset $TEMPEST_CONF scenario large_ops_number ${TEMPEST_LARGE_OPS_NUMBER:-0}
+
     # Volume
     CINDER_MULTI_LVM_BACKEND=$(trueorfalse False $CINDER_MULTI_LVM_BACKEND)
     if [ $CINDER_MULTI_LVM_BACKEND == "True" ]; then
diff --git a/openrc b/openrc
index a23c6e9..3de7e39 100644
--- a/openrc
+++ b/openrc
@@ -63,21 +63,19 @@
 # should be listening on HOST_IP.  If its running elsewhere, it can be set here
 GLANCE_HOST=${GLANCE_HOST:-$HOST_IP}
 
+# Identity API version
+export OS_IDENTITY_API_VERSION=${IDENTITY_API_VERSION:-2.0}
+
 # Authenticating against an Openstack cloud using Keystone returns a **Token**
 # and **Service Catalog**.  The catalog contains the endpoints for all services
 # the user/tenant has access to - including nova, glance, keystone, swift, ...
 # We currently recommend using the 2.0 *identity api*.
 #
-# *NOTE*: Using the 2.0 *identity api* does not mean that compute api is 2.0.  We
-# will use the 1.1 *compute api*
-export OS_AUTH_URL=$SERVICE_PROTOCOL://$SERVICE_HOST:5000/v2.0
+export OS_AUTH_URL=$SERVICE_PROTOCOL://$SERVICE_HOST:5000/v${OS_IDENTITY_API_VERSION}
 
 # Set the pointer to our CA certificate chain.  Harmless if TLS is not used.
 export OS_CACERT=$INT_CA_DIR/ca-chain.pem
 
-# Identity API version
-export OS_IDENTITY_API_VERSION=${IDENTITY_API_VERSION:-2.0}
-
 # Currently novaclient needs you to specify the *compute api* version.  This
 # needs to match the config of your catalog returned by Keystone.
 export NOVA_VERSION=${NOVA_VERSION:-1.1}
diff --git a/stackrc b/stackrc
index c81906a..8b97536 100644
--- a/stackrc
+++ b/stackrc
@@ -275,6 +275,9 @@
 # Set default screen name
 SCREEN_NAME=${SCREEN_NAME:-stack}
 
+# Do not install packages tagged with 'testonly' by default
+INSTALL_TESTONLY_PACKAGES=${INSTALL_TESTONLY_PACKAGES:-False}
+
 # Local variables:
 # mode: shell-script
 # End:
diff --git a/tests/functions.sh b/tests/functions.sh
index 27a6cfe..7d486d4 100755
--- a/tests/functions.sh
+++ b/tests/functions.sh
@@ -367,3 +367,25 @@
 else
     echo "is_package_installed() on non-existing package failed"
 fi
+
+# test against removed package...was a bug on Ubuntu
+if is_ubuntu; then
+    PKG=cowsay
+    if ! (dpkg -s $PKG >/dev/null 2>&1); then
+        # it was never installed...set up the condition
+        sudo apt-get install -y cowsay >/dev/null 2>&1
+    fi
+    if (dpkg -s $PKG >/dev/null 2>&1); then
+        # remove it to create the 'un' status
+        sudo dpkg -P $PKG >/dev/null 2>&1
+    fi
+
+    # now test the installed check on a deleted package
+    is_package_installed $PKG
+    VAL=$?
+    if [[ "$VAL" -ne 0 ]]; then
+        echo "OK"
+    else
+        echo "is_package_installed() on deleted package failed"
+    fi
+fi