Merge "misleading source filename in error message"
diff --git a/README.md b/README.md
index 3a47fc3..8ae4231 100644
--- a/README.md
+++ b/README.md
@@ -83,6 +83,13 @@
 
     ENABLED_SERVICES="$ENABLED_SERVICES,-rabbit,-zeromq,qpid"
 
+# Apache Frontend
+
+Apache web server is enabled for wsgi services by setting `APACHE_ENABLED_SERVICES` in your localrc. But remember to enable these services at first as above.
+
+Example:
+    APACHE_ENABLED_SERVICES+=keystone,swift
+
 # Swift
 
 Swift is disabled by default.  When enabled, it is configured with
@@ -179,7 +186,7 @@
 If tempest has been successfully configured, a basic set of smoke tests can be run as follows:
 
     $ cd /opt/stack/tempest
-    $ nosetests tempest/tests/network/test_network_basic_ops.py
+    $ nosetests tempest/scenario/test_network_basic_ops.py
 
 # Multi-Node Setup
 
diff --git a/exercises/euca.sh b/exercises/euca.sh
index 5b0d1ba..b8b283a 100755
--- a/exercises/euca.sh
+++ b/exercises/euca.sh
@@ -129,7 +129,8 @@
     # Allocate floating address
     FLOATING_IP=`euca-allocate-address | cut -f2`
     die_if_not_set $LINENO FLOATING_IP "Failure allocating floating IP"
-
+    # describe all instances at this moment
+    euca-describe-instances
     # Associate floating address
     euca-associate-address -i $INSTANCE $FLOATING_IP || \
         die $LINENO "Failure associating address $FLOATING_IP to $INSTANCE"
diff --git a/files/apts/general b/files/apts/general
index ec6dd0d..fcf0b5b 100644
--- a/files/apts/general
+++ b/files/apts/general
@@ -1,6 +1,6 @@
 bridge-utils
 pylint
-python-pip
+python-setuptools
 screen
 unzip
 wget
@@ -20,4 +20,3 @@
 euca2ools # only for testing client
 tar
 python-cmd2 # dist:precise
-python-netaddr
diff --git a/files/apts/horizon b/files/apts/horizon
index e1ce85f..0865931 100644
--- a/files/apts/horizon
+++ b/files/apts/horizon
@@ -21,4 +21,3 @@
 python-migrate
 nodejs
 nodejs-legacy # dist:quantal
-python-netaddr
diff --git a/files/apts/keystone b/files/apts/keystone
index c98409f..564921b 100644
--- a/files/apts/keystone
+++ b/files/apts/keystone
@@ -1,4 +1,3 @@
-python-setuptools
 python-dev
 python-lxml
 python-pastescript
diff --git a/files/apts/neutron b/files/apts/neutron
index 64fc1bf..0f4b69f 100644
--- a/files/apts/neutron
+++ b/files/apts/neutron
@@ -9,7 +9,6 @@
 python-paste
 python-routes
 python-suds
-python-netaddr
 python-pastedeploy
 python-greenlet
 python-kombu
diff --git a/files/apts/nova b/files/apts/nova
index 6a7ef74..ae925c3 100644
--- a/files/apts/nova
+++ b/files/apts/nova
@@ -30,7 +30,6 @@
 python-libvirt # NOPRIME
 python-libxml2
 python-routes
-python-netaddr
 python-numpy # used by websockify for spice console
 python-pastedeploy
 python-eventlet
diff --git a/files/apts/ryu b/files/apts/ryu
index 4a4fc52..e8ed926 100644
--- a/files/apts/ryu
+++ b/files/apts/ryu
@@ -1,4 +1,3 @@
-python-setuptools
 python-gevent
 python-gflags
 python-netifaces
diff --git a/files/apts/swift b/files/apts/swift
index 1c283cf..37d5bc0 100644
--- a/files/apts/swift
+++ b/files/apts/swift
@@ -10,7 +10,6 @@
 python-netifaces
 python-nose
 python-pastedeploy
-python-setuptools
 python-simplejson
 python-webob
 python-xattr
diff --git a/files/rpms-suse/general b/files/rpms-suse/general
index 93711ff..355af88 100644
--- a/files/rpms-suse/general
+++ b/files/rpms-suse/general
@@ -6,9 +6,8 @@
 openssh
 openssl
 psmisc
+python-setuptools # instead of python-distribute; dist:sle11sp2
 python-cmd2 # dist:opensuse-12.3
-python-netaddr
-python-pip
 python-pylint
 python-unittest2
 python-virtualenv
diff --git a/files/rpms-suse/horizon b/files/rpms-suse/horizon
index 405fb7a..73932ac 100644
--- a/files/rpms-suse/horizon
+++ b/files/rpms-suse/horizon
@@ -15,7 +15,6 @@
 python-eventlet
 python-kombu
 python-mox
-python-netaddr
 python-nose
 python-pylint
 python-sqlalchemy-migrate
diff --git a/files/rpms-suse/keystone b/files/rpms-suse/keystone
index 7d9a7bf..403d82f 100644
--- a/files/rpms-suse/keystone
+++ b/files/rpms-suse/keystone
@@ -7,8 +7,6 @@
 python-SQLAlchemy
 python-WebOb
 python-devel
-python-distribute
-python-setuptools # instead of python-distribute; dist:sle11sp2
 python-greenlet
 python-lxml
 python-mysql
diff --git a/files/rpms-suse/neutron b/files/rpms-suse/neutron
index aadb156..e9ccf59 100644
--- a/files/rpms-suse/neutron
+++ b/files/rpms-suse/neutron
@@ -10,7 +10,6 @@
 python-iso8601
 python-kombu
 python-mysql
-python-netaddr
 python-Paste
 python-PasteDeploy
 python-pyudev
diff --git a/files/rpms-suse/nova b/files/rpms-suse/nova
index edb1a8a..ee4917d 100644
--- a/files/rpms-suse/nova
+++ b/files/rpms-suse/nova
@@ -35,7 +35,6 @@
 python-lxml # needed for glance which is needed for nova --- this shouldn't be here
 python-mox
 python-mysql
-python-netaddr
 python-numpy # needed by websockify for spice console
 python-paramiko
 python-python-gflags
