]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Automate host configuration for functional testing
authorMaru Newby <marun@redhat.com>
Fri, 9 Jan 2015 15:02:59 +0000 (15:02 +0000)
committerMaru Newby <marun@redhat.com>
Sat, 14 Feb 2015 05:13:03 +0000 (05:13 +0000)
This change adds a new script, configure_for_func_testing.sh, that
automates configuration of a host to support functional testing.  The
script's functionality is consumed by a refactored version of
gate_hook.sh, and both minimizes runtime and removes the previous
dependency on the devstack-gate repo.

Additionally, the dsvm-functional tox env is no longer dependent on
devstack to deploy neutron's rootwrap configuration system-wide.
Rootwrap configuration is now deployed to the target tox venv on each
tox invocation.

Change-Id: Iaf43be458bdf3c4535f95ee5a3a3b47a744020a0

TESTING.rst
neutron/tests/contrib/functional-testing.filters [moved from neutron/tests/contrib/filters.template with 66% similarity]
neutron/tests/contrib/gate_hook.sh
tools/configure_for_func_testing.sh [new file with mode: 0755]
tools/deploy_rootwrap.sh [new file with mode: 0755]
tools/misc-sanity-checks.sh
tox.ini

index d3b7795232fc2e23864788a860690f2a3f6e41f4..6c9204d1b0f4b032a267a8ea0ebeb46b095ea738 100644 (file)
@@ -119,11 +119,25 @@ specific-system dependencies::
 
     tox -e functional
 
-To run all the functional tests in an environment that has been configured
-by devstack to support sudo and system-specific dependencies::
-
+To run all the functional tests, including those requiring sudo
+privileges and system-specific dependencies, the procedure defined by
+tools/configure_for_func_testing.sh should be followed.
+
+IMPORTANT: configure_for_func_testing.sh relies on devstack to perform
+extensive modification to the underlying host.  Execution of the
+script requires sudo privileges and it is recommended that the
+following commands be invoked only on a clean and disposeable VM.  A
+VM that has had devstack previously installed on it is also fine. ::
+
+    git clone https://git.openstack.org/openstack-dev/devstack ../devstack
+    ./tools/configure_for_func_testing.sh ../devstack -i
     tox -e dsvm-functional
 
+The '-i' option is optional and instructs the script to use devstack
+to install and configure all of Neutron's package dependencies.  It is
+not necessary to provide this option if devstack has already been used
+to deploy Neutron to the target host.
+
 For more information on the standard Tox-based test infrastructure used by
 OpenStack and how to do some common test/debugging procedures with Testr,
 see this wiki page:
similarity index 66%
rename from neutron/tests/contrib/filters.template
rename to neutron/tests/contrib/functional-testing.filters
index 45835118f8f0820c37064b77c090f84660b5fec5..edfcec07ce44d82baeaca70042da472a559ee5c0 100644 (file)
@@ -4,13 +4,6 @@
 # This file should be owned by (and only-writeable by) the root user
 
 [Filters]
-# '$BASE_PATH' is intended to be replaced with the expected tox path
-# (e.g. /opt/stack/new/neutron/.tox/dsvm-functional) by the neutron
-# functional jenkins job.  This ensures that tests can kill the
-# processes that they launch with their containing tox environment's
-# python.
-kill_tox_python: KillFilter, root, $BASE_PATH/bin/python, -9
-
 # enable ping from namespace
 ping_filter: CommandFilter, ping, root
 
index 67ec27ccc5bcdb87fbcbbb940228816a0c2fc5aa..0f93918a4be1dd35bc6bbad023c812375015013f 100644 (file)
@@ -1,58 +1,29 @@
 #!/bin/bash
 
+
 set -ex
 
-venv=${1:-"dsvm-functional"}
 
-CONTRIB_DIR="$BASE/new/neutron/neutron/tests/contrib"
+venv=${1:-"dsvm-functional"}
 
