Merge "Rework class inheritance for scenario tests"
diff --git a/run_tests.sh b/run_tests.sh
index a645b22..f8636c1 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -11,23 +11,22 @@
echo " -u, --update Update the virtual environment with any newer package versions"
echo " -s, --smoke Only run smoke tests"
echo " -w, --whitebox Only run whitebox tests"
- echo " -t, --with-testr Run using testr instead of nose"
+ echo " -t, --parallel Run testr parallel"
echo " -c, --nova-coverage Enable Nova coverage collection"
echo " -C, --config Config file location"
echo " -p, --pep8 Just run pep8"
echo " -h, --help Print this usage message"
echo " -d, --debug Debug this script -- set -o xtrace"
- echo " -S, --stdout Don't capture stdout"
echo " -l, --logging Enable logging"
echo " -L, --logging-config Logging config file location. Default is etc/logging.conf"
- echo " -- [NOSEOPTIONS] After the first '--' you can pass arbitrary arguments to nosetests "
+ echo " -- [TESTROPTIONS] After the first '--' you can pass arbitrary arguments to testr "
}
-noseargs=""
+testrargs=""
just_pep8=0
venv=.venv
with_venv=tools/with_venv.sh
-with_testr=0
+parallel=0
always_venv=0
never_venv=0
no_site_packages=0
@@ -39,7 +38,7 @@
logging=0
logging_config=etc/logging.conf
-if ! options=$(getopt -o VNnfuswtcphdSC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,whitebox,with-testr,nova-coverage,pep8,help,debug,stdout,config:,logging,logging-config: -- "$@")
+if ! options=$(getopt -o VNnfuswtcphdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,whitebox,parallel,nova-coverage,pep8,help,debug,config:,logging,logging-config: -- "$@")
then
# parse error
usage
@@ -60,14 +59,13 @@
-c|--nova-coverage) let nova_coverage=1;;
-C|--config) config_file=$2; shift;;
-p|--pep8) let just_pep8=1;;
- -s|--smoke) noseargs="$noseargs --attr=type=smoke";;
- -w|--whitebox) noseargs="$noseargs --attr=type=whitebox";;
- -t|--with-testr) with_testr=1;;
- -S|--stdout) noseargs="$noseargs -s";;
+ -s|--smoke) testrargs="$testrargs smoke";;
+ -w|--whitebox) testrargs="$testrargs whitebox";;
+ -t|--parallel) parallel=1;;
-l|--logging) logging=1;;
-L|--logging-config) logging_config=$2; shift;;
- --) [ "yes" == "$first_uu" ] || noseargs="$noseargs $1"; first_uu=no ;;
- *) noseargs="$noseargs $1"
+ --) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no ;;
+ *) testrargs="$testrargs $1"
esac
shift
done
@@ -90,24 +88,10 @@
cd `dirname "$0"`
-export NOSE_WITH_OPENSTACK=1
-export NOSE_OPENSTACK_COLOR=1
-export NOSE_OPENSTACK_RED=15.00
-export NOSE_OPENSTACK_YELLOW=3.00
-export NOSE_OPENSTACK_SHOW_ELAPSED=1
-export NOSE_OPENSTACK_STDOUT=1
-
if [ $no_site_packages -eq 1 ]; then
installvenvopts="--no-site-packages"
fi
-# only add tempest default if we don't specify a test
-if [[ "x$noseargs" =~ "tempest" ]]; then
- noseargs="$noseargs"
-else
- noseargs="$noseargs tempest"
-fi
-
function testr_init {
if [ ! -d .testrepository ]; then
${wrapper} testr init
@@ -115,12 +99,12 @@
}
function run_tests {
- if [ $with_testr -eq 1 ]; then
- testr_init
- ${wrapper} find . -type f -name "*.pyc" -delete
- ${wrapper} testr run --parallel --subunit $noseargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+ testr_init
+ ${wrapper} find . -type f -name "*.pyc" -delete
+ if [ $parallel -eq 1 ]; then
+ ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
else
- ${wrapper} $NOSETESTS
+ ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
fi
}
@@ -139,8 +123,6 @@
${wrapper} python tools/tempest_coverage.py -c report
}
-NOSETESTS="nosetests $noseargs"
-
if [ $never_venv -eq 0 ]
then
# Remove the virtual environment if --force used
@@ -187,7 +169,7 @@
run_coverage_report
fi
-if [ -z "$noseargs" ]; then
+if [ -z "$testrargs" ]; then
run_pep8
fi
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 703f143..e09a23f 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -255,6 +255,20 @@
self.assertRaises(exceptions.NotFound, self.client.get_server,
'999erra43')
+ @attr(type=['negative', 'gate'])
+ def test_stop_non_existent_server(self):
+ # Stop a non existent server
+ non_exist_id = rand_name('non-existent-server')
+ self.assertRaises(exceptions.NotFound, self.servers_client.stop,
+ non_exist_id)
+
+ @attr(type=['negative', 'gate'])
+ def test_pause_non_existent_server(self):
+ # pause a non existent server
+ non_exist_id = rand_name('non-existent-server')
+ self.assertRaises(exceptions.NotFound, self.client.pause_server,
+ non_exist_id)
+
class ServersNegativeTestXML(ServersNegativeTestJSON):
_interface = 'xml'
diff --git a/tempest/scenario/test_volume_snapshot_pattern.py b/tempest/scenario/test_volume_snapshot_pattern.py
new file mode 100644
index 0000000..4d8a400
--- /dev/null
+++ b/tempest/scenario/test_volume_snapshot_pattern.py
@@ -0,0 +1,122 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+from tempest.openstack.common import log as logging
+
+from tempest.common.utils.data_utils import rand_name
+from tempest.scenario import manager
+
+LOG = logging.getLogger(__name__)
+
+
+class TestVolumeSnapshotPattern(manager.OfficialClientTest):
+
+ """
+ This test case attempts to reproduce the following steps:
+
+ * Create in Cinder some bootable volume importing a Glance image
+ * Boot an instance from the bootable volume
+ * Create a volume snapshot while the instance is running
+ * Boot an additional instance from the new snapshot based volume
+ """
+
+ def _create_volume_from_image(self):
+ img_uuid = self.config.compute.image_ref
+ vol_name = rand_name('volume-origin')
+ vol = self.volume_client.volumes.create(size=1,
+ display_name=vol_name,
+ imageRef=img_uuid)
+ self.set_resource(vol.id, vol)
+ self.status_timeout(self.volume_client.volumes,
+ vol.id,
+ 'available')
+ return vol
+
+ def _boot_instance_from_volume(self, vol_id):
+ # NOTE(gfidente): the img_uuid here is only needed because
+ # the novaclient requires it to be passed as arg
+ img_uuid = self.config.compute.image_ref
+ i_name = rand_name('instance')
+ flavor_id = self.config.compute.flavor_ref
+ # NOTE(gfidente): the syntax for block_device_mapping is
+ # dev_name=id:type:size:delete_on_terminate
+ # where type needs to be "snap" if the server is booted
+ # from a snapshot, size instead can be safely left empty
+ bd_map = {
+ 'vda': vol_id + ':::0'
+ }
+ create_kwargs = {
+ 'block_device_mapping': bd_map
+ }
+ i = self.compute_client.servers.create(name=i_name,
+ image=img_uuid,
+ flavor=flavor_id,
+ **create_kwargs)
+ self.set_resource(i.id, i)
+ self.status_timeout(self.compute_client.servers,
+ i.id,
+ 'ACTIVE')
+ return i
+
+ def _create_snapshot_from_volume(self, vol_id):
+ volume_snapshots = self.volume_client.volume_snapshots
+ snap_name = rand_name('snapshot')
+ snap = volume_snapshots.create(volume_id=vol_id,
+ force=True,
+ display_name=snap_name)
+ self.set_resource(snap.id, snap)
+ self.status_timeout(volume_snapshots,
+ snap.id,
+ 'available')
+ return snap
+
+ def _create_volume_from_snapshot(self, snap_id):
+ vol_name = rand_name('volume')
+ vol = self.volume_client.volumes.create(size=1,
+ display_name=vol_name,
+ snapshot_id=snap_id)
+ self.set_resource(vol.id, vol)
+ self.status_timeout(self.volume_client.volumes,
+ vol.id,
+ 'available')
+ return vol
+
+ def _stop_instances(self, instances):
+ # NOTE(gfidente): two loops so we do not wait for the status twice
+ for i in instances:
+ self.compute_client.servers.stop(i)
+ for i in instances:
+ self.status_timeout(self.compute_client.servers,
+ i.id,
+ 'SHUTOFF')
+
+ def _detach_volumes(self, volumes):
+ # NOTE(gfidente): two loops so we do not wait for the status twice
+ for v in volumes:
+ self.volume_client.volumes.detach(v)
+ for v in volumes:
+ self.status_timeout(self.volume_client.volumes,
+ v.id,
+ 'available')
+
+ def test_volume_snapshot_pattern(self):
+ volume_origin = self._create_volume_from_image()
+ i_origin = self._boot_instance_from_volume(volume_origin.id)
+ snapshot = self._create_snapshot_from_volume(volume_origin.id)
+ volume = self._create_volume_from_snapshot(snapshot.id)
+ i = self._boot_instance_from_volume(volume.id)
+ # NOTE(gfidente): ensure resources are in clean state for
+ # deletion operations to succeed
+ self._stop_instances([i_origin, i])
+ self._detach_volumes([volume_origin, volume])
diff --git a/tools/pretty_tox_serial.sh b/tools/pretty_tox_serial.sh
index 490d263..dd7b682 100755
--- a/tools/pretty_tox_serial.sh
+++ b/tools/pretty_tox_serial.sh
@@ -5,5 +5,5 @@
if [ ! -d .testrepository ]; then
testr init
fi
-testr run --subunit $TESTRARGS | subunit-2to1 | tools/colorizer.py
+testr run --subunit $TESTRARGS | subunit2pyunit
testr slowest
diff --git a/tox.ini b/tox.ini
index c3562e6..53f85c1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,22 +13,11 @@
commands =
python setup.py testr --slowest
-
[testenv:full]
sitepackages = True
setenv = VIRTUAL_ENV={envdir}
- NOSE_WITH_OPENSTACK=1
- NOSE_OPENSTACK_COLOR=1
- NOSE_OPENSTACK_RED=15
- NOSE_OPENSTACK_YELLOW=3
- NOSE_OPENSTACK_SHOW_ELAPSED=1
- NOSE_OPENSTACK_STDOUT=1
-commands =
- nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit --xunit-file=nosetests-full.xml -sv tempest/api tempest/scenario tempest/thirdparty tempest/cli
-
-[testenv:testr-serial]
-sitepackages = True
-setenv = VIRTUAL_ENV={envdir}
+# The regex below is used to select which tests to run and exclude the slow tag:
+# See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610
commands =
sh tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
@@ -41,27 +30,15 @@
[testenv:smoke]
sitepackages = True
setenv = VIRTUAL_ENV={envdir}
- NOSE_WITH_OPENSTACK=1
- NOSE_OPENSTACK_COLOR=1
- NOSE_OPENSTACK_RED=15
- NOSE_OPENSTACK_YELLOW=3
- NOSE_OPENSTACK_SHOW_ELAPSED=1
- NOSE_OPENSTACK_STDOUT=1
commands =
- nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit -sv --attr=type=smoke --xunit-file=nosetests-smoke.xml tempest
+ sh tools/pretty_tox_serial.sh 'smoke {posargs}'
[testenv:coverage]
sitepackages = True
setenv = VIRTUAL_ENV={envdir}
- NOSE_WITH_OPENSTACK=1
- NOSE_OPENSTACK_COLOR=1
- NOSE_OPENSTACK_RED=15
- NOSE_OPENSTACK_YELLOW=3
- NOSE_OPENSTACK_SHOW_ELAPSED=1
- NOSE_OPENSTACK_STDOUT=1
commands =
python -m tools/tempest_coverage -c start --combine
- nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit --xunit-file=nosetests-full.xml -sv tempest/api tempest/scenario tempest/thirdparty tempest/cli
+ sh tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
python -m tools/tempest_coverage -c report --html {posargs}
[testenv:stress]