diff --git a/files/rpms-suse/ryu b/files/rpms-suse/ryu
index 90b43a4..3797b6c 100644
--- a/files/rpms-suse/ryu
+++ b/files/rpms-suse/ryu
@@ -1,5 +1,3 @@
-python-distribute
-python-setuptools # instead of python-distribute; dist:sle11sp2
 python-Sphinx
 python-gevent
 python-netifaces
diff --git a/files/rpms-suse/swift b/files/rpms-suse/swift
index db379bb..f3c95aa 100644
--- a/files/rpms-suse/swift
+++ b/files/rpms-suse/swift
@@ -6,8 +6,6 @@
 python-configobj
 python-coverage
 python-devel
-python-distribute
-python-setuptools # instead of python-distribute; dist:sle11sp2
 python-eventlet
 python-greenlet
 python-netifaces
diff --git a/files/rpms/general b/files/rpms/general
index 5cb3e28..2db31d1 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -11,8 +11,7 @@
 libxslt-devel # dist:rhel6 [2]
 psmisc
 pylint
-python-netaddr
-python-pip
+python-setuptools
 python-prettytable # dist:rhel6 [1]
 python-unittest2
 python-virtualenv
diff --git a/files/rpms/horizon b/files/rpms/horizon
index b844d98..0ca18ca 100644
--- a/files/rpms/horizon
+++ b/files/rpms/horizon
@@ -16,7 +16,6 @@
 python-kombu
 python-migrate
 python-mox
-python-netaddr
 python-nose
 python-paste        #dist:f16,f17,f18,f19
 python-paste-deploy #dist:f16,f17,f18,f19
diff --git a/files/rpms/keystone b/files/rpms/keystone
index 33a4f47..52dbf47 100644
--- a/files/rpms/keystone
+++ b/files/rpms/keystone
@@ -4,10 +4,9 @@
 python-paste-deploy #dist:f16,f17,f18,f19
 python-paste-script #dist:f16,f17,f18,f19
 python-routes
-python-setuptools   #dist:f16,f17,f18,f19
 python-sqlalchemy
 python-sqlite2
 python-webob
 sqlite
 
-# Deps installed via pip for RHEL
\ No newline at end of file
+# Deps installed via pip for RHEL
diff --git a/files/rpms/neutron b/files/rpms/neutron
index 6a8fd36..a7700f7 100644
--- a/files/rpms/neutron
+++ b/files/rpms/neutron
@@ -10,7 +10,6 @@
 python-greenlet
 python-iso8601
 python-kombu
-python-netaddr
 #rhel6 gets via pip
 python-paste        # dist:f16,f17,f18,f19
 python-paste-deploy # dist:f16,f17,f18,f19
diff --git a/files/rpms/nova b/files/rpms/nova
index 8d8a0b8..c99f3de 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -28,7 +28,6 @@
 python-lockfile
 python-migrate
 python-mox
-python-netaddr
 python-paramiko # dist:f16,f17,f18,f19
 # ^ on RHEL, brings in python-crypto which conflicts with version from
 # pip we need
diff --git a/files/rpms/ryu b/files/rpms/ryu
index 0f62f9f..e8ed926 100644
--- a/files/rpms/ryu
+++ b/files/rpms/ryu
@@ -1,5 +1,4 @@
 python-gevent
 python-gflags
 python-netifaces
-python-setuptools #dist:f16,f17,f18,f19
 python-sphinx
diff --git a/files/rpms/swift b/files/rpms/swift
index 2cc4a0b..b137f30 100644
--- a/files/rpms/swift
+++ b/files/rpms/swift
@@ -10,7 +10,6 @@
 python-netifaces
 python-nose
 python-paste-deploy # dist:f16,f17,f18,f19
-python-setuptools   # dist:f16,f17,f18,f19
 python-simplejson
 python-webob
 pyxattr
diff --git a/functions b/functions
index 43ff1a7..e9c6061 100644
--- a/functions
+++ b/functions
@@ -76,6 +76,19 @@
 }
 
 