-$BASE/new/devstack-gate/devstack-vm-gate.sh
 
 if [ "$venv" == "dsvm-functional" ]
 then
-    # Add a rootwrap filter to support test-only
-    # configuration (e.g. a KillFilter for processes that
-    # use the python installed in a tox env).
-    FUNC_FILTER=$CONTRIB_DIR/filters.template
-    sed -e "s+\$BASE_PATH+$BASE/new/neutron/.tox/dsvm-functional+" \
-        $FUNC_FILTER | sudo tee /etc/neutron/rootwrap.d/functional.filters > /dev/null
-
-    # Use devstack functions to install mysql and psql servers
-    TOP_DIR=$BASE/new/devstack
-    source $TOP_DIR/functions
-    source $TOP_DIR/lib/config
-    source $TOP_DIR/stackrc
-    source $TOP_DIR/lib/database
-    source $TOP_DIR/localrc
-
-    disable_service postgresql
-    enable_service mysql
-    initialize_database_backends
-    install_database
-
-    disable_service mysql
-    enable_service postgresql
-    initialize_database_backends
-    install_database
-
-    # Set up the 'openstack_citest' user and database in each backend
-    tmp_dir=`mktemp -d`
-
-    cat << EOF > $tmp_dir/mysql.sql
-CREATE DATABASE openstack_citest;
-CREATE USER 'openstack_citest'@'localhost' IDENTIFIED BY 'openstack_citest';
-CREATE USER 'openstack_citest' IDENTIFIED BY 'openstack_citest';
-GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest'@'localhost';
-GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest';
-FLUSH PRIVILEGES;
-EOF
-    /usr/bin/mysql -u root < $tmp_dir/mysql.sql
-
-    cat << EOF > $tmp_dir/postgresql.sql
-CREATE USER openstack_citest WITH CREATEDB LOGIN PASSWORD 'openstack_citest';
-CREATE DATABASE openstack_citest WITH OWNER openstack_citest;
-EOF
-    # User/group postgres needs to be given access to tmp_dir
-    setfacl -m g:postgres:rwx $tmp_dir
-    sudo -u postgres /usr/bin/psql --file=$tmp_dir/postgresql.sql
+    # The following need to be set before sourcing
+    # configure_for_func_testing.
+    GATE_DEST=$BASE/new
+    GATE_STACK_USER=stack
+    NEUTRON_PATH=$GATE_DEST/neutron
+    DEVSTACK_PATH=$GATE_DEST/devstack
+    IS_GATE=True
+
+    source $NEUTRON_PATH/tools/configure_for_func_testing.sh
+
+    # Make the workspace owned by the stack user
+    sudo chown -R $STACK_USER:$STACK_USER $BASE
+
+    configure_host_for_func_testing $STACK_USER
+elif [ "$venv" == "api" ]
+then
+    $BASE/new/devstack-gate/devstack-vm-gate.sh
 fi