+# Prints backtrace info
+# filename:lineno:function
+function backtrace {
+    local level=$1
+    local deep=$((${#BASH_SOURCE[@]} - 1))
+    echo "[Call Trace]"
+    while [ $level -le $deep ]; do
+        echo "${BASH_SOURCE[$deep]}:${BASH_LINENO[$deep-1]}:${FUNCNAME[$deep-1]}"
+        deep=$((deep - 1))
+    done
+}
+
+
 # Prints line number and "message" then exits
 # die $LINENO "message"
 function die() {
@@ -85,6 +98,7 @@
     if [ $exitcode == 0 ]; then
         exitcode=1
     fi
+    backtrace 2
     err $line "$*"
     exit $exitcode
 }
@@ -930,7 +944,7 @@
         CMD_PIP=$(get_pip_command)
     fi
 
-    if [[ is_fedora && $DISTRO =~ (rhel6) ]]; then
+    if is_fedora && [[ $DISTRO =~ (rhel6) ]]; then
         # RHEL6 pip by default doesn't have this (was introduced
         # around 0.8.1 or so)
         PIP_USE_MIRRORS=${PIP_USE_MIRRORS:-False}
@@ -1116,7 +1130,7 @@
 
     for service in $failures; do
         service=`basename $service`
-        service=${service::-8}
+        service=${service%.failure}
         echo "Error: Service $service is not running"
     done
 
@@ -1126,29 +1140,29 @@
 }
 
 
-# ``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`
+# ``pip install -e`` the package, which processes the dependencies
+# using pip before running `setup.py develop`
+# Uses globals ``STACK_USER``, ``TRACK_DEPENDS``, ``REQUIREMENTS_DIR``
 # setup_develop directory
 function setup_develop() {
+    local project_dir=$1
     if [[ $TRACK_DEPENDS = True ]]; then
         SUDO_CMD="env"
     else
         SUDO_CMD="sudo"
     fi
-    for reqs_file in $1/requirements.txt $1/tools/pip-requires ; do
-        if [ -f $reqs_file ] ; then
-            pip_install -r $reqs_file
-        fi
-    done
-    (cd $1; \
-        python setup.py egg_info; \
-        $SUDO_CMD \
-            HTTP_PROXY=$http_proxy \
-            HTTPS_PROXY=$https_proxy \
-            NO_PROXY=$no_proxy \
-            python setup.py develop \
-    )
+
+    echo "cd $REQUIREMENTS_DIR; $SUDO_CMD python update.py $project_dir"
+
+    # Don't update repo if local changes exist
+    if (cd $project_dir && git diff --quiet); then
+        (cd $REQUIREMENTS_DIR; \
+            $SUDO_CMD python update.py $project_dir)
+    fi
+
+    pip_install -e $project_dir
+    # ensure that further actions can do things like setup.py sdist
+    $SUDO_CMD chown -R $STACK_USER $1/*.egg-info
 }
 
 
diff --git a/lib/apache b/lib/apache
new file mode 100644
index 0000000..a2b0534
--- /dev/null
+++ b/lib/apache
@@ -0,0 +1,118 @@
+# lib/apache
+# Functions to control configuration and operation of apache web server
+
+# Dependencies:
+# ``functions`` file
+# is_apache_enabled_service
+# change_apache_user_group
+# install_apache_wsgi
+# config_apache_wsgi
+# start_apache_server
+# stop_apache_server
+# restart_apache_server
+
+# Save trace setting
+XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+# Allow overriding the default Apache user and group, default to
+# current user and his default group.
+APACHE_USER=${APACHE_USER:-$USER}
+APACHE_GROUP=${APACHE_GROUP:-$(id -gn $APACHE_USER)}
+
+
+# Set up apache name and configuration directory
+if is_ubuntu; then
+    APACHE_NAME=apache2
+    APACHE_CONF_DIR=sites-available
+elif is_fedora; then
+    APACHE_NAME=httpd
+    APACHE_CONF_DIR=conf.d
+elif is_suse; then
+    APACHE_NAME=apache2
+    APACHE_CONF_DIR=vhosts.d
+fi
+
+# Functions
+# ---------
+
+# is_apache_enabled_service() checks if the service(s) specified as arguments are
+# apache enabled by the user in ``APACHE_ENABLED_SERVICES`` as web front end.
+#
+# Multiple services specified as arguments are ``OR``'ed together; the test
+# is a short-circuit boolean, i.e it returns on the first match.
+#
+# Uses global ``APACHE_ENABLED_SERVICES``
+# APACHE_ENABLED_SERVICES service [service ...]
+function is_apache_enabled_service() {
+    services=$@
+    for service in ${services}; do
+        [[ ,${APACHE_ENABLED_SERVICES}, =~ ,${service}, ]] && return 0
+    done
+    return 1
+}
+
+# change_apache_user_group() - Change the User/Group to run Apache server
+function change_apache_user_group(){
+    local stack_user=$@
+    if is_ubuntu; then
+        sudo sed -e "
+            s/^export APACHE_RUN_USER=.*/export APACHE_RUN_USER=${stack_user}/g;
+            s/^export APACHE_RUN_GROUP=.*/export APACHE_RUN_GROUP=${stack_user}/g
+        " -i /etc/${APACHE_NAME}/envvars
+    elif is_fedora; then
+        sudo sed -e "
+            s/^User .*/User ${stack_user}/g;
+            s/^Group .*/Group ${stack_user}/g
+        " -i /etc/${APACHE_NAME}/httpd.conf
+    elif is_suse; then
+        sudo sed -e "
+            s/^User .*/User ${stack_user}/g;
+            s/^Group .*/Group ${stack_user}/g
+        " -i /etc/${APACHE_NAME}/uid.conf
+    else
+        exit_distro_not_supported "apache user and group"
+    fi
+}
+
+# install_apache_wsgi() - Install Apache server and wsgi module
+function install_apache_wsgi() {
+    # Apache installation, because we mark it NOPRIME
+    if is_ubuntu; then
+        # Install apache2, which is NOPRIME'd
+        install_package apache2 libapache2-mod-wsgi
+    elif is_fedora; then
+        sudo rm -f /etc/httpd/conf.d/000-*
+        install_package httpd mod_wsgi
+    elif is_suse; then
+        install_package apache2 apache2-mod_wsgi
+    else
+        exit_distro_not_supported "apache installation"
+    fi
+}
+
+# start_apache_server() - Start running apache server
+function start_apache_server() {
+    start_service $APACHE_NAME
+}
+
+# stop_apache_server() - Stop running apache server
+function stop_apache_server() {
+    if [ -n "$APACHE_NAME" ]; then
+        stop_service $APACHE_NAME
+    else
+        exit_distro_not_supported "apache configuration"
+    fi
+}
+
+# restart_apache_server
+function restart_apache_server() {
+    restart_service $APACHE_NAME
+}
+
+# Restore xtrace
+$XTRACE
+
+# Local variables:
+# mode: shell-script
+# End:
diff --git a/lib/baremetal b/lib/baremetal
index 145544d..8f6c3f1 100644
--- a/lib/baremetal
+++ b/lib/baremetal
@@ -138,9 +138,12 @@
 BM_IMAGE_BUILD_DIR=${BM_IMAGE_BUILD_DIR:-$DEST/diskimage-builder}
 BM_POSEUR_DIR=${BM_POSEUR_DIR:-$DEST/bm_poseur}
 
-BM_HOST_CURRENT_KERNEL=$(uname -r)
-BM_DEPLOY_RAMDISK=${BM_DEPLOY_RAMDISK:-bm-deploy-$BM_HOST_CURRENT_KERNEL-initrd}
-BM_DEPLOY_KERNEL=${BM_DEPLOY_KERNEL:-bm-deploy-$BM_HOST_CURRENT_KERNEL-vmlinuz}
+# Use DIB to create deploy ramdisk and kernel.
+BM_BUILD_DEPLOY_RAMDISK=`trueorfalse True $BM_BUILD_DEPLOY_RAMDISK`
+# If not use DIB, these files are used as deploy ramdisk/kernel.
+# (The value must be a relative path from $TOP_DIR/files/)
+BM_DEPLOY_RAMDISK=${BM_DEPLOY_RAMDISK:-}
+BM_DEPLOY_KERNEL=${BM_DEPLOY_KERNEL:-}
 
 # If you need to add any extra flavors to the deploy ramdisk image
 # eg, specific network drivers, specify them here
@@ -233,13 +236,13 @@
 function upload_baremetal_deploy() {
     token=$1
 
-    if [ ! -e $TOP_DIR/files/$BM_DEPLOY_KERNEL -a -e /boot/vmlinuz-$BM_HOST_CURRENT_KERNEL ]; then
-        sudo cp /boot/vmlinuz-$BM_HOST_CURRENT_KERNEL $TOP_DIR/files/$BM_DEPLOY_KERNEL
-        sudo chmod a+r $TOP_DIR/files/$BM_DEPLOY_KERNEL
-    fi
-    if [ ! -e $TOP_DIR/files/$BM_DEPLOY_RAMDISK ]; then
-       $BM_IMAGE_BUILD_DIR/bin/ramdisk-image-create $BM_DEPLOY_FLAVOR deploy \
-           -o $TOP_DIR/files/$BM_DEPLOY_RAMDISK -k $BM_HOST_CURRENT_KERNEL
+    if [ "$BM_BUILD_DEPLOY_RAMDISK" = "True" ]; then
+        BM_DEPLOY_KERNEL=bm-deploy.kernel
+        BM_DEPLOY_RAMDISK=bm-deploy.initramfs
+        if [ ! -e "$TOP_DIR/files/$BM_DEPLOY_KERNEL" -o ! -e "$TOP_DIR/files/$BM_DEPLOY_RAMDISK" ]; then
+            $BM_IMAGE_BUILD_DIR/bin/ramdisk-image-create $BM_DEPLOY_FLAVOR deploy \
+                -o $TOP_DIR/files/bm-deploy
+        fi
     fi
 
     # load them into glance
diff --git a/lib/cinder b/lib/cinder
index ef7e3dc..3472dcd 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -296,6 +296,10 @@
             -e 's/snapshot_autoextend_percent =.*/snapshot_autoextend_percent = 20/' \
             /etc/lvm/lvm.conf
     fi
+    iniset $CINDER_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT
+    iniset $CINDER_CONF keystone_authtoken admin_user cinder
+    iniset $CINDER_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
+    iniset $CINDER_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
 
 }
 
diff --git a/lib/horizon b/lib/horizon
index f88247c..89bd659 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -4,6 +4,7 @@
 
 # Dependencies:
 # ``functions`` file
+# ``apache`` file
 # ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
 # <list other global vars that are assumed to be defined>
 
@@ -33,23 +34,6 @@
 # The example file in Horizon repo is used by default.
 HORIZON_SETTINGS=${HORIZON_SETTINGS:-$HORIZON_DIR/openstack_dashboard/local/local_settings.py.example}
 
-# Allow overriding the default Apache user and group, default to
-# current user and his default group.
-APACHE_USER=${APACHE_USER:-$USER}
-APACHE_GROUP=${APACHE_GROUP:-$(id -gn $APACHE_USER)}
-
-# Set up service name and configuration path
-if is_ubuntu; then
-    APACHE_NAME=apache2
-    APACHE_CONF=sites-available/horizon
-elif is_fedora; then
-    APACHE_NAME=httpd
-    APACHE_CONF=conf.d/horizon.conf
-elif is_suse; then
-    APACHE_NAME=apache2
-    APACHE_CONF=vhosts.d/horizon.conf
-fi
-
 
 # Functions
 # ---------
@@ -122,11 +106,12 @@
     sudo mkdir -p $HORIZON_DIR/.blackhole
 
     HORIZON_REQUIRE=''
+    local horizon_conf=/etc/$APACHE_NAME/$APACHE_CONF_DIR/horizon
     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 /etc/$APACHE_NAME/$APACHE_CONF
+        sudo touch $horizon_conf
         sudo a2ensite horizon
         # WSGI isn't enabled by default, enable it
         sudo a2enmod wsgi
@@ -156,23 +141,13 @@
         s,%APACHE_NAME%,$APACHE_NAME,g;
         s,%DEST%,$DEST,g;
         s,%HORIZON_REQUIRE%,$HORIZON_REQUIRE,g;
-    \" $FILES/apache-horizon.template >/etc/$APACHE_NAME/$APACHE_CONF"
+    \" $FILES/apache-horizon.template >$horizon_conf"
 }
 
 # install_horizon() - Collect source and prepare
 function install_horizon() {
     # Apache installation, because we mark it NOPRIME
-    if is_ubuntu; then
-        # Install apache2, which is NOPRIME'd
-        install_package apache2 libapache2-mod-wsgi
-    elif is_fedora; then
-        sudo rm -f /etc/httpd/conf.d/000-*
-        install_package httpd mod_wsgi
-    elif is_suse; then
-        install_package apache2 apache2-mod_wsgi
-    else
-        exit_distro_not_supported "apache installation"
-    fi
+    install_apache_wsgi
 
     # NOTE(sdague) quantal changed the name of the node binary
     if is_ubuntu; then
@@ -188,17 +163,13 @@
 
 # start_horizon() - Start running processes, including screen
 function start_horizon() {
-    restart_service $APACHE_NAME
+    restart_apache_server
     screen_it horizon "cd $HORIZON_DIR && sudo tail -f /var/log/$APACHE_NAME/horizon_error.log"
 }
 
 # stop_horizon() - Stop running processes (non-screen)
 function stop_horizon() {
-    if [ -n "$APACHE_NAME" ]; then
-        stop_service $APACHE_NAME
-    else
-        exit_distro_not_supported "apache configuration"
-    fi
+    stop_apache_server
 }
 
 
diff --git a/lib/neutron b/lib/neutron
index 835f900..c546f37 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -367,7 +367,9 @@
 
 # init_neutron() - Initialize databases, etc.
 function init_neutron() {
-    :
+    recreate_database $Q_DB_NAME utf8
+    # Run Neutron db migrations
+    $NEUTRON_BIN_DIR/neutron-db-manage --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE upgrade head
 }
 
 # install_neutron() - Collect source and prepare
@@ -614,12 +616,6 @@
     cp $NEUTRON_DIR/etc/api-paste.ini $Q_API_PASTE_FILE
     cp $NEUTRON_DIR/etc/policy.json $Q_POLICY_FILE
 
-    if is_service_enabled $DATABASE_BACKENDS; then
-        recreate_database $Q_DB_NAME utf8
-    else
-        die $LINENO "A database must be enabled in order to use the $Q_PLUGIN Neutron plugin."
-    fi
-
     # Update either configuration file with plugin
     iniset $NEUTRON_CONF DEFAULT core_plugin $Q_PLUGIN_CLASS
 
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index ff49d8e..00bd716 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -20,7 +20,7 @@
 source $TOP_DIR/lib/neutron_plugins/${Q_AGENT}_agent
 
 # List of MechanismDrivers to load
-Q_ML2_PLUGIN_MECHANISM_DRIVERS=${Q_PLUGIN_MECHANISM_DRIVERS:-}
+Q_ML2_PLUGIN_MECHANISM_DRIVERS=${Q_ML2_PLUGIN_MECHANISM_DRIVERS:-}
 # List of Type Drivers to load
 Q_ML2_PLUGIN_TYPE_DRIVERS=${Q_ML2_PLUGIN_TYPE_DRIVERS:-local,flat,vlan,gre,vxlan}
 # Default GRE TypeDriver options
@@ -92,6 +92,8 @@
     # Since we enable the tunnel TypeDrivers, also enable a local_ip
     iniset /$Q_PLUGIN_CONF_FILE ovs local_ip $HOST_IP
 
+    populate_ml2_config mechanism_drivers=$Q_ML2_PLUGIN_MECHANISM_DRIVERS /$Q_PLUGIN_CONF_FILE ml2
+
     populate_ml2_config type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS /$Q_PLUGIN_CONF_FILE ml2
 
     populate_ml2_config $Q_SRV_EXTRA_OPTS /$Q_PLUGIN_CONF_FILE ml2
diff --git a/lib/neutron_plugins/plumgrid b/lib/neutron_plugins/plumgrid
index a4f0b0d..9d3c92f 100644
--- a/lib/neutron_plugins/plumgrid
+++ b/lib/neutron_plugins/plumgrid
@@ -21,7 +21,7 @@
     Q_PLUGIN_CONF_PATH=etc/neutron/plugins/plumgrid
     Q_PLUGIN_CONF_FILENAME=plumgrid.ini
     Q_DB_NAME="plumgrid_neutron"
-    Q_PLUGIN_CLASS="neutron.plugins.plumgrid.plumgrid_nos_plugin.plumgrid_plugin.NeutronPluginPLUMgridV2"
+    Q_PLUGIN_CLASS="neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin.NeutronPluginPLUMgridV2"
     PLUMGRID_DIRECTOR_IP=${PLUMGRID_DIRECTOR_IP:-localhost}
     PLUMGRID_DIRECTOR_PORT=${PLUMGRID_DIRECTOR_PORT:-7766}
 }
@@ -35,6 +35,16 @@
     :
 }
 
+function is_neutron_ovs_base_plugin() {
+    # False
+    return 1
+}
+
+function has_neutron_plugin_security_group() {
+    # False
+    return 1
+}
+
 function neutron_plugin_check_adv_test_requirements() {
     is_service_enabled q-agt && is_service_enabled q-dhcp && return 0
 }
diff --git a/lib/nova b/lib/nova
index 7a5ff1f..9c38498 100644
--- a/lib/nova
+++ b/lib/nova
@@ -722,6 +722,11 @@
         # The group **$LIBVIRT_GROUP** is added to the current user in this script.
         # Use 'sg' to execute nova-compute as a member of the **$LIBVIRT_GROUP** group.
         screen_it n-cpu "cd $NOVA_DIR && sg $LIBVIRT_GROUP '$NOVA_BIN_DIR/nova-compute --config-file $NOVA_CONF_BOTTOM'"
+    elif [[ "$VIRT_DRIVER" = 'fake' ]]; then
+       for i in `seq 1 $NUMBER_FAKE_NOVA_COMPUTE`
+       do
+           screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $NOVA_CONF_BOTTOM"
+       done
     else
         screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $NOVA_CONF_BOTTOM"
     fi
diff --git a/lib/swift b/lib/swift
index e53d674..8e64152 100644
--- a/lib/swift
+++ b/lib/swift
@@ -3,6 +3,7 @@
 
 # Dependencies:
 # ``functions`` file