diff --git a/tools/configure_for_func_testing.sh b/tools/configure_for_func_testing.sh
new file mode 100755 (executable)
index 0000000..38c1ffe
--- /dev/null
@@ -0,0 +1,249 @@
+#!/bin/bash
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+set -e
+
+
+# Control variable used to determine whether to execute this script
+# directly or allow the gate_hook to import.
+IS_GATE=${IS_GATE:-False}
+
+
+if [[ "$IS_GATE" != "True" ]] && [[ "$#" -lt 1 ]]; then
+    >&2 echo "Usage: $0 /path/to/devstack [-i]
+Configure a host to run Neutron's functional test suite.
+
+-i   Install Neutron's package dependencies.  By default, it is assumed
+     that devstack has already been used to deploy neutron to the
+     target host and that package dependencies need not be installed.
+
+Warning: This script relies on devstack to perform extensive
+modification to the underlying host.  It is recommended that it be
+invoked only on a throw-away VM."
+    exit 1
+fi
+
+
+# Skip the first argument
+OPTIND=2
+while getopts ":i" opt; do
+    case $opt in
+        i)
+            INSTALL_BASE_DEPENDENCIES=True
+            ;;
+    esac
+
+done
+
+# Default to environment variables to permit the gate_hook to override
+# when sourcing.
+DEVSTACK_PATH=${DEVSTACK_PATH:-$1}
+ # The gate should automatically install dependencies.
+INSTALL_BASE_DEPENDENCIES=${INSTALL_BASE_DEPENDENCIES:-$IS_GATE}
+
+
+if [ ! -f "$DEVSTACK_PATH/stack.sh" ]; then
+  >&2 echo "Unable to find devstack at '$DEVSTACK_PATH'.  Please verify that the specified path points to a valid devstack repo."
+  exit 1
+fi
+
+
+set -x
+
+
+function _init {
+    NEUTRON_PATH=${NEUTRON_PATH:-$(cd $(dirname "$0")/.. && pwd)}
+
+    # Subsequently-called devstack functions depend on the following variables.
+    HOST_IP=127.0.0.1
+    FILES=$DEVSTACK_PATH/files
+    TOP_DIR=$DEVSTACK_PATH
+
+    source $DEVSTACK_PATH/stackrc
+
+    # Allow the gate to override values set by stackrc.
+    DEST=${GATE_DEST:-$DEST}
+    STACK_USER=${GATE_STACK_USER:-$STACK_USER}
+}
+
+
+function _install_base_deps {
+    echo_summary "Installing base dependencies"
+
+    INSTALL_TESTONLY_PACKAGES=True
+    PACKAGES=$(get_packages general neutron,q-agt,q-l3)
+    # Do not install 'python-' prefixed packages other than
+    # python-dev*.  Neutron's functional testing relies on deployment
+    # to a tox env so there is no point in installing python
+    # dependencies system-wide.
+    PACKAGES=$(echo $PACKAGES | perl -pe 's|python-(?!dev)[^ ]*||g')
+    install_package $PACKAGES
+}
+
+
+function _install_rpc_backend {
+    echo_summary "Installing rabbitmq"
+
+    RABBIT_USERID=${RABBIT_USERID:-stackrabbit}
+    RABBIT_HOST=${RABBIT_HOST:-$SERVICE_HOST}
+    RABBIT_PASSWORD=${RABBIT_HOST:-secretrabbit}
+
+    source $DEVSTACK_PATH/lib/rpc_backend
+
+    enable_service rabbit
+    install_rpc_backend
+    restart_rpc_backend
+}
+
+
+function _install_databases {
+    echo_summary "Installing databases"
+
+    # Avoid attempting to configure the db if it appears to already
+    # have run.  The setup as currently defined is not idempotent.
+    if mysql openstack_citest > /dev/null 2>&1 < /dev/null; then
+        echo_summary "DB config appears to be complete, skipping."
+        return 0
+    fi
+
+    MYSQL_PASSWORD=${MYSQL_PASSWORD:-secretmysql}
+    DATABASE_PASSWORD=${DATABASE_PASSWORD:-secretdatabase}
+
+    source $DEVSTACK_PATH/lib/database
+
+    disable_service postgresql
+    enable_service mysql
+    initialize_database_backends
+    install_database
+    configure_database_mysql
+
+    disable_service mysql
+    enable_service postgresql
+    initialize_database_backends
+    install_database
+    configure_database_postgresql
+
+    # Set up the 'openstack_citest' user and database in each backend
+    tmp_dir=$(mktemp -d)
+    trap "rm -rf $tmp_dir" EXIT
+
+    cat << EOF > $tmp_dir/mysql.sql
+CREATE DATABASE openstack_citest;
+CREATE USER 'openstack_citest'@'localhost' IDENTIFIED BY 'openstack_citest';
+CREATE USER 'openstack_citest' IDENTIFIED BY 'openstack_citest';
+GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest'@'localhost';
+GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest';
+FLUSH PRIVILEGES;
+EOF
+    /usr/bin/mysql -u root < $tmp_dir/mysql.sql
+
+    cat << EOF > $tmp_dir/postgresql.sql
+CREATE USER openstack_citest WITH CREATEDB LOGIN PASSWORD 'openstack_citest';
+CREATE DATABASE openstack_citest WITH OWNER openstack_citest;
+EOF
+
+    # User/group postgres needs to be given access to tmp_dir
+    setfacl -m g:postgres:rwx $tmp_dir
+    sudo -u postgres /usr/bin/psql --file=$tmp_dir/postgresql.sql
+}
+
+
+function _install_agent_deps {
+    echo_summary "Installing agent dependencies"
+
+    source $DEVSTACK_PATH/lib/neutron
+
+    ENABLED_SERVICES=q-agt,q-dhcp,q-l3
+    install_neutron_agent_packages
+}
+
+
+# Set up the rootwrap sudoers for neutron to target the rootwrap
+# configuration deployed in the venv.
+function _install_rootwrap_sudoers {
+    echo_summary "Installing rootwrap sudoers file"
+
+    VENV_NAME=${venv:-dsvm-functional}
+    VENV_PATH=$NEUTRON_PATH/.tox/$VENV_NAME
+    ROOTWRAP_SUDOER_CMD="$VENV_PATH/bin/neutron-rootwrap $VENV_PATH/etc/neutron/rootwrap.conf *"
+    TEMPFILE=$(mktemp)
+    cat << EOF > $TEMPFILE
+# A bug in oslo.rootwrap [1] prevents commands executed with 'ip netns
+# exec' from being automatically qualified with a prefix from
+# rootwrap's configured exec_dirs.  To work around this problem, add
+# the venv bin path to a user-specific secure_path.
+#
+# While it might seem preferable to set a command-specific
+# secure_path, this would only ensure the correct path for 'ip netns
+# exec' and the command targeted for execution in the namespace would
+# not inherit the path.
+#
+# 1: https://bugs.launchpad.net/oslo.rootwrap/+bug/1417331
+#
+Defaults:$STACK_USER  secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$VENV_PATH/bin"
+$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD
+EOF
+    chmod 0440 $TEMPFILE
+    sudo chown root:root $TEMPFILE
+    # Name the functional testing rootwrap to ensure that it will be
+    # loaded after the devstack rootwrap (50_stack_sh if present) so
+    # that the functional testing secure_path (a superset of what
+    # devstack expects) will not be overwritten.
+    sudo mv $TEMPFILE /etc/sudoers.d/60-neutron-func-test-rootwrap
+}
+
+
+function _install_post_devstack {
+    echo_summary "Performing post-devstack installation"
+
+    _install_databases
+    _install_rootwrap_sudoers
+
+    # Installing python-openvswitch from packages is a stop-gap while
+    # python-openvswitch remains unavailable from pypi.  This also
+    # requires that sitepackages=True be set in tox.ini to allow the
+    # venv to use the installed package.  Once python-openvswitch
+    # becomes available on pypi, this will no longer be required.
+    #
+    # NOTE: the package name 'python-openvswitch' is common across
+    # supported distros.
+    install_package python-openvswitch
+
+    # Configure ovs-vsctl to be reachable via the standard ovsdb port.
+    sudo ovs-vsctl set-manager ptcp:6640:127.0.0.1
+}
+
+
+function configure_host_for_func_testing {
+    echo_summary "Configuring host for functional testing"
+
+    if [[ "$INSTALL_BASE_DEPENDENCIES" == "True" ]]; then
+        # Installing of the following can be achieved via devstack by
+        # installing neutron, so their installation is conditional to
+        # minimize the work to do on a devstack-configured host.
+        _install_base_deps
+        _install_agent_deps
+        _install_rpc_backend
+    fi
+    _install_post_devstack
+}
+
+
+_init
+
+
+if [[ "$IS_GATE" != "True" ]]; then
+    configure_host_for_func_testing
+fi
diff --git a/tools/deploy_rootwrap.sh b/tools/deploy_rootwrap.sh
new file mode 100755 (executable)
index 0000000..dbe8ef7
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+set -eu
+
+if [ "$#" -ne 3 ]; then
+  >&2 echo "Usage: $0 /path/to/neutron /path/to/target/etc /path/to/target/bin
+Deploy Neutron's rootwrap configuration.
+
+Warning: Any existing rootwrap files at the specified etc path will be
+removed by this script.
+
+Optional: set OS_SUDO_TESTING=1 to deploy the filters required by
+Neutron's functional testing suite."
+  exit 1
+fi
+
+OS_SUDO_TESTING=${OS_SUDO_TESTING:-0}
+
+neutron_path=$1
+target_etc_path=$2
+target_bin_path=$3
+
+src_conf_path=${neutron_path}/etc
+src_conf=${src_conf_path}/rootwrap.conf
+src_rootwrap_path=${src_conf_path}/neutron/rootwrap.d
+
+dst_conf_path=${target_etc_path}/neutron
+dst_conf=${dst_conf_path}/rootwrap.conf
+dst_rootwrap_path=${dst_conf_path}/rootwrap.d
+
+if [[ -d "$dst_rootwrap_path" ]]; then
+    rm -rf ${dst_rootwrap_path}
+fi
+mkdir -p -m 755 ${dst_rootwrap_path}
+
+cp -p ${src_rootwrap_path}/* ${dst_rootwrap_path}/
+cp -p ${src_conf} ${dst_conf}
+sed -i "s:^filters_path=.*$:filters_path=${dst_rootwrap_path}:" ${dst_conf}
+sed -i "s:^\(exec_dirs=.*\)$:\1,${target_bin_path}:" ${dst_conf}
+
+if [[ "$OS_SUDO_TESTING" = "1" ]]; then
+    cp -p ${neutron_path}/neutron/tests/contrib/functional-testing.filters \
+        ${dst_rootwrap_path}/
+fi
index 05480edc9a33a9d132c8f10c385bc35bddce4ea1..e049449828b2da9ec8478b0c6942e7f3f42d5bd3 100644 (file)
@@ -32,7 +32,7 @@ check_opinionated_shell () {
     # If you cannot avoid the use of bash, please change the EXPECTED var below.
     OBSERVED=$(grep -E '^([[:space:]]*[^#[:space:]]|#!).*bash' \
                tox.ini tools/* | wc -l)
-    EXPECTED=4
+    EXPECTED=6
     if [ ${EXPECTED} -ne ${OBSERVED} ]; then
         echo "Bash usage has been detected!" >>$FAILURES
     fi
diff --git a/tox.ini b/tox.ini
index 3d1f62f44fd0618b7eb588d8d9f33f976b245745..b9590ffb4daef2508cfce40bcda5c3aff0936aab 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -14,6 +14,7 @@ deps = -r{toxinidir}/requirements.txt
        -r{toxinidir}/test-requirements.txt
 whitelist_externals = sh
 commands =
+  dsvm-functional: {toxinidir}/tools/deploy_rootwrap.sh {toxinidir} {envdir}/etc {envbindir}
   sh tools/pretty_tox.sh '{posargs}'
 # there is also secret magic in pretty_tox.sh which lets you run in a fail only
 # mode. To do this define the TRACE_FAILONLY environmental variable.
@@ -37,7 +38,7 @@ deps =
 [testenv:dsvm-functional]
 setenv = OS_TEST_PATH=./neutron/tests/functional
          OS_SUDO_TESTING=1
-         OS_ROOTWRAP_CMD=sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
+         OS_ROOTWRAP_CMD=sudo {envbindir}/neutron-rootwrap {envdir}/etc/neutron/rootwrap.conf
          OS_FAIL_ON_MISSING_DEPS=1
          OS_TEST_TIMEOUT=90
 sitepackages=True