+# ``apache`` file
 # ``DEST``, ``SCREEN_NAME``, `SWIFT_HASH` must be defined
 # ``STACK_USER`` must be defined
 # ``SWIFT_DATA_DIR`` or ``DATA_DIR`` must be defined
@@ -10,11 +11,13 @@
 # ``stack.sh`` calls the entry points in this order:
 #
 # install_swift
+# _config_swift_apache_wsgi
 # configure_swift
 # init_swift
 # start_swift
 # stop_swift
 # cleanup_swift
+# _cleanup_swift_apache_wsgi
 
 # Save trace setting
 XTRACE=$(set +o | grep xtrace)
@@ -28,6 +31,7 @@
 SWIFT_DIR=$DEST/swift
 SWIFTCLIENT_DIR=$DEST/python-swiftclient
 SWIFT_AUTH_CACHE_DIR=${SWIFT_AUTH_CACHE_DIR:-/var/cache/swift}
+SWIFT_APACHE_WSGI_DIR=${SWIFT_APACHE_WSGI_DIR:-/var/www/swift}
 SWIFT3_DIR=$DEST/swift3
 
 # TODO: add logging to different location.
@@ -54,8 +58,8 @@
 SWIFT_LOOPBACK_DISK_SIZE=${SWIFT_LOOPBACK_DISK_SIZE:-1000000}
 
 # Set ``SWIFT_EXTRAS_MIDDLEWARE`` to extras middlewares.
-# Default is ``staticweb, tempurl, bulk, formpost``
-SWIFT_EXTRAS_MIDDLEWARE=${SWIFT_EXTRAS_MIDDLEWARE:-tempurl formpost staticweb bulk}
+# Default is ``staticweb, tempurl, formpost``
+SWIFT_EXTRAS_MIDDLEWARE=${SWIFT_EXTRAS_MIDDLEWARE:-tempurl formpost staticweb}
 
 # The ring uses a configurable number of bits from a path’s MD5 hash as
 # a partition index that designates a device. The number of bits kept
@@ -97,6 +101,103 @@
       rm ${SWIFT_DATA_DIR}/drives/images/swift.img
    fi
    rm -rf ${SWIFT_DATA_DIR}/run/
+   if is_apache_enabled_service swift; then
+       _cleanup_swift_apache_wsgi
+   fi
+}
+
+# _cleanup_swift_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
+function _cleanup_swift_apache_wsgi() {
+    sudo rm -f $SWIFT_APACHE_WSGI_DIR/*.wsgi
+    ! is_fedora && sudo a2dissite proxy-server
+    for node_number in ${SWIFT_REPLICAS_SEQ}; do
+        for type in object container account; do
+            site_name=${type}-server-${node_number}
+            ! is_fedora && sudo a2dissite ${site_name}
+            sudo rm -f /etc/$APACHE_NAME/$APACHE_CONF_DIR/${site_name}
+        done
+    done
+}
+
+# _config_swift_apache_wsgi() - Set WSGI config files of Swift
+function _config_swift_apache_wsgi() {
+    sudo mkdir -p ${SWIFT_APACHE_WSGI_DIR}
+    local apache_vhost_dir=/etc/${APACHE_NAME}/$APACHE_CONF_DIR
+    local proxy_port=${SWIFT_DEFAULT_BIND_PORT:-8080}
+
+    # copy proxy vhost and wsgi file
+    sudo cp ${SWIFT_DIR}/examples/apache2/proxy-server.template ${apache_vhost_dir}/proxy-server
+    sudo sed -e "
+        /^#/d;/^$/d;
+        s/%PORT%/$proxy_port/g;
+        s/%SERVICENAME%/proxy-server/g;
+        s/%APACHE_NAME%/${APACHE_NAME}/g;
+    " -i ${apache_vhost_dir}/proxy-server
+
+    sudo cp ${SWIFT_DIR}/examples/wsgi/proxy-server.wsgi.template ${SWIFT_APACHE_WSGI_DIR}/proxy-server.wsgi
+    sudo sed -e "
+        /^#/d;/^$/d;
+        s/%SERVICECONF%/proxy-server.conf/g;
+    " -i ${SWIFT_APACHE_WSGI_DIR}/proxy-server.wsgi
+    ! is_fedora && sudo a2ensite proxy-server
+
+    # copy apache vhost file and set name and port
+    for node_number in ${SWIFT_REPLICAS_SEQ}; do
+        object_port=$[OBJECT_PORT_BASE + 10 * ($node_number - 1)]
+        container_port=$[CONTAINER_PORT_BASE + 10 * ($node_number - 1)]
+        account_port=$[ACCOUNT_PORT_BASE + 10 * ($node_number - 1)]
+
+        sudo cp ${SWIFT_DIR}/examples/apache2/object-server.template ${apache_vhost_dir}/object-server-${node_number}
+        sudo sed -e "
+            s/%PORT%/$object_port/g;
+            s/%SERVICENAME%/object-server-${node_number}/g;
+            s/%APACHE_NAME%/${APACHE_NAME}/g;
+        " -i ${apache_vhost_dir}/object-server-${node_number}
+        ! is_fedora && sudo a2ensite object-server-${node_number}
+
+        sudo cp ${SWIFT_DIR}/examples/wsgi/object-server.wsgi.template ${SWIFT_APACHE_WSGI_DIR}/object-server-${node_number}.wsgi
+        sudo sed -e "
+            /^#/d;/^$/d;
+            s/%SERVICECONF%/object-server\/${node_number}.conf/g;
+        " -i ${SWIFT_APACHE_WSGI_DIR}/object-server-${node_number}.wsgi
+
+        sudo cp ${SWIFT_DIR}/examples/apache2/container-server.template ${apache_vhost_dir}/container-server-${node_number}
+        sudo sed -e "
+            /^#/d;/^$/d;
+            s/%PORT%/$container_port/g;
+            s/%SERVICENAME%/container-server-${node_number}/g;
+            s/%APACHE_NAME%/${APACHE_NAME}/g;
+        " -i ${apache_vhost_dir}/container-server-${node_number}
+        ! is_fedora && sudo a2ensite container-server-${node_number}
+
+        sudo cp ${SWIFT_DIR}/examples/wsgi/container-server.wsgi.template ${SWIFT_APACHE_WSGI_DIR}/container-server-${node_number}.wsgi
+        sudo sed -e "
+            /^#/d;/^$/d;
+            s/%SERVICECONF%/container-server\/${node_number}.conf/g;
+        " -i ${SWIFT_APACHE_WSGI_DIR}/container-server-${node_number}.wsgi
+
+        sudo cp ${SWIFT_DIR}/examples/apache2/account-server.template ${apache_vhost_dir}/account-server-${node_number}
+        sudo sed -e "
+             /^#/d;/^$/d;
+            s/%PORT%/$account_port/g;
+            s/%SERVICENAME%/account-server-${node_number}/g;
+            s/%APACHE_NAME%/${APACHE_NAME}/g;
+        " -i ${apache_vhost_dir}/account-server-${node_number}
+        ! is_fedora && sudo a2ensite account-server-${node_number}
+
+        sudo cp ${SWIFT_DIR}/examples/wsgi/account-server.wsgi.template ${SWIFT_APACHE_WSGI_DIR}/account-server-${node_number}.wsgi
+        sudo sed -e "
+             /^#/d;/^$/d;
+            s/%SERVICECONF%/account-server\/${node_number}.conf/g;
+        " -i ${SWIFT_APACHE_WSGI_DIR}/account-server-${node_number}.wsgi
+
+    done
+
+    # run apache server as stack user
+    change_apache_user_group ${STACK_USER}
+
+    # WSGI isn't enabled by default, enable it
+    ! is_fedora && sudo a2enmod wsgi
 }
 
 # configure_swift() - Set config files, create data dirs and loop image
@@ -288,6 +389,9 @@
     sudo chown -R $USER:adm ${swift_log_dir}
     sed "s,%SWIFT_LOGDIR%,${swift_log_dir}," $FILES/swift/rsyslog.conf | sudo \
         tee /etc/rsyslog.d/10-swift.conf
+    if is_apache_enabled_service swift; then
+        _config_swift_apache_wsgi
+    fi
 }
 
 # create_swift_disk - Create Swift backing disk
@@ -423,6 +527,9 @@
 function install_swift() {
     git_clone $SWIFT_REPO $SWIFT_DIR $SWIFT_BRANCH
     setup_develop $SWIFT_DIR
+    if is_apache_enabled_service swift; then
+        install_apache_wsgi
+    fi
 }
 
 function install_swiftclient() {
@@ -444,6 +551,22 @@
         sudo systemctl start xinetd.service
     fi
 
+    if is_apache_enabled_service swift; then
+        # Make sure the apache lock dir is owned by $STACK_USER
+        # for running apache server to avoid failure of restarting
+        # apache server due to permission problem.
+        sudo chown -R $STACK_USER /var/run/lock/$APACHE_NAME
+        restart_apache_server
+        swift-init --run-dir=${SWIFT_DATA_DIR}/run rest start
+        screen_it s-proxy "cd $SWIFT_DIR && sudo tail -f /var/log/$APACHE_NAME/proxy-server"
+        if [[ ${SWIFT_REPLICAS} == 1 ]]; then
+            for type in object container account; do
+                screen_it s-${type} "cd $SWIFT_DIR && sudo tail -f /var/log/$APACHE_NAME/${type}-server-1"
+            done
+        fi
+        return 0
+    fi
+
    # By default with only one replica we are launching the proxy,
    # container, account and object server in screen in foreground and
    # other services in background. If we have SWIFT_REPLICAS set to something
@@ -460,7 +583,7 @@
    done
    screen_it s-proxy "cd $SWIFT_DIR && $SWIFT_DIR/bin/swift-proxy-server ${SWIFT_CONF_DIR}/proxy-server.conf -v"
    if [[ ${SWIFT_REPLICAS} == 1 ]]; then
-       for type in object container account;do
+       for type in object container account; do
            screen_it s-${type} "cd $SWIFT_DIR && $SWIFT_DIR/bin/swift-${type}-server ${SWIFT_CONF_DIR}/${type}-server/1.conf -v"
        done
    fi
@@ -468,6 +591,11 @@
 
 # stop_swift() - Stop running processes (non-screen)
 function stop_swift() {
+
+    if is_apache_enabled_service swift; then
+        swift-init --run-dir=${SWIFT_DATA_DIR}/run rest stop && return 0
+    fi
+
     # screen normally killed by unstack.sh
     if type -p swift-init >/dev/null; then
         swift-init --run-dir=${SWIFT_DATA_DIR}/run all stop || true
diff --git a/stack.sh b/stack.sh
index c5e306e..22a23c8 100755
--- a/stack.sh
+++ b/stack.sh
@@ -298,6 +298,7 @@
 # ==================
 
 # Source project function libraries
+source $TOP_DIR/lib/apache
 source $TOP_DIR/lib/tls
 source $TOP_DIR/lib/infra
 source $TOP_DIR/lib/oslo
@@ -577,18 +578,8 @@
 echo_summary "Installing package prerequisites"
 source $TOP_DIR/tools/install_prereqs.sh
 
-install_rpc_backend
-
-if is_service_enabled $DATABASE_BACKENDS; then
-    install_database
-fi
-
-if is_service_enabled neutron; then
-    install_neutron_agent_packages
-fi
-
-# Unbreak the giant mess that is the current state of setuptools
-unfubar_setuptools
+# Configure an appropriate python environment
+$TOP_DIR/tools/install_pip.sh
 
 # System-specific preconfigure
 # ============================
@@ -600,23 +591,29 @@
         sudo setenforce 0
     fi
 
-    # An old version of ``python-crypto`` (2.0.1) may be installed on a
-    # fresh system via Anaconda and the dependency chain
-    # ``cas`` -> ``python-paramiko`` -> ``python-crypto``.
-    # ``pip uninstall pycrypto`` will remove the packaged ``.egg-info`` file
-    # but leave most of the actual library files behind in ``/usr/lib64/python2.6/Crypto``.
-    # Later ``pip install pycrypto`` will install over the packaged files resulting
-    # in a useless mess of old, rpm-packaged files and pip-installed files.
-    # Remove the package so that ``pip install python-crypto`` installs cleanly.
-    # Note: other RPM packages may require ``python-crypto`` as well.  For example,
-    # RHEL6 does not install ``python-paramiko packages``.
-    uninstall_package python-crypto
+    # The following workarounds break xenserver
+    if [ "$VIRT_DRIVER" != 'xenserver' ]; then
+        # An old version of ``python-crypto`` (2.0.1) may be installed on a
+        # fresh system via Anaconda and the dependency chain
+        # ``cas`` -> ``python-paramiko`` -> ``python-crypto``.
+        # ``pip uninstall pycrypto`` will remove the packaged ``.egg-info``
+        #  file but leave most of the actual library files behind in
+        # ``/usr/lib64/python2.6/Crypto``. Later ``pip install pycrypto``
+        # will install over the packaged files resulting
+        # in a useless mess of old, rpm-packaged files and pip-installed files.
+        # Remove the package so that ``pip install python-crypto`` installs
+        # cleanly.
+        # Note: other RPM packages may require ``python-crypto`` as well.
+        # For example, RHEL6 does not install ``python-paramiko packages``.
+        uninstall_package python-crypto
 
-    # A similar situation occurs with ``python-lxml``, which is required by
-    # ``ipa-client``, an auditing package we don't care about.  The
-    # build-dependencies needed for ``pip install lxml`` (``gcc``,
-    # ``libxml2-dev`` and ``libxslt-dev``) are present in ``files/rpms/general``.
-    uninstall_package python-lxml
+        # A similar situation occurs with ``python-lxml``, which is required by
+        # ``ipa-client``, an auditing package we don't care about.  The
+        # build-dependencies needed for ``pip install lxml`` (``gcc``,
+        # ``libxml2-dev`` and ``libxslt-dev``) are present in
+        # ``files/rpms/general``.
+        uninstall_package python-lxml
+    fi
 
     # If the ``dbus`` package was installed by DevStack dependencies the
     # uuid may not be generated because the service was never started (PR#598200),
@@ -641,12 +638,22 @@
     sudo ln -sf /usr/bin/nosetests1.1 /usr/local/bin/nosetests
 fi
 
+install_rpc_backend
+
+if is_service_enabled $DATABASE_BACKENDS; then
+    install_database
+fi
+
+if is_service_enabled neutron; then
+    install_neutron_agent_packages
+fi
+
 TRACK_DEPENDS=${TRACK_DEPENDS:-False}
 
 # Install python packages into a virtualenv so that we can track them
 if [[ $TRACK_DEPENDS = True ]]; then
     echo_summary "Installing Python packages into a virtualenv $DEST/.venv"
-    install_package python-virtualenv
+    pip_install -U virtualenv
 
     rm -rf $DEST/.venv
     virtualenv --system-site-packages $DEST/.venv
@@ -938,7 +945,10 @@
     echo_summary "Configuring Neutron"
 
     configure_neutron
-    init_neutron
+    # Run init_neutron only on the node hosting the neutron API server
+    if is_service_enabled $DATABASE_BACKENDS && is_service_enabled q-svc; then
+        init_neutron
+    fi
 fi
 
 # Some Neutron plugins require network controllers which are not
diff --git a/stackrc b/stackrc
index 74a399c..1e08d16 100644
--- a/stackrc
+++ b/stackrc
@@ -191,6 +191,9 @@
             LIBVIRT_GROUP=libvirtd
         fi
         ;;
+    fake)
+        NUMBER_FAKE_NOVA_COMPUTE=${NUMBER_FAKE_NOVA_COMPUTE:-1}
+        ;;
     xenserver)
         # Xen config common to nova and neutron
         XENAPI_USER=${XENAPI_USER:-"root"}
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
new file mode 100755
index 0000000..0ea8f53
--- /dev/null
+++ b/tools/install_pip.sh
@@ -0,0 +1,118 @@
+#!/usr/bin/env bash
+
+# **install_pip.sh**
+
+# install_pip.sh [--pip-version <version>] [--use-get-pip] [--setuptools] [--force]
+#
+# Update pip and friends to a known common version
+
+# Assumptions:
+# - currently we try to leave the system setuptools alone, install
+#   the system package if it is not already present
+# - update pip to $INSTALL_PIP_VERSION
+
+# Keep track of the current directory
+TOOLS_DIR=$(cd $(dirname "$0") && pwd)
+TOP_DIR=`cd $TOOLS_DIR/..; pwd`
+
+# Change dir to top of devstack
+cd $TOP_DIR
+
+# Import common functions
+source $TOP_DIR/functions
+
+FILES=$TOP_DIR/files
+
+# Handle arguments
+
+INSTALL_PIP_VERSION=${INSTALL_PIP_VERSION:-"1.4"}
+while [[ -n "$1" ]]; do
+    case $1 in
+        --force)
+            FORCE=1
+            ;;
+        --pip-version)
+            INSTALL_PIP_VERSION="$2"
+            shift
+            ;;
+        --setuptools)
+            SETUPTOOLS=1
+            ;;
+        --use-get-pip)
+            USE_GET_PIP=1;
+            ;;
+    esac
+    shift
+done
+
+SETUPTOOLS_EZ_SETUP_URL=https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
+PIP_GET_PIP_URL=https://raw.github.com/pypa/pip/master/contrib/get-pip.py
+PIP_TAR_URL=https://pypi.python.org/packages/source/p/pip/pip-$INSTALL_PIP_VERSION.tar.gz
+
+GetDistro
+echo "Distro: $DISTRO"
+
+function get_versions() {
+    PIP=$(which pip 2>/dev/null || which pip-python 2>/dev/null)
+    if [[ -n $PIP ]]; then
+        DISTRIBUTE_VERSION=$($PIP freeze | grep 'distribute==')
+        SETUPTOOLS_VERSION=$($PIP freeze | grep 'setuptools==')
+        PIP_VERSION=$($PIP --version | awk '{ print $2}')
+        echo "pip: $PIP_VERSION  setuptools: $SETUPTOOLS_VERSION  distribute: $DISTRIBUTE_VERSION"
+    fi
+}
+
+function setuptools_ez_setup() {
+    if [[ ! -r $FILES/ez_setup.py ]]; then
+        (cd $FILES; \
+         curl -OR $SETUPTOOLS_EZ_SETUP_URL; \
+        )
+    fi
+    sudo python $FILES/ez_setup.py
+}
+
+function install_get_pip() {
+    if [[ ! -r $FILES/get-pip.py ]]; then
+        (cd $FILES; \
+            curl $PIP_GET_PIP_URL; \
+        )
+    fi
+    sudo python $FILES/get-pip.py
+}
+
+function install_pip_tarball() {
+    curl -O $PIP_TAR_URL
+    tar xvfz pip-$INSTALL_PIP_VERSION.tar.gz
+    cd pip-$INSTALL_PIP_VERSION
+    sudo python setup.py install
+}
+
+# Show starting versions
+get_versions
+
+# Do setuptools
+if [[ -n "$SETUPTOOLS" ]]; then
+    # We want it from source
+    uninstall_package python-setuptools
+    setuptools_ez_setup
+else
+    # See about installing the distro setuptools
+    if ! python -c "import setuptools"; then
+        install_package python-setuptools
+    fi
+fi
+
+# Do pip
+if [[ -z $PIP || "$PIP_VERSION" != "$INSTALL_PIP_VERSION" || -n $FORCE ]]; then
+
+    # Eradicate any and all system packages
+    uninstall_package python-pip
+
+    if [[ -n "$USE_GET_PIP" ]]; then
+        install_get_pip
+    else
+        install_pip_tarball
+    fi
+
+    get_versions
+fi
diff --git a/unstack.sh b/unstack.sh
index 1e80bf3..2268b90 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -24,6 +24,9 @@
 # Destination path for service data
 DATA_DIR=${DATA_DIR:-${DEST}/data}
 
+# Import apache functions
+source $TOP_DIR/lib/apache
+
 # Get project function libraries
 source $TOP_DIR/lib/baremetal
 source $TOP_DIR/lib/cinder