Merge "Remove old cinder multibackend configuration from tempest.conf"
diff --git a/HACKING.rst b/HACKING.rst
index b82f8c9..4095c4b 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -20,6 +20,7 @@
- [T110] Check that service client names of GET should be consistent
- [T111] Check that service client names of DELETE should be consistent
- [T112] Check that tempest.lib should not import local tempest code
+- [T113] Check that tests use data_utils.rand_uuid() instead of uuid.uuid4()
- [N322] Method's default argument shouldn't be mutable
Test Data/Configuration
diff --git a/README.rst b/README.rst
index 7da83cd..650a1ed 100644
--- a/README.rst
+++ b/README.rst
@@ -58,7 +58,7 @@
#. You first need to install Tempest. This is done with pip after you check out
the Tempest repo::
- $ git clone https://github.com/openstack/tempest/
+ $ git clone http://git.openstack.org/openstack/tempest
$ pip install tempest/
This can be done within a venv, but the assumption for this guide is that
@@ -71,14 +71,14 @@
it's recommended that you copy or rename tempest.conf.sample to tempest.conf
and make those changes to that file in /etc/tempest
-#. Setup a local working Tempest dir. This is done using the tempest init
+#. Setup a local working Tempest dir. This is done by using the tempest init
command::
- tempest init cloud-01
+ $ tempest init cloud-01
works the same as::
- mkdir cloud-01 && cd cloud-01 && tempest init
+ $ mkdir cloud-01 && cd cloud-01 && tempest init
This will create a new directory for running a single Tempest configuration.
If you'd like to run Tempest against multiple OpenStack deployments the idea
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 63ec04b..fc05b12 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -205,3 +205,7 @@
* `2.2`_
.. _2.2: http://docs.openstack.org/developer/nova/api_microversion_history.html#id2
+
+ * `2.10`_
+
+ .. _2.10: http://docs.openstack.org/developer/nova/api_microversion_history.html#id9
diff --git a/openstack-common.conf b/openstack-common.conf
deleted file mode 100644
index acb1437..0000000
--- a/openstack-common.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-[DEFAULT]
-
-# The list of modules to copy from openstack-common
-module=install_venv_common
-module=with_venv
-module=install_venv
-
-# The base module to hold the copy of openstack.common
-base=tempest
diff --git a/requirements.txt b/requirements.txt
index 7c426e6..79ae42e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,6 @@
pbr>=1.6 # Apache-2.0
cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0
anyjson>=0.3.3 # BSD
-httplib2>=0.7.5 # MIT
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
testtools>=1.4.0 # MIT
paramiko>=1.16.0 # LGPL
@@ -22,6 +21,7 @@
fixtures<2.0,>=1.3.1 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
PyYAML>=3.1.0 # MIT
-stevedore>=1.5.0 # Apache-2.0
+stevedore>=1.9.0 # Apache-2.0
PrettyTable<0.8,>=0.7 # BSD
os-testr>=0.4.1 # Apache-2.0
+urllib3>=1.8.3 # MIT
diff --git a/run_tempest.sh b/run_tempest.sh
index 8c8f25f..af01734 100755
--- a/run_tempest.sh
+++ b/run_tempest.sh
@@ -103,22 +103,25 @@
fi
if [ $update -eq 1 ]; then
echo "Updating virtualenv..."
- python tools/install_venv.py $installvenvopts
+ virtualenv $installvenvopts $venv
+ $venv/bin/pip install -U -r requirements.txt
fi
if [ -e ${venv} ]; then
wrapper="${with_venv}"
else
if [ $always_venv -eq 1 ]; then
# Automatically install the virtualenv
- python tools/install_venv.py $installvenvopts
+ virtualenv $installvenvopts $venv
wrapper="${with_venv}"
+ ${wrapper} pip install -U -r requirements.txt
else
echo -e "No virtual environment found...create one? (Y/n) \c"
read use_ve
if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
# Install the virtualenv and run the test suite in it
- python tools/install_venv.py $installvenvopts
+ virtualenv $installvenvopts $venv
wrapper=${with_venv}
+ ${wrapper} pip install -U -r requirements.txt
fi
fi
fi
diff --git a/run_tests.sh b/run_tests.sh
index 908056f..22314b6 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -114,22 +114,25 @@
fi
if [ $update -eq 1 ]; then
echo "Updating virtualenv..."
- python tools/install_venv.py $installvenvopts
+ virtualenv $installvenvopts $venv
+ $venv/bin/pip install -U -r requirements.txt -r test-requirements.txt
fi
if [ -e ${venv} ]; then
wrapper="${with_venv}"
else
if [ $always_venv -eq 1 ]; then
# Automatically install the virtualenv
- python tools/install_venv.py $installvenvopts
+ virtualenv $installvenvopts $venv
wrapper="${with_venv}"
+ ${wrapper} pip install -U -r requirements.txt -r test-requirements.txt
else
echo -e "No virtual environment found...create one? (Y/n) \c"
read use_ve
if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
# Install the virtualenv and run the test suite in it
- python tools/install_venv.py $installvenvopts
+ virtualenv $installvenvopts $venv
wrapper=${with_venv}
+ ${wrapper} pip install -U -r requirements.txt -r test-requirements.txt
fi
fi
fi
diff --git a/tempest/api/baremetal/admin/test_ports_negative.py b/tempest/api/baremetal/admin/test_ports_negative.py
index 8f04db9..5e3a33f 100644
--- a/tempest/api/baremetal/admin/test_ports_negative.py
+++ b/tempest/api/baremetal/admin/test_ports_negative.py
@@ -37,7 +37,7 @@
@test.attr(type=['negative'])
@test.idempotent_id('30277ee8-0c60-4f1d-b125-0e51c2f43369')
def test_create_port_nonexsistent_node_id(self):
- node_id = str(data_utils.rand_uuid())
+ node_id = data_utils.rand_uuid()
address = data_utils.rand_mac_address()
self.assertRaises(lib_exc.BadRequest, self.create_port,
node_id=node_id, address=address)
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 96dedcf..95e7ef1 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -91,7 +91,7 @@
@test.idempotent_id('94c9bb4e-2c2a-4f3c-bb1f-5f0daf918e6d')
def test_create_flavor_with_uuid_id(self):
- flavor_id = str(uuid.uuid4())
+ flavor_id = data_utils.rand_uuid()
new_flavor_id = self._create_flavor(flavor_id)
self.assertEqual(new_flavor_id, flavor_id)
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 3854973..1b7eb12 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -145,4 +143,4 @@
self.assertRaises(lib_exc.NotFound,
self.client.remove_flavor_access,
new_flavor['id'],
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index f313f76..9c6df7f 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -38,7 +36,7 @@
@test.attr(type=['negative'])
@test.idempotent_id('c136086a-0f67-4b2b-bc61-8482bd68989f')
def test_show_nonexistent_hypervisor(self):
- nonexistent_hypervisor_id = str(uuid.uuid4())
+ nonexistent_hypervisor_id = data_utils.rand_uuid()
self.assertRaises(
lib_exc.NotFound,
@@ -70,7 +68,7 @@
@test.attr(type=['negative'])
@test.idempotent_id('02463d69-0ace-4d33-a4a8-93d7883a2bba')
def test_show_servers_with_nonexistent_hypervisor(self):
- nonexistent_hypervisor_id = str(uuid.uuid4())
+ nonexistent_hypervisor_id = data_utils.rand_uuid()
self.assertRaises(
lib_exc.NotFound,
@@ -87,7 +85,7 @@
@test.attr(type=['negative'])
@test.idempotent_id('f60aa680-9a3a-4c7d-90e1-fae3a4891303')
def test_get_nonexistent_hypervisor_uptime(self):
- nonexistent_hypervisor_id = str(uuid.uuid4())
+ nonexistent_hypervisor_id = data_utils.rand_uuid()
self.assertRaises(
lib_exc.NotFound,
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index f81d665..6113c04 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -15,8 +15,10 @@
import testtools
from tempest.api.compute import base
+from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
+from tempest.lib import exceptions
from tempest import test
CONF = config.CONF
@@ -28,6 +30,7 @@
def setup_clients(cls):
super(MigrationsAdminTest, cls).setup_clients()
cls.client = cls.os_adm.migrations_client
+ cls.flavors_admin_client = cls.os_adm.flavors_client
@test.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
def test_list_migrations(self):
@@ -53,3 +56,50 @@
instance_uuids = [x['instance_uuid'] for x in body]
self.assertIn(server_id, instance_uuids)
+
+ def _flavor_clean_up(self, flavor_id):
+ try:
+ self.flavors_admin_client.delete_flavor(flavor_id)
+ self.flavors_admin_client.wait_for_resource_deletion(flavor_id)
+ except exceptions.NotFound:
+ pass
+
+ @test.idempotent_id('33f1fec3-ba18-4470-8e4e-1d888e7c3593')
+ @testtools.skipUnless(CONF.compute_feature_enabled.resize,
+ 'Resize not available.')
+ def test_resize_server_revert_deleted_flavor(self):
+ # Tests that we can revert the resize on an instance whose original
+ # flavor has been deleted.
+
+ # First we have to create a flavor that we can delete so make a copy
+ # of the normal flavor from which we'd create a server.
+ flavor = self.flavors_admin_client.show_flavor(
+ self.flavor_ref)['flavor']
+ flavor = self.flavors_admin_client.create_flavor(
+ name=data_utils.rand_name('test_resize_flavor_'),
+ ram=flavor['ram'],
+ disk=flavor['disk'],
+ vcpus=flavor['vcpus']
+ )['flavor']
+ self.addCleanup(self._flavor_clean_up, flavor['id'])
+
+ # Now boot a server with the copied flavor.
+ server = self.create_test_server(
+ wait_until='ACTIVE', flavor=flavor['id'])
+
+ # Delete the flavor we used to boot the instance.
+ self._flavor_clean_up(flavor['id'])
+
+ # Now resize the server and wait for it to go into verify state.
+ self.servers_client.resize_server(server['id'], self.flavor_ref_alt)
+ waiters.wait_for_server_status(self.servers_client, server['id'],
+ 'VERIFY_RESIZE')
+
+ # Now revert the resize, it should be OK even though the original
+ # flavor used to boot the server was deleted.
+ self.servers_client.revert_resize_server(server['id'])
+ waiters.wait_for_server_status(self.servers_client, server['id'],
+ 'ACTIVE')
+
+ server = self.servers_client.show_server(server['id'])['server']
+ self.assertEqual(flavor['id'], server['flavor']['id'])
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 07a7a30..7437c14 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
import testtools
from tempest.api.compute import base
@@ -147,7 +145,7 @@
# migrate a non existent server
self.assertRaises(lib_exc.NotFound,
self.client.migrate_server,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.idempotent_id('b0b17f83-d14e-4fc4-8f31-bcc9f3cfa629')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index 105c4e3..f71f046 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.compute.floating_ips import base
from tempest.common.utils import data_utils
from tempest import config
@@ -47,7 +45,7 @@
while True:
cls.non_exist_id = data_utils.rand_int_id(start=999)
if CONF.service_available.neutron:
- cls.non_exist_id = str(uuid.uuid4())
+ cls.non_exist_id = data_utils.rand_uuid()
if cls.non_exist_id not in cls.floating_ip_ids:
break
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index c6c7347..ea56ae9 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
@@ -39,7 +37,7 @@
# of non-existent floating IP
# Creating a non-existent floatingIP id
if CONF.service_available.neutron:
- non_exist_id = str(uuid.uuid4())
+ non_exist_id = data_utils.rand_uuid()
else:
non_exist_id = data_utils.rand_int_id(start=999)
self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 4fb4e9a..8201363 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import netaddr
import time
from tempest.api.compute import base
@@ -44,6 +45,8 @@
def setup_clients(cls):
super(AttachInterfacesTestJSON, cls).setup_clients()
cls.client = cls.os.interfaces_client
+ cls.networks_client = cls.os.networks_client
+ cls.subnets_client = cls.os.subnets_client
cls.ports_client = cls.os.ports_client
def wait_for_interface_status(self, server, port_id, status):
@@ -120,6 +123,22 @@
self._check_interface(iface, port_id=port_id)
return iface
+ def _test_create_interface_by_fixed_ips(self, server, ifs):
+ network_id = ifs[0]['net_id']
+ ip_list = [
+ ifs[n]['fixed_ips'][0]['ip_address'] for n in range(0, len(ifs))]
+ ip = str(netaddr.IPAddress(sorted(ip_list)[-1]) + 1)
+
+ fixed_ips = [{'ip_address': ip}]
+ iface = self.client.create_interface(
+ server['id'], net_id=network_id,
+ fixed_ips=fixed_ips)['interfaceAttachment']
+ self.addCleanup(self.ports_client.delete_port, iface['port_id'])
+ iface = self.wait_for_interface_status(
+ server['id'], iface['port_id'], 'ACTIVE')
+ self._check_interface(iface, fixed_ip=ip)
+ return iface
+
def _test_show_interface(self, server, ifs):
iface = ifs[0]
_iface = self.client.show_interface(
@@ -182,6 +201,9 @@
iface = self._test_create_interface_by_port_id(server, ifs)
ifs.append(iface)
+ iface = self._test_create_interface_by_fixed_ips(server, ifs)
+ ifs.append(iface)
+
_ifs = (self.client.list_interfaces(server['id'])
['interfaceAttachments'])
self._compare_iface_list(ifs, _ifs)
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 6796bb5..079465d 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -16,6 +16,7 @@
import testtools
from tempest.api.compute import base
+from tempest.common import compute
from tempest.common import waiters
from tempest import config
from tempest import test
@@ -84,16 +85,8 @@
def test_delete_server_while_in_shelved_state(self):
# Delete a server while it's VM state is Shelved
server = self.create_test_server(wait_until='ACTIVE')
- self.client.shelve_server(server['id'])
+ compute.shelve_server(self.client, server['id'])
- offload_time = CONF.compute.shelved_offload_time
- if offload_time >= 0:
- waiters.wait_for_server_status(self.client, server['id'],
- 'SHELVED_OFFLOADED',
- extra_timeout=offload_time)
- else:
- waiters.wait_for_server_status(self.client, server['id'],
- 'SHELVED')
self.client.delete_server(server['id'])
waiters.wait_for_server_termination(self.client, server['id'])
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 5b4417a..f3aa16a 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -19,6 +19,7 @@
import testtools
from tempest.api.compute import base
+from tempest.common import compute
from tempest.common.utils import data_utils
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
@@ -440,20 +441,8 @@
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
def test_shelve_unshelve_server(self):
- self.client.shelve_server(self.server_id)
-
- offload_time = CONF.compute.shelved_offload_time
- if offload_time >= 0:
- waiters.wait_for_server_status(self.client, self.server_id,
- 'SHELVED_OFFLOADED',
- extra_timeout=offload_time)
- else:
- waiters.wait_for_server_status(self.client, self.server_id,
- 'SHELVED')
-
- self.client.shelve_offload_server(self.server_id)
- waiters.wait_for_server_status(self.client, self.server_id,
- 'SHELVED_OFFLOADED')
+ compute.shelve_server(self.client, self.server_id,
+ force_shelve_offload=True)
server = self.client.show_server(self.server_id)['server']
image_name = server['name'] + '-shelved'
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 8f0e430..10ea31d 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -18,6 +18,7 @@
import testtools
from tempest.api.compute import base
+from tempest.common import compute
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
@@ -453,18 +454,7 @@
@test.attr(type=['negative'])
def test_shelve_shelved_server(self):
# shelve a shelved server.
- self.client.shelve_server(self.server_id)
-
- offload_time = CONF.compute.shelved_offload_time
- if offload_time >= 0:
- waiters.wait_for_server_status(self.client,
- self.server_id,
- 'SHELVED_OFFLOADED',
- extra_timeout=offload_time)
- else:
- waiters.wait_for_server_status(self.client,
- self.server_id,
- 'SHELVED')
+ compute.shelve_server(self.client, self.server_id)
server = self.client.show_server(self.server_id)['server']
image_name = server['name'] + '-shelved'
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index e038b82..912b0a1 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -13,9 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.compute import base
+from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest import test
@@ -39,7 +38,7 @@
def test_list_virtual_interfaces_invalid_server_id(self):
# Negative test: Should not be able to GET virtual interfaces
# for an invalid server_id
- invalid_server_id = str(uuid.uuid4())
+ invalid_server_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound,
self.client.list_virtual_interfaces,
invalid_server_id)
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index e9c8e30..37423a3 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -16,6 +16,7 @@
import testtools
from tempest.api.compute import base
+from tempest.common import compute
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
from tempest import config
@@ -25,6 +26,7 @@
class AttachVolumeTestJSON(base.BaseV2ComputeTest):
+ max_microversion = '2.19'
def __init__(self, *args, **kwargs):
super(AttachVolumeTestJSON, self).__init__(*args, **kwargs)
@@ -62,7 +64,7 @@
self.volumes_client.wait_for_resource_deletion(self.volume['id'])
self.volume = None
- def _create_and_attach(self):
+ def _create_and_attach(self, shelve_server=False):
# Start a server and wait for it to become ready
self.admin_pass = self.image_ssh_password
self.server = self.create_test_server(
@@ -81,6 +83,9 @@
waiters.wait_for_volume_status(self.volumes_client,
self.volume['id'], 'available')
+ if shelve_server:
+ compute.shelve_server(self.servers_client, self.server['id'])
+
# Attach the volume to the server
self.attachment = self.servers_client.attach_volume(
self.server['id'],
@@ -152,3 +157,66 @@
self.assertEqual(self.server['id'], body['serverId'])
self.assertEqual(self.volume['id'], body['volumeId'])
self.assertEqual(self.attachment['id'], body['id'])
+
+
+class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
+ """Testing volume with shelved instance.
+
+ This test checks the attaching and detaching volumes from
+ a shelved or shelved ofload instance.
+ """
+
+ min_microversion = '2.20'
+ max_microversion = 'latest'
+
+ def _unshelve_server_and_check_volumes(self, number_of_partition):
+ # Unshelve the instance and check that there are expected volumes
+ self.servers_client.unshelve_server(self.server['id'])
+ waiters.wait_for_server_status(self.servers_client,
+ self.server['id'],
+ 'ACTIVE')
+ linux_client = remote_client.RemoteClient(
+ self.get_server_ip(self.server['id']),
+ self.image_ssh_user,
+ self.admin_pass,
+ self.validation_resources['keypair']['private_key'])
+
+ command = 'grep vd /proc/partitions | wc -l'
+ nb_partitions = linux_client.exec_command(command).strip()
+ self.assertEqual(number_of_partition, nb_partitions)
+
+ @test.idempotent_id('13a940b6-3474-4c3c-b03f-29b89112bfee')
+ @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+ 'Shelve is not available.')
+ @testtools.skipUnless(CONF.validation.run_validation,
+ 'SSH required for this test')
+ def test_attach_volume_shelved_or_offload_server(self):
+ self._create_and_attach(shelve_server=True)
+
+ # Unshelve the instance and check that there are two volumes
+ self._unshelve_server_and_check_volumes('2')
+
+ # Get Volume attachment of the server
+ volume_attachment = self.servers_client.show_volume_attachment(
+ self.server['id'],
+ self.attachment['id'])['volumeAttachment']
+ self.assertEqual(self.server['id'], volume_attachment['serverId'])
+ self.assertEqual(self.attachment['id'], volume_attachment['id'])
+ # Check the mountpoint is not None after unshelve server even in
+ # case of shelved_offloaded.
+ self.assertIsNotNone(volume_attachment['device'])
+
+ @test.idempotent_id('b54e86dd-a070-49c4-9c07-59ae6dae15aa')
+ @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+ 'Shelve is not available.')
+ @testtools.skipUnless(CONF.validation.run_validation,
+ 'SSH required for this test')
+ def test_detach_volume_shelved_or_offload_server(self):
+ self._create_and_attach(shelve_server=True)
+
+ # Detach the volume
+ self._detach(self.server['id'], self.volume['id'])
+ self.attachment = None
+
+ # Unshelve the instance and check that there is only one volume
+ self._unshelve_server_and_check_volumes('1')
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index d1c48c4..92f5ea8 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
@@ -45,7 +43,7 @@
# Creating a nonexistent volume id
# Trying to GET a non existent volume
self.assertRaises(lib_exc.NotFound, self.client.show_volume,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.attr(type=['negative'])
@test.idempotent_id('54a34226-d910-4b00-9ef8-8683e6c55846')
@@ -54,7 +52,7 @@
# Creating nonexistent volume id
# Trying to DELETE a non existent volume
self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.attr(type=['negative'])
@test.idempotent_id('5125ae14-152b-40a7-b3c5-eae15e9022ef')
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index 14f4306..fd56285 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -115,7 +113,7 @@
@test.idempotent_id('38373691-8551-453a-b074-4260ad8298ef')
def test_delete_role_non_existent(self):
# Attempt to delete a non existent role should fail
- non_existent_role = str(uuid.uuid4().hex)
+ non_existent_role = data_utils.rand_uuid_hex()
self.assertRaises(lib_exc.NotFound, self.roles_client.delete_role,
non_existent_role)
@@ -146,7 +144,7 @@
def test_assign_user_role_for_non_existent_role(self):
# Attempt to assign a non existent role to user should fail
(user, tenant, role) = self._get_role_params()
- non_existent_role = str(uuid.uuid4().hex)
+ non_existent_role = data_utils.rand_uuid_hex()
self.assertRaises(lib_exc.NotFound, self.roles_client.assign_user_role,
tenant['id'], user['id'], non_existent_role)
@@ -155,7 +153,7 @@
def test_assign_user_role_for_non_existent_tenant(self):
# Attempt to assign a role on a non existent tenant should fail
(user, tenant, role) = self._get_role_params()
- non_existent_tenant = str(uuid.uuid4().hex)
+ non_existent_tenant = data_utils.rand_uuid_hex()
self.assertRaises(lib_exc.NotFound, self.roles_client.assign_user_role,
non_existent_tenant, user['id'], role['id'])
@@ -205,7 +203,7 @@
self.roles_client.assign_user_role(tenant['id'],
user['id'],
role['id'])
- non_existent_role = str(uuid.uuid4().hex)
+ non_existent_role = data_utils.rand_uuid_hex()
self.assertRaises(lib_exc.NotFound, self.roles_client.delete_user_role,
tenant['id'], user['id'], non_existent_role)
@@ -217,7 +215,7 @@
self.roles_client.assign_user_role(tenant['id'],
user['id'],
role['id'])
- non_existent_tenant = str(uuid.uuid4().hex)
+ non_existent_tenant = data_utils.rand_uuid_hex()
self.assertRaises(lib_exc.NotFound, self.roles_client.delete_user_role,
non_existent_tenant, user['id'], role['id'])
diff --git a/tempest/api/identity/admin/v2/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
index a4c1afc..5169dae 100644
--- a/tempest/api/identity/admin/v2/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -70,7 +68,7 @@
def test_delete_non_existent_tenant(self):
# Attempt to delete a non existent tenant should fail
self.assertRaises(lib_exc.NotFound, self.tenants_client.delete_tenant,
- str(uuid.uuid4().hex))
+ data_utils.rand_uuid_hex())
@test.attr(type=['negative'])
@test.idempotent_id('af16f44b-a849-46cb-9f13-a751c388f739')
@@ -130,7 +128,7 @@
def test_update_non_existent_tenant(self):
# Attempt to update a non existent tenant should fail
self.assertRaises(lib_exc.NotFound, self.tenants_client.update_tenant,
- str(uuid.uuid4().hex))
+ data_utils.rand_uuid_hex())
@test.attr(type=['negative'])
@test.idempotent_id('41704dc5-c5f7-4f79-abfa-76e6fedc570b')
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index dee42b7..46ecba1 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -108,7 +106,7 @@
def test_update_user_for_non_existent_user(self):
# Attempt to update a user non-existent user should fail
user_name = data_utils.rand_name('user')
- non_existent_id = str(uuid.uuid4())
+ non_existent_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound, self.users_client.update_user,
non_existent_id, name=user_name)
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index fc74326..14de8fd 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -14,9 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.image import base
+from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest import test
@@ -38,7 +37,7 @@
@test.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81d9f')
def test_get_non_existent_image(self):
# get the non-existent image
- non_existent_id = str(uuid.uuid4())
+ non_existent_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound, self.client.show_image,
non_existent_id)
@@ -72,7 +71,7 @@
@test.idempotent_id('6fe40f1c-57bd-4918-89cc-8500f850f3de')
def test_delete_non_existing_image(self):
# delete non-existent image
- non_existent_image_id = str(uuid.uuid4())
+ non_existent_image_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound, self.client.delete_image,
non_existent_image_id)
diff --git a/tempest/api/image/v2/test_images_tags_negative.py b/tempest/api/image/v2/test_images_tags_negative.py
index 1aa2d11..dd5650f 100644
--- a/tempest/api/image/v2/test_images_tags_negative.py
+++ b/tempest/api/image/v2/test_images_tags_negative.py
@@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.image import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -27,7 +25,7 @@
def test_update_tags_for_non_existing_image(self):
# Update tag with non existing image.
tag = data_utils.rand_name('tag')
- non_exist_image = str(uuid.uuid4())
+ non_exist_image = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound, self.client.add_image_tag,
non_exist_image, tag)
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index b6f9da7..a5fb25c 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -397,7 +397,7 @@
self.assertEmpty(body['subnets'], "Public subnets visible")
-class BulkNetworkOpsTestJSON(base.BaseNetworkTest):
+class BulkNetworkOpsTest(base.BaseNetworkTest):
"""Tests the following operations in the Neutron API:
bulk network creation
@@ -520,11 +520,11 @@
self.assertIn(n['id'], ports_list)
-class BulkNetworkOpsIpV6TestJSON(BulkNetworkOpsTestJSON):
+class BulkNetworkOpsIpV6Test(BulkNetworkOpsTest):
_ip_version = 6
-class NetworksIpV6TestJSON(NetworksTest):
+class NetworksIpV6Test(NetworksTest):
_ip_version = 6
@test.idempotent_id('e41a4888-65a6-418c-a095-f7c2ef4ad59a')
@@ -576,7 +576,7 @@
'Subnet are not in the same network')
-class NetworksIpV6TestAttrs(NetworksIpV6TestJSON):
+class NetworksIpV6TestAttrs(NetworksIpV6Test):
@classmethod
def skip_checks(cls):
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 86d0b46..b9765c8 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -13,10 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.network import base_security_groups as base
from tempest import config
+from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest import test
@@ -36,7 +35,7 @@
@test.attr(type=['negative'])
@test.idempotent_id('424fd5c3-9ddc-486a-b45f-39bf0c820fc6')
def test_show_non_existent_security_group(self):
- non_exist_id = str(uuid.uuid4())
+ non_exist_id = data_utils.rand_uuid()
self.assertRaises(
lib_exc.NotFound, self.security_groups_client.show_security_group,
non_exist_id)
@@ -44,7 +43,7 @@
@test.attr(type=['negative'])
@test.idempotent_id('4c094c09-000b-4e41-8100-9617600c02a6')
def test_show_non_existent_security_group_rule(self):
- non_exist_id = str(uuid.uuid4())
+ non_exist_id = data_utils.rand_uuid()
self.assertRaises(
lib_exc.NotFound,
self.security_group_rules_client.show_security_group_rule,
@@ -53,7 +52,7 @@
@test.attr(type=['negative'])
@test.idempotent_id('1f1bb89d-5664-4956-9fcd-83ee0fa603df')
def test_delete_non_existent_security_group(self):
- non_exist_id = str(uuid.uuid4())
+ non_exist_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound,
self.security_groups_client.delete_security_group,
non_exist_id
@@ -91,7 +90,7 @@
@test.idempotent_id('4bf786fd-2f02-443c-9716-5b98e159a49a')
def test_create_security_group_rule_with_non_existent_remote_groupid(self):
group_create_body, _ = self._create_security_group()
- non_exist_id = str(uuid.uuid4())
+ non_exist_id = data_utils.rand_uuid()
# Create rule with non existent remote_group_id
group_ids = ['bad_group_id', non_exist_id]
@@ -204,7 +203,7 @@
@test.idempotent_id('be308db6-a7cf-4d5c-9baf-71bafd73f35e')
def test_create_security_group_rule_with_non_existent_security_group(self):
# Create security group rules with not existing security group.
- non_existent_sg = str(uuid.uuid4())
+ non_existent_sg = data_utils.rand_uuid()
self.assertRaises(
lib_exc.NotFound,
self.security_group_rules_client.create_security_group_rule,
diff --git a/tempest/api/telemetry/test_alarming_api_negative.py b/tempest/api/telemetry/test_alarming_api_negative.py
index 0701b54..3e34f8b 100644
--- a/tempest/api/telemetry/test_alarming_api_negative.py
+++ b/tempest/api/telemetry/test_alarming_api_negative.py
@@ -17,8 +17,6 @@
from tempest.lib import exceptions as lib_exc
from tempest import test
-import uuid
-
class TelemetryAlarmingNegativeTest(base.BaseAlarmingTest):
"""Negative tests for show_alarm, update_alarm, show_alarm_history tests
@@ -33,7 +31,7 @@
@test.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81e7d')
def test_get_non_existent_alarm(self):
# get the non-existent alarm
- non_existent_id = str(uuid.uuid4())
+ non_existent_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
non_existent_id)
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index 29ce2e7..f3e52e9 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.volume import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -53,7 +51,7 @@
self.assertRaises(
lib_exc.BadRequest,
self.volume_types_client.update_volume_type_extra_specs,
- self.volume_type['id'], str(uuid.uuid4()),
+ self.volume_type['id'], data_utils.rand_uuid(),
extra_spec)
@test.idempotent_id('9bf7a657-b011-4aec-866d-81c496fbe5c8')
@@ -84,7 +82,7 @@
self.assertRaises(
lib_exc.NotFound,
self.volume_types_client.create_volume_type_extra_specs,
- str(uuid.uuid4()), extra_specs)
+ data_utils.rand_uuid(), extra_specs)
@test.idempotent_id('c821bdc8-43a4-4bf4-86c8-82f3858d5f7d')
def test_create_none_body(self):
@@ -110,7 +108,7 @@
self.assertRaises(
lib_exc.NotFound,
self.volume_types_client.delete_volume_type_extra_specs,
- str(uuid.uuid4()), extra_specs.keys()[0])
+ data_utils.rand_uuid(), extra_specs.keys()[0])
@test.idempotent_id('dee5cf0c-cdd6-4353-b70c-e847050d71fb')
def test_list_nonexistent_volume_type_id(self):
@@ -118,7 +116,7 @@
self.assertRaises(
lib_exc.NotFound,
self.volume_types_client.list_volume_types_extra_specs,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.idempotent_id('9f402cbd-1838-4eb4-9554-126a6b1908c9')
def test_get_nonexistent_volume_type_id(self):
@@ -127,7 +125,7 @@
self.assertRaises(
lib_exc.NotFound,
self.volume_types_client.show_volume_type_extra_specs,
- str(uuid.uuid4()), extra_specs.keys()[0])
+ data_utils.rand_uuid(), extra_specs.keys()[0])
@test.idempotent_id('c881797d-12ff-4f1a-b09d-9f6212159753')
def test_get_nonexistent_extra_spec_id(self):
@@ -136,7 +134,7 @@
self.assertRaises(
lib_exc.NotFound,
self.volume_types_client.show_volume_type_extra_specs,
- self.volume_type['id'], str(uuid.uuid4()))
+ self.volume_type['id'], data_utils.rand_uuid())
class ExtraSpecsNegativeV1Test(ExtraSpecsNegativeV2Test):
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index bccf20e..aff5466 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -13,9 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.volume import base
+from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest import test
@@ -26,8 +25,8 @@
def test_create_with_nonexistent_volume_type(self):
# Should not be able to create volume with nonexistent volume_type.
self.name_field = self.special_fields['name_field']
- params = {self.name_field: str(uuid.uuid4()),
- 'volume_type': str(uuid.uuid4())}
+ params = {self.name_field: data_utils.rand_uuid(),
+ 'volume_type': data_utils.rand_uuid()}
self.assertRaises(lib_exc.NotFound,
self.volumes_client.create_volume, **params)
@@ -42,14 +41,14 @@
# Should not be able to get volume type with nonexistent type id.
self.assertRaises(lib_exc.NotFound,
self.volume_types_client.show_volume_type,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.idempotent_id('6b3926d2-7d73-4896-bc3d-e42dfd11a9f6')
def test_delete_nonexistent_type_id(self):
# Should not be able to delete volume type with nonexistent type id.
self.assertRaises(lib_exc.NotFound,
self.volume_types_client.delete_volume_type,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
class VolumeTypesNegativeV1Test(VolumeTypesNegativeV2Test):
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 9c67579..e52216f 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -17,6 +17,7 @@
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
+from tempest.lib import exceptions
from tempest import test
import testtools
@@ -34,7 +35,6 @@
@classmethod
def resource_setup(cls):
super(VolumesV2ActionsTest, cls).resource_setup()
-
# Create a test shared instance
srv_name = data_utils.rand_name(cls.__name__ + '-Instance')
cls.server = cls.create_server(
@@ -61,10 +61,10 @@
@test.services('compute')
def test_attach_detach_volume_to_instance(self):
# Volume is attached and detached successfully from an instance
- mountpoint = '/dev/vdc'
self.client.attach_volume(self.volume['id'],
instance_uuid=self.server['id'],
- mountpoint=mountpoint)
+ mountpoint='/dev/%s' %
+ CONF.compute.volume_device_name)
waiters.wait_for_volume_status(self.client,
self.volume['id'], 'in-use')
self.client.detach_volume(self.volume['id'])
@@ -90,10 +90,10 @@
@test.services('compute')
def test_get_volume_attachment(self):
# Verify that a volume's attachment information is retrieved
- mountpoint = '/dev/vdc'
self.client.attach_volume(self.volume['id'],
instance_uuid=self.server['id'],
- mountpoint=mountpoint)
+ mountpoint='/dev/%s' %
+ CONF.compute.volume_device_name)
waiters.wait_for_volume_status(self.client,
self.volume['id'], 'in-use')
# NOTE(gfidente): added in reverse order because functions will be
@@ -105,7 +105,9 @@
volume = self.client.show_volume(self.volume['id'])['volume']
self.assertIn('attachments', volume)
attachment = self.client.get_attachment_from_volume(volume)
- self.assertEqual(mountpoint, attachment['device'])
+ self.assertEqual('/dev/%s' %
+ CONF.compute.volume_device_name,
+ attachment['device'])
self.assertEqual(self.server['id'], attachment['server_id'])
self.assertEqual(self.volume['id'], attachment['id'])
self.assertEqual(self.volume['id'], attachment['volume_id'])
@@ -122,11 +124,19 @@
self.volume['id'], image_name=image_name,
disk_format=CONF.volume.disk_format)['os-volume_upload_image']
image_id = body["image_id"]
- self.addCleanup(self.image_client.delete_image, image_id)
+ self.addCleanup(self._cleanup_image, image_id)
self.image_client.wait_for_image_status(image_id, 'active')
waiters.wait_for_volume_status(self.client,
self.volume['id'], 'available')
+ def _cleanup_image(self, image_id):
+ # Ignores the image deletion
+ # in the case that image wasn't created in the first place
+ try:
+ self.image_client.delete_image(image_id)
+ except exceptions.NotFound:
+ pass
+
@test.idempotent_id('92c4ef64-51b2-40c0-9f7e-4749fbaaba33')
def test_reserve_unreserve_volume(self):
# Mark volume as reserved.
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 1b5e72a..77bfaf1 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.volume import base
from tempest.common.utils import data_utils
from tempest.common import waiters
@@ -44,14 +42,14 @@
def test_volume_get_nonexistent_volume_id(self):
# Should not be able to get a non-existent volume
self.assertRaises(lib_exc.NotFound, self.client.show_volume,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.attr(type=['negative'])
@test.idempotent_id('555efa6e-efcd-44ef-8a3b-4a7ca4837a29')
def test_volume_delete_nonexistent_volume_id(self):
# Should not be able to delete a non-existent Volume
self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.attr(type=['negative'])
@test.idempotent_id('1ed83a8a-682d-4dfb-a30e-ee63ffd6c049')
@@ -98,7 +96,7 @@
v_name = data_utils.rand_name('Volume')
metadata = {'Type': 'work'}
self.assertRaises(lib_exc.NotFound, self.client.create_volume,
- size='1', volume_type=str(uuid.uuid4()),
+ size='1', volume_type=data_utils.rand_uuid(),
display_name=v_name, metadata=metadata)
@test.attr(type=['negative'])
@@ -108,7 +106,7 @@
v_name = data_utils.rand_name('Volume')
metadata = {'Type': 'work'}
self.assertRaises(lib_exc.NotFound, self.client.create_volume,
- size='1', snapshot_id=str(uuid.uuid4()),
+ size='1', snapshot_id=data_utils.rand_uuid(),
display_name=v_name, metadata=metadata)
@test.attr(type=['negative'])
@@ -118,7 +116,7 @@
v_name = data_utils.rand_name('Volume')
metadata = {'Type': 'work'}
self.assertRaises(lib_exc.NotFound, self.client.create_volume,
- size='1', source_volid=str(uuid.uuid4()),
+ size='1', source_volid=data_utils.rand_uuid(),
display_name=v_name, metadata=metadata)
@test.attr(type=['negative'])
@@ -127,7 +125,8 @@
v_name = data_utils.rand_name('Volume')
metadata = {'Type': 'work'}
self.assertRaises(lib_exc.NotFound, self.client.update_volume,
- volume_id=str(uuid.uuid4()), display_name=v_name,
+ volume_id=data_utils.rand_uuid(),
+ display_name=v_name,
metadata=metadata)
@test.attr(type=['negative'])
@@ -188,7 +187,7 @@
self.assertRaises(lib_exc.NotFound,
self.client.attach_volume,
- str(uuid.uuid4()),
+ data_utils.rand_uuid(),
instance_uuid=server['id'],
mountpoint=self.mountpoint)
@@ -229,7 +228,7 @@
# Extend volume size when volume is nonexistent.
extend_size = int(self.volume['size']) + 1
self.assertRaises(lib_exc.NotFound, self.client.extend_volume,
- str(uuid.uuid4()), new_size=extend_size)
+ data_utils.rand_uuid(), new_size=extend_size)
@test.attr(type=['negative'])
@test.idempotent_id('aff8ba64-6d6f-4f2e-bc33-41a08ee9f115')
@@ -244,14 +243,14 @@
def test_reserve_volume_with_nonexistent_volume_id(self):
self.assertRaises(lib_exc.NotFound,
self.client.reserve_volume,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.attr(type=['negative'])
@test.idempotent_id('eb467654-3dc1-4a72-9b46-47c29d22654c')
def test_unreserve_volume_with_nonexistent_volume_id(self):
self.assertRaises(lib_exc.NotFound,
self.client.unreserve_volume,
- str(uuid.uuid4()))
+ data_utils.rand_uuid())
@test.attr(type=['negative'])
@test.idempotent_id('449c4ed2-ecdd-47bb-98dc-072aeccf158c')
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 347877c..866e676 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -68,10 +68,9 @@
name=server_name,
wait_until='ACTIVE')
self.addCleanup(self.servers_client.delete_server, server['id'])
- mountpoint = '/dev/%s' % CONF.compute.volume_device_name
self.servers_client.attach_volume(
server['id'], volumeId=self.volume_origin['id'],
- device=mountpoint)
+ device='/dev/%s' % CONF.compute.volume_device_name)
waiters.wait_for_volume_status(self.volumes_client,
self.volume_origin['id'], 'in-use')
self.addCleanup(waiters.wait_for_volume_status, self.volumes_client,
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index 54459ac..374979c 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -10,8 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from tempest.api.volume import base
from tempest.common.utils import data_utils
from tempest import config
@@ -36,7 +34,8 @@
s_name = data_utils.rand_name('snap')
self.assertRaises(lib_exc.NotFound,
self.snapshots_client.create_snapshot,
- volume_id=str(uuid.uuid4()), display_name=s_name)
+ volume_id=data_utils.rand_uuid(),
+ display_name=s_name)
@test.attr(type=['negative'])
@test.idempotent_id('bb9da53e-d335-4309-9c15-7e76fd5e4d6d')
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 6568627..1fa54c2 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -14,9 +14,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+import random
from six.moves.urllib import parse
from tempest.api.volume import base
+from tempest.lib import decorators
from tempest import test
@@ -185,3 +187,29 @@
@test.idempotent_id('af55e775-8e4b-4feb-8719-215c43b0238c')
def test_volume_list_pagination(self):
self._test_pagination('volumes', ids=self.volume_id_list, detail=False)
+
+ @test.idempotent_id('46eff077-100b-427f-914e-3db2abcdb7e2')
+ @decorators.skip_because(bug='1572765')
+ def test_volume_list_with_detail_param_marker(self):
+ # Choosing a random volume from a list of volumes for 'marker'
+ # parameter
+ random_volume = random.choice(self.volume_id_list)
+
+ params = {'marker': random_volume}
+
+ # Running volume list using marker parameter
+ vol_with_marker = self.client.list_volumes(detail=True,
+ params=params)['volumes']
+
+ # Fetching the index of the random volume from volume_id_list
+ index_marker = self.volume_id_list.index(random_volume)
+
+ # The expected list with marker parameter
+ verify_volume_list = self.volume_id_list[:index_marker]
+
+ failed_msg = "Failed to list volume details by marker"
+
+ # Validating the expected list is the same like the observed list
+ self.assertEqual(verify_volume_list,
+ map(lambda x: x['id'],
+ vol_with_marker[::-1]), failed_msg)
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index a154d0b..5fab961 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -262,7 +262,7 @@
user = identity.get_user_by_username(tenants_admin,
tenant['id'], u['name'])
except tempest.lib.exceptions.NotFound:
- LOG.error("User: %s - not found" % u['user'])
+ LOG.error("User: %s - not found" % u['name'])
continue
for r in u['role_ids']:
try:
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 0ba322d..3ef04f5 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -15,7 +15,6 @@
# under the License.
import argparse
-import httplib2
import os
import sys
import traceback
@@ -29,6 +28,7 @@
from tempest import clients
from tempest.common import credentials_factory as credentials
from tempest import config
+import tempest.lib.common.http
CONF = config.CONF
@@ -91,11 +91,12 @@
}
client_dict[service].skip_path()
endpoint = _get_unversioned_endpoint(client_dict[service].base_url)
- dscv = CONF.identity.disable_ssl_certificate_validation
- ca_certs = CONF.identity.ca_certificates_file
- raw_http = httplib2.Http(disable_ssl_certificate_validation=dscv,
- ca_certs=ca_certs)
- __, body = raw_http.request(endpoint, 'GET')
+
+ http = tempest.lib.common.http.ClosingHttp(
+ CONF.identity.disable_ssl_certificate_validation,
+ CONF.identity.ca_certificates_file)
+
+ __, body = http.request(endpoint, 'GET')
client_dict[service].reset_path()
try:
body = json.loads(body)
@@ -364,7 +365,16 @@
CONF_PARSER = moves.configparser.SafeConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
- icreds = credentials.get_credentials_provider('verify_tempest_config')
+
+ # Indicate not to create network resources as part of getting credentials
+ net_resources = {
+ 'network': False,
+ 'router': False,
+ 'subnet': False,
+ 'dhcp': False
+ }
+ icreds = credentials.get_credentials_provider(
+ 'verify_tempest_config', network_resources=net_resources)
try:
os = clients.Manager(icreds.get_primary_creds())
services = check_service_availability(os, update)
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index b5c4547..7ebc283 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -157,3 +157,29 @@
% server['id'])
return body, servers
+
+
+def shelve_server(client, server_id, force_shelve_offload=False):
+ """Common wrapper utility to shelve server.
+
+ This method is a common wrapper to make server in 'SHELVED'
+ or 'SHELVED_OFFLOADED' state.
+
+ :param server_id: Server to make in shelve state
+ :param force_shelve_offload: Forcefully offload shelve server if it
+ is configured not to offload server
+ automatically after offload time.
+ """
+ client.shelve_server(server_id)
+
+ offload_time = CONF.compute.shelved_offload_time
+ if offload_time >= 0:
+ waiters.wait_for_server_status(client, server_id,
+ 'SHELVED_OFFLOADED',
+ extra_timeout=offload_time)
+ else:
+ waiters.wait_for_server_status(client, server_id, 'SHELVED')
+ if force_shelve_offload:
+ client.shelve_offload_server(server_id)
+ waiters.wait_for_server_status(client, server_id,
+ 'SHELVED_OFFLOADED')
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 58157ef..3923aec 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -133,7 +133,7 @@
def get_creds_by_roles(self, roles, force_new=False):
msg = "Credentials being specified through the config file can not be"\
" used with tests that specify using credentials by roles. "\
- "Either exclude/skip the tests doing this or use either an "\
+ "Either exclude/skip the tests doing this or use either a "\
"test_accounts_file or dynamic credentials."
raise exceptions.InvalidConfiguration(msg)
diff --git a/tempest/config.py b/tempest/config.py
index 910f110..67c8c9e 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -91,7 +91,7 @@
"create users and projects",
deprecated_group='identity'),
cfg.StrOpt('admin_project_name',
- help="Project name to use for an administrative user. This is "
+ help="Project name to use for an administrative user. This is "
"needed for authenticating requests made by project "
"isolation to create users and projects",
deprecated_opts=[cfg.DeprecatedOpt('admin_tenant_name',
@@ -99,7 +99,7 @@
cfg.DeprecatedOpt('admin_tenant_name',
group='identity')]),
cfg.StrOpt('admin_password',
- help="Password to use for an administrative user. This is "
+ help="Password to use for an administrative user. This is "
"needed for authenticating requests made by project "
"isolation to create users and projects",
secret=True,
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 031df7f..b8e052f 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -82,11 +82,6 @@
message = "Image %(image_id)s failed to become ACTIVE in the allotted time"
-class EC2RegisterImageException(TempestException):
- message = ("Image %(image_id)s failed to become 'available' "
- "in the allotted time")
-
-
class VolumeBuildErrorException(TempestException):
message = "Volume %(volume_id)s failed to build and is in ERROR status"
@@ -108,25 +103,10 @@
"due to '%(stack_status_reason)s'")
-class StackResourceBuildErrorException(TempestException):
- message = ("Resource %(resource_name)s in stack %(stack_identifier)s is "
- "in %(resource_status)s status due to "
- "'%(resource_status_reason)s'")
-
-
-class AuthenticationFailure(TempestException):
- message = ("Authentication with user %(user)s and password "
- "%(password)s failed auth using tenant %(tenant)s.")
-
-
class EndpointNotFound(TempestException):
message = "Endpoint not found"
-class ImageFault(TempestException):
- message = "Got image fault"
-
-
class IdentityError(TempestException):
message = "Got identity error"
@@ -135,10 +115,6 @@
message = "The server is not reachable via the configured network"
-class TearDownException(TempestException):
- message = "%(num)d cleanUp operation failed"
-
-
# NOTE(andreaf) This exception is added here to facilitate the migration
# of get_network_from_name and preprov_creds to tempest-lib, and it should
# be migrated along with them
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index d1bc141..d0e1fcb 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -119,11 +119,6 @@
T108
"""
- if './tempest/api/network/' in filename:
- # Network API tests are migrating from Tempest to Neutron repo now.
- # So here should avoid network API tests checks.
- return
-
msg = "T108: hyphen should not be specified at the end of rand_name()"
if RAND_NAME_HYPHEN_RE.match(logical_line):
return 0, msg
@@ -246,6 +241,22 @@
yield (0, msg)
+def use_rand_uuid_instead_of_uuid4(logical_line, filename):
+ """Check that tests use data_utils.rand_uuid() instead of uuid.uuid4()
+
+ T113
+ """
+ if 'tempest/lib/' in filename:
+ return
+
+ if 'uuid.uuid4()' not in logical_line:
+ return
+
+ msg = ("T113: Tests should use data_utils.rand_uuid()/rand_uuid_hex() "
+ "instead of uuid.uuid4()/uuid.uuid4().hex")
+ yield (0, msg)
+
+
def factory(register):
register(import_no_clients_in_api_and_scenario_tests)
register(scenario_tests_need_service_tags)
@@ -258,3 +269,4 @@
register(get_resources_on_service_clients)
register(delete_resources_on_service_clients)
register(dont_import_local_tempest_into_lib)
+ register(use_rand_uuid_instead_of_uuid4)
diff --git a/tempest/lib/api_schema/response/compute/v2_19/__init__.py b/tempest/lib/api_schema/response/compute/v2_19/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_19/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_19/servers.py b/tempest/lib/api_schema/response/compute/v2_19/servers.py
new file mode 100644
index 0000000..883839e
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_19/servers.py
@@ -0,0 +1,49 @@
+# Copyright 2016 NEC Corporation. All rights reserved.
+#
+# 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.
+
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import servers as serversv21
+from tempest.lib.api_schema.response.compute.v2_9 import servers as serversv29
+
+get_server = copy.deepcopy(serversv29.get_server)
+get_server['response_body']['properties']['server'][
+ 'properties'].update({'description': {'type': ['string', 'null']}})
+get_server['response_body']['properties']['server'][
+ 'required'].append('description')
+
+list_servers_detail = copy.deepcopy(serversv29.list_servers_detail)
+list_servers_detail['response_body']['properties']['servers']['items'][
+ 'properties'].update({'description': {'type': ['string', 'null']}})
+list_servers_detail['response_body']['properties']['servers']['items'][
+ 'required'].append('description')
+
+update_server = copy.deepcopy(serversv21.update_server)
+update_server['response_body']['properties']['server'][
+ 'properties'].update({'description': {'type': ['string', 'null']}})
+update_server['response_body']['properties']['server'][
+ 'required'].append('description')
+
+rebuild_server = copy.deepcopy(serversv21.rebuild_server)
+rebuild_server['response_body']['properties']['server'][
+ 'properties'].update({'description': {'type': ['string', 'null']}})
+rebuild_server['response_body']['properties']['server'][
+ 'required'].append('description')
+
+rebuild_server_with_admin_pass = copy.deepcopy(
+ serversv21.rebuild_server_with_admin_pass)
+rebuild_server_with_admin_pass['response_body']['properties']['server'][
+ 'properties'].update({'description': {'type': ['string', 'null']}})
+rebuild_server_with_admin_pass['response_body']['properties']['server'][
+ 'required'].append('description')
diff --git a/tempest/lib/api_schema/response/compute/v2_9/__init__.py b/tempest/lib/api_schema/response/compute/v2_9/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_9/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_9/servers.py b/tempest/lib/api_schema/response/compute/v2_9/servers.py
new file mode 100644
index 0000000..e9b7249
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_9/servers.py
@@ -0,0 +1,29 @@
+# Copyright 2016 NEC Corporation. All rights reserved.
+#
+# 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.
+
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import servers
+
+get_server = copy.deepcopy(servers.get_server)
+get_server['response_body']['properties']['server'][
+ 'properties'].update({'locked': {'type': 'boolean'}})
+get_server['response_body']['properties']['server'][
+ 'required'].append('locked')
+
+list_servers_detail = copy.deepcopy(servers.list_servers_detail)
+list_servers_detail['response_body']['properties']['servers']['items'][
+ 'properties'].update({'locked': {'type': 'boolean'}})
+list_servers_detail['response_body']['properties']['servers']['items'][
+ 'required'].append('locked')
diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py
index 71c4f4f..a6833be 100644
--- a/tempest/lib/auth.py
+++ b/tempest/lib/auth.py
@@ -31,6 +31,39 @@
LOG = logging.getLogger(__name__)
+def replace_version(url, new_version):
+ parts = urlparse.urlparse(url)
+ version_path = '/%s' % new_version
+ path, subs = re.subn(r'(^|/)+v\d+(?:\.\d+)?',
+ version_path,
+ parts.path,
+ count=1)
+ if not subs:
+ path = '%s%s' % (parts.path.rstrip('/'), version_path)
+ url = urlparse.urlunparse((parts.scheme,
+ parts.netloc,
+ path,
+ parts.params,
+ parts.query,
+ parts.fragment))
+ return url
+
+
+def apply_url_filters(url, filters):
+ if filters.get('api_version', None) is not None:
+ url = replace_version(url, filters['api_version'])
+ parts = urlparse.urlparse(url)
+ if filters.get('skip_path', None) is not None and parts.path != '':
+ url = urlparse.urlunparse((parts.scheme,
+ parts.netloc,
+ '/',
+ parts.params,
+ parts.query,
+ parts.fragment))
+
+ return url
+
+
@six.add_metaclass(abc.ABCMeta)
class AuthProvider(object):
"""Provide authentication"""
@@ -322,29 +355,7 @@
raise exceptions.EndpointNotFound(
"service: %s, region: %s, endpoint_type: %s" %
(service, region, endpoint_type))
-
- parts = urlparse.urlparse(_base_url)
- if filters.get('api_version', None) is not None:
- version_path = '/%s' % filters['api_version']
- path = re.sub(r'(^|/)+v\d+(?:\.\d+)?',
- version_path,
- parts.path,
- count=1)
- _base_url = urlparse.urlunparse((parts.scheme,
- parts.netloc,
- path or version_path,
- parts.params,
- parts.query,
- parts.fragment))
- if filters.get('skip_path', None) is not None and parts.path != '':
- _base_url = urlparse.urlunparse((parts.scheme,
- parts.netloc,
- '/',
- parts.params,
- parts.query,
- parts.fragment))
-
- return _base_url
+ return apply_url_filters(_base_url, filters)
def is_expired(self, auth_data):
_, access = auth_data
@@ -455,29 +466,7 @@
_base_url = filtered_catalog[0].get('url', None)
if _base_url is None:
raise exceptions.EndpointNotFound(service)
-
- parts = urlparse.urlparse(_base_url)
- if filters.get('api_version', None) is not None:
- version_path = '/%s' % filters['api_version']
- path = re.sub(r'(^|/)+v\d+(?:\.\d+)?',
- version_path,
- parts.path,
- count=1)
- _base_url = urlparse.urlunparse((parts.scheme,
- parts.netloc,
- path or version_path,
- parts.params,
- parts.query,
- parts.fragment))
- if filters.get('skip_path', None) is not None:
- _base_url = urlparse.urlunparse((parts.scheme,
- parts.netloc,
- '/',
- parts.params,
- parts.query,
- parts.fragment))
-
- return _base_url
+ return apply_url_filters(_base_url, filters)
def is_expired(self, auth_data):
_, access = auth_data
diff --git a/tempest/lib/common/http.py b/tempest/lib/common/http.py
index b3793bc..dffc5f9 100644
--- a/tempest/lib/common/http.py
+++ b/tempest/lib/common/http.py
@@ -1,5 +1,4 @@
-# Copyright 2013 OpenStack Foundation
-# Copyright 2013 Citrix Systems, Inc.
+# Copyright 2016 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -14,12 +13,43 @@
# License for the specific language governing permissions and limitations
# under the License.
-import httplib2
+import urllib3
-class ClosingHttp(httplib2.Http):
- def request(self, *args, **kwargs):
+class ClosingHttp(urllib3.poolmanager.PoolManager):
+ def __init__(self, disable_ssl_certificate_validation=False,
+ ca_certs=None):
+ kwargs = {}
+
+ if disable_ssl_certificate_validation:
+ urllib3.disable_warnings()
+ kwargs['cert_reqs'] = 'CERT_NONE'
+
+ if ca_certs:
+ kwargs['cert_reqs'] = 'CERT_REQUIRED'
+ kwargs['ca_certs'] = ca_certs
+
+ super(ClosingHttp, self).__init__(**kwargs)
+
+ def request(self, url, method, *args, **kwargs):
+
+ class Response(dict):
+ def __init__(self, info):
+ for key, value in info.getheaders().items():
+ self[key.lower()] = value
+ self.status = info.status
+ self['status'] = str(self.status)
+ self.reason = info.reason
+ self.version = info.version
+ self['content-location'] = url
+
original_headers = kwargs.get('headers', {})
new_headers = dict(original_headers, connection='close')
new_kwargs = dict(kwargs, headers=new_headers)
- return super(ClosingHttp, self).request(*args, **new_kwargs)
+
+ # Follow up to 5 redirections. Don't raise an exception if
+ # it's exceeded but return the HTTP 3XX response instead.
+ retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
+ r = super(ClosingHttp, self).request(method, url, retries=retry,
+ *args, **new_kwargs)
+ return Response(r), r.data
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index 511dd08..a831dbd 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -117,56 +117,56 @@
"""
ssh = self._get_ssh_connection()
transport = ssh.get_transport()
- channel = transport.open_session()
- channel.fileno() # Register event pipe
- channel.exec_command(cmd)
- channel.shutdown_write()
- exit_status = channel.recv_exit_status()
+ with transport.open_session() as channel:
+ channel.fileno() # Register event pipe
+ channel.exec_command(cmd)
+ channel.shutdown_write()
+ exit_status = channel.recv_exit_status()
- # If the executing host is linux-based, poll the channel
- if self._can_system_poll():
- out_data_chunks = []
- err_data_chunks = []
- poll = select.poll()
- poll.register(channel, select.POLLIN)
- start_time = time.time()
+ # If the executing host is linux-based, poll the channel
+ if self._can_system_poll():
+ out_data_chunks = []
+ err_data_chunks = []
+ poll = select.poll()
+ poll.register(channel, select.POLLIN)
+ start_time = time.time()
- while True:
- ready = poll.poll(self.channel_timeout)
- if not any(ready):
- if not self._is_timed_out(start_time):
+ while True:
+ ready = poll.poll(self.channel_timeout)
+ if not any(ready):
+ if not self._is_timed_out(start_time):
+ continue
+ raise exceptions.TimeoutException(
+ "Command: '{0}' executed on host '{1}'.".format(
+ cmd, self.host))
+ if not ready[0]: # If there is nothing to read.
continue
- raise exceptions.TimeoutException(
- "Command: '{0}' executed on host '{1}'.".format(
- cmd, self.host))
- if not ready[0]: # If there is nothing to read.
- continue
- out_chunk = err_chunk = None
- if channel.recv_ready():
- out_chunk = channel.recv(self.buf_size)
- out_data_chunks += out_chunk,
- if channel.recv_stderr_ready():
- err_chunk = channel.recv_stderr(self.buf_size)
- err_data_chunks += err_chunk,
- if channel.closed and not err_chunk and not out_chunk:
- break
- out_data = b''.join(out_data_chunks)
- err_data = b''.join(err_data_chunks)
- # Just read from the channels
- else:
- out_file = channel.makefile('rb', self.buf_size)
- err_file = channel.makefile_stderr('rb', self.buf_size)
- out_data = out_file.read()
- err_data = err_file.read()
- if encoding:
- out_data = out_data.decode(encoding)
- err_data = err_data.decode(encoding)
+ out_chunk = err_chunk = None
+ if channel.recv_ready():
+ out_chunk = channel.recv(self.buf_size)
+ out_data_chunks += out_chunk,
+ if channel.recv_stderr_ready():
+ err_chunk = channel.recv_stderr(self.buf_size)
+ err_data_chunks += err_chunk,
+ if not err_chunk and not out_chunk:
+ break
+ out_data = b''.join(out_data_chunks)
+ err_data = b''.join(err_data_chunks)
+ # Just read from the channels
+ else:
+ out_file = channel.makefile('rb', self.buf_size)
+ err_file = channel.makefile_stderr('rb', self.buf_size)
+ out_data = out_file.read()
+ err_data = err_file.read()
+ if encoding:
+ out_data = out_data.decode(encoding)
+ err_data = err_data.decode(encoding)
- if 0 != exit_status:
- raise exceptions.SSHExecCommandFailed(
- command=cmd, exit_status=exit_status,
- stderr=err_data, stdout=out_data)
- return out_data
+ if 0 != exit_status:
+ raise exceptions.SSHExecCommandFailed(
+ command=cmd, exit_status=exit_status,
+ stderr=err_data, stdout=out_data)
+ return out_data
def test_connection_auth(self):
"""Raises an exception when we can not connect to server via ssh."""
diff --git a/tempest/lib/services/compute/images_client.py b/tempest/lib/services/compute/images_client.py
index 4a55ce7..da8a61e 100644
--- a/tempest/lib/services/compute/images_client.py
+++ b/tempest/lib/services/compute/images_client.py
@@ -131,8 +131,10 @@
return rest_client.ResponseBody(resp, body)
def is_resource_deleted(self, id):
+ # Added status check for user with admin role
try:
- self.show_image(id)
+ if self.show_image(id)['image']['status'] == 'DELETED':
+ return True
except lib_exc.NotFound:
return True
return False
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index a37f167..0472eda 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -20,11 +20,17 @@
from six.moves.urllib import parse as urllib
from tempest.lib.api_schema.response.compute.v2_1 import servers as schema
+from tempest.lib.api_schema.response.compute.v2_19 import servers as schemav219
+from tempest.lib.api_schema.response.compute.v2_9 import servers as schemav29
from tempest.lib.common import rest_client
from tempest.lib.services.compute import base_compute_client
class ServersClient(base_compute_client.BaseComputeClient):
+ schema_versions_info = [
+ {'min': None, 'max': '2.8', 'schema': schema},
+ {'min': '2.9', 'max': '2.18', 'schema': schemav29},
+ {'min': '2.19', 'max': None, 'schema': schemav219}]
def __init__(self, auth_provider, service, region,
enable_instance_password=True, **kwargs):
@@ -88,6 +94,7 @@
post_body = json.dumps({'server': kwargs})
resp, body = self.put("servers/%s" % server_id, post_body)
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.update_server, resp, body)
return rest_client.ResponseBody(resp, body)
@@ -95,6 +102,7 @@
"""Get server details."""
resp, body = self.get("servers/%s" % server_id)
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.get_server, resp, body)
return rest_client.ResponseBody(resp, body)
@@ -114,6 +122,7 @@
"""
url = 'servers'
+ schema = self.get_schema(self.schema_versions_info)
_schema = schema.list_servers
if detail:
@@ -209,6 +218,7 @@
kwargs['imageRef'] = image_ref
if 'disk_config' in kwargs:
kwargs['OS-DCF:diskConfig'] = kwargs.pop('disk_config')
+ schema = self.get_schema(self.schema_versions_info)
if self.enable_instance_password:
rebuild_schema = schema.rebuild_server_with_admin_pass
else:
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 77de47e..6d3ecd4 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -15,6 +15,7 @@
import testtools
+from tempest.common import compute
from tempest.common import waiters
from tempest import config
from tempest.scenario import manager
@@ -35,18 +36,9 @@
"""
def _shelve_then_unshelve_server(self, server):
- self.servers_client.shelve_server(server['id'])
- offload_time = CONF.compute.shelved_offload_time
- if offload_time >= 0:
- waiters.wait_for_server_status(self.servers_client, server['id'],
- 'SHELVED_OFFLOADED',
- extra_timeout=offload_time)
- else:
- waiters.wait_for_server_status(self.servers_client,
- server['id'], 'SHELVED')
- self.servers_client.shelve_offload_server(server['id'])
- waiters.wait_for_server_status(self.servers_client, server['id'],
- 'SHELVED_OFFLOADED')
+ compute.shelve_server(self.servers_client, server['id'],
+ force_shelve_offload=True)
+
self.servers_client.unshelve_server(server['id'])
waiters.wait_for_server_status(self.servers_client, server['id'],
'ACTIVE')
diff --git a/tempest/services/image/v1/json/images_client.py b/tempest/services/image/v1/json/images_client.py
index 3f256ec..e29ff89 100644
--- a/tempest/services/image/v1/json/images_client.py
+++ b/tempest/services/image/v1/json/images_client.py
@@ -213,7 +213,8 @@
def is_resource_deleted(self, id):
try:
- self.get_image_meta(id)
+ if self.get_image_meta(id)['status'] == 'deleted':
+ return True
except lib_exc.NotFound:
return True
return False
diff --git a/tempest/test.py b/tempest/test.py
index 6ba4962..b32beaa 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -19,7 +19,6 @@
import re
import sys
import time
-import uuid
import fixtures
from oslo_log import log as logging
@@ -38,6 +37,7 @@
import tempest.common.validation_resources as vresources
from tempest import config
from tempest import exceptions
+from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
LOG = logging.getLogger(__name__)
@@ -714,10 +714,10 @@
resource = resource['name']
LOG.debug("Add resource to test %s" % resource)
scn_name = "inv_res_%s" % (resource)
- scenario_list.append((scn_name, {"resource": (resource,
- str(uuid.uuid4())),
- "expected_result": expected_result
- }))
+ scenario_list.append((scn_name, {
+ "resource": (resource, data_utils.rand_uuid()),
+ "expected_result": expected_result
+ }))
if schema is not None:
for scenario in generator.generate_scenarios(schema):
scenario_list.append((scenario['_negtest_name'],
diff --git a/tempest/tests/lib/base.py b/tempest/tests/base.py
similarity index 79%
rename from tempest/tests/lib/base.py
rename to tempest/tests/base.py
index fe9268e..ca81d4d 100644
--- a/tempest/tests/lib/base.py
+++ b/tempest/tests/base.py
@@ -14,17 +14,10 @@
import mock
from oslotest import base
-from oslotest import moxstubout
class TestCase(base.BaseTestCase):
- def setUp(self):
- super(TestCase, self).setUp()
- mox_fixture = self.useFixture(moxstubout.MoxStubout())
- self.mox = mox_fixture.mox
- self.stubs = mox_fixture.stubs
-
def patch(self, target, **kwargs):
"""Returns a started `mock.patch` object for the supplied target.
@@ -42,3 +35,15 @@
m = p.start()
self.addCleanup(p.stop)
return m
+
+ def patchobject(self, target, attribute, new=mock.DEFAULT):
+ """Convenient wrapper around `mock.patch.object`
+
+ Returns a started mock that will be automatically stopped after the
+ test ran.
+ """
+
+ p = mock.patch.object(target, attribute, new)
+ m = p.start()
+ self.addCleanup(p.stop)
+ return m
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index b8c9969..2d0256a 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -17,7 +17,7 @@
from tempest.cmd import javelin
from tempest.lib import exceptions as lib_exc
-from tempest.tests.lib import base
+from tempest.tests import base
class JavelinUnitTest(base.TestCase):
diff --git a/tempest/tests/cmd/test_list_plugins.py b/tempest/tests/cmd/test_list_plugins.py
index 782dde7..17ddb18 100644
--- a/tempest/tests/cmd/test_list_plugins.py
+++ b/tempest/tests/cmd/test_list_plugins.py
@@ -14,7 +14,7 @@
import subprocess
-from tempest.tests.lib import base
+from tempest.tests import base
class TestTempestListPlugins(base.TestCase):
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
index 6c5326a..685a0b3 100644
--- a/tempest/tests/cmd/test_tempest_init.py
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -18,7 +18,7 @@
import fixtures
from tempest.cmd import init
-from tempest.tests.lib import base
+from tempest.tests import base
class TestTempestInit(base.TestCase):
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 5d050d1..3b09673 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -19,8 +19,8 @@
from tempest.cmd import verify_tempest_config
from tempest import config
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class TestGetAPIVersions(base.TestCase):
@@ -41,7 +41,8 @@
def setUp(self):
super(TestDiscovery, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
def test_get_keystone_api_versions(self):
self.useFixture(mockpatch.PatchObject(
@@ -49,8 +50,9 @@
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': {'values': [{'id': 'v2.0'}, {'id': 'v3.0'}]}}
fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, fake_resp)))
+ self.useFixture(mockpatch.Patch(
+ 'tempest.lib.common.http.ClosingHttp.request',
+ return_value=(None, fake_resp)))
fake_os = mock.MagicMock()
versions = verify_tempest_config._get_api_versions(fake_os, 'keystone')
self.assertIn('v2.0', versions)
@@ -62,8 +64,9 @@
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v1.0'}, {'id': 'v2.0'}]}
fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, fake_resp)))
+ self.useFixture(mockpatch.Patch(
+ 'tempest.lib.common.http.ClosingHttp.request',
+ return_value=(None, fake_resp)))
fake_os = mock.MagicMock()
versions = verify_tempest_config._get_api_versions(fake_os, 'cinder')
self.assertIn('v1.0', versions)
@@ -75,8 +78,9 @@
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v2.0'}, {'id': 'v3.0'}]}
fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, fake_resp)))
+ self.useFixture(mockpatch.Patch(
+ 'tempest.lib.common.http.ClosingHttp.request',
+ return_value=(None, fake_resp)))
fake_os = mock.MagicMock()
versions = verify_tempest_config._get_api_versions(fake_os, 'nova')
self.assertIn('v2.0', versions)
@@ -95,8 +99,9 @@
sample_body = (
'<html><head>Sample Response</head><body>This is the sample page '
'for the web server. Why are you requesting it?</body></html>')
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, sample_body)))
+ self.useFixture(mockpatch.Patch(
+ 'tempest.lib.common.http.ClosingHttp.request',
+ return_value=(None, sample_body)))
# service value doesn't matter, just needs to match what
# _get_api_versions puts in its client_dict.
@@ -122,14 +127,14 @@
verify_tempest_config.verify_api_versions(fake_os, 'foo', True)
self.assertFalse(verify_mock.called)
- def test_verify_keystone_api_versions_no_v3(self):
+ @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+ def test_verify_keystone_api_versions_no_v3(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': {'values': [{'id': 'v2.0'}]}}
fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, fake_resp)))
+ mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
@@ -138,14 +143,14 @@
'identity-feature-enabled',
False, True)
- def test_verify_keystone_api_versions_no_v2(self):
+ @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+ def test_verify_keystone_api_versions_no_v2(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': {'values': [{'id': 'v3.0'}]}}
fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, fake_resp)))
+ mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
@@ -154,14 +159,14 @@
'identity-feature-enabled',
False, True)
- def test_verify_cinder_api_versions_no_v2(self):
+ @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+ def test_verify_cinder_api_versions_no_v2(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v1.0'}]}
fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, fake_resp)))
+ mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
@@ -169,14 +174,14 @@
print_mock.assert_called_once_with('api_v2', 'volume-feature-enabled',
False, True)
- def test_verify_cinder_api_versions_no_v1(self):
+ @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+ def test_verify_cinder_api_versions_no_v1(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v2.0'}]}
fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.Patch('httplib2.Http.request',
- return_value=(None, fake_resp)))
+ mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
diff --git a/tempest/tests/common/test_admin_available.py b/tempest/tests/common/test_admin_available.py
index c803541..01a9cd0 100644
--- a/tempest/tests/common/test_admin_available.py
+++ b/tempest/tests/common/test_admin_available.py
@@ -17,8 +17,8 @@
from tempest.common import credentials_factory as credentials
from tempest import config
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class TestAdminAvailable(base.TestCase):
@@ -28,7 +28,8 @@
def setUp(self):
super(TestAdminAvailable, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
def run_test(self, dynamic_creds, use_accounts_file, admin_creds):
diff --git a/tempest/tests/common/test_alt_available.py b/tempest/tests/common/test_alt_available.py
index cb1de16..d4cfab6 100644
--- a/tempest/tests/common/test_alt_available.py
+++ b/tempest/tests/common/test_alt_available.py
@@ -17,8 +17,8 @@
from tempest.common import credentials_factory as credentials
from tempest import config
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class TestAltAvailable(base.TestCase):
@@ -28,7 +28,8 @@
def setUp(self):
super(TestAltAvailable, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
def run_test(self, dynamic_creds, use_accounts_file, creds):
diff --git a/tempest/tests/common/test_configured_creds.py b/tempest/tests/common/test_configured_creds.py
index 8c721e6..3c242b3 100644
--- a/tempest/tests/common/test_configured_creds.py
+++ b/tempest/tests/common/test_configured_creds.py
@@ -21,9 +21,9 @@
from tempest.lib import exceptions as lib_exc
from tempest.lib.services.identity.v2 import token_client as v2_client
from tempest.lib.services.identity.v3 import token_client as v3_client
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests import fake_identity
-from tempest.tests.lib import base
+from tempest.tests.lib import fake_identity
class ConfiguredV2CredentialsTests(base.TestCase):
@@ -41,9 +41,10 @@
def setUp(self):
super(ConfiguredV2CredentialsTests, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
- self.stubs.Set(self.tokenclient_class, 'raw_request',
- self.identity_response)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
+ self.patchobject(self.tokenclient_class, 'raw_request',
+ self.identity_response)
def _get_credentials(self, attributes=None):
if attributes is None:
diff --git a/tempest/tests/common/test_credentials.py b/tempest/tests/common/test_credentials.py
index 6fc490e..00f2d39 100644
--- a/tempest/tests/common/test_credentials.py
+++ b/tempest/tests/common/test_credentials.py
@@ -15,8 +15,8 @@
from tempest.common import credentials_factory as credentials
from tempest import config
from tempest import exceptions
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class TestLegacyCredentialsProvider(base.TestCase):
@@ -26,7 +26,8 @@
def setUp(self):
super(TestLegacyCredentialsProvider, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
def test_get_creds_roles_legacy_invalid(self):
test_accounts_class = credentials.LegacyCredentialProvider(
diff --git a/tempest/tests/common/test_custom_matchers.py b/tempest/tests/common/test_custom_matchers.py
index d664961..2656a47 100644
--- a/tempest/tests/common/test_custom_matchers.py
+++ b/tempest/tests/common/test_custom_matchers.py
@@ -14,7 +14,7 @@
# under the License.
from tempest.common import custom_matchers
-from tempest.tests.lib import base
+from tempest.tests import base
from testtools.tests.matchers import helpers
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index f2052dc..8d4f33b 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -31,10 +31,10 @@
from tempest.services.identity.v2.json import users_client as \
json_users_client
from tempest.services.network.json import routers_client
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests import fake_http
-from tempest.tests import fake_identity
-from tempest.tests.lib import base
+from tempest.tests.lib import fake_http
+from tempest.tests.lib import fake_identity
class TestDynamicCredentialProvider(base.TestCase):
@@ -46,10 +46,10 @@
def setUp(self):
super(TestDynamicCredentialProvider, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
- self.fake_http = fake_http.fake_httplib2(return_type=200)
- self.stubs.Set(json_token_client.TokenClient, 'raw_request',
- fake_identity._fake_v2_response)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
+ self.patchobject(json_token_client.TokenClient, 'raw_request',
+ fake_identity._fake_v2_response)
cfg.CONF.set_default('operator_role', 'FakeRole',
group='object-storage')
self._mock_list_ec2_credentials('fake_user_id', 'fake_tenant_id')
@@ -402,7 +402,7 @@
side_effect=side_effect)
secgroup_list_mock.start()
- return_values = (fake_http.fake_httplib({}, status=204), {})
+ return_values = fake_http.fake_http_response({}, status=204), ''
remove_secgroup_mock = self.patch(
'tempest.lib.services.network.security_groups_client.'
'SecurityGroupsClient.delete', return_value=return_values)
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/common/test_preprov_creds.py
index efc5ef6..b595c88 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -28,10 +28,9 @@
from tempest.lib import auth
from tempest.lib import exceptions as lib_exc
from tempest.lib.services.identity.v2 import token_client
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests import fake_http
-from tempest.tests import fake_identity
-from tempest.tests.lib import base
+from tempest.tests.lib import fake_identity
class TestPreProvisionedCredentials(base.TestCase):
@@ -47,10 +46,10 @@
def setUp(self):
super(TestPreProvisionedCredentials, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
- self.fake_http = fake_http.fake_httplib2(return_type=200)
- self.stubs.Set(token_client.TokenClient, 'raw_request',
- fake_identity._fake_v2_response)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
+ self.patchobject(token_client.TokenClient, 'raw_request',
+ fake_identity._fake_v2_response)
self.useFixture(lockutils_fixtures.ExternalLockFixture())
self.test_accounts = [
{'username': 'test_user1', 'tenant_name': 'test_tenant1',
@@ -98,8 +97,8 @@
return hash_list
def test_get_hash(self):
- self.stubs.Set(token_client.TokenClient, 'raw_request',
- fake_identity._fake_v2_response)
+ self.patchobject(token_client.TokenClient, 'raw_request',
+ fake_identity._fake_v2_response)
test_account_class = preprov_creds.PreProvisionedCredentialProvider(
**self.fixed_params)
hash_list = self._get_hash_list(self.test_accounts)
@@ -190,7 +189,7 @@
return False
return True
- self.stubs.Set(os.path, 'isfile', _fake_is_file)
+ self.patchobject(os.path, 'isfile', _fake_is_file)
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True) as open_mock:
test_account_class._get_free_hash(hash_list)
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index e0cef62..492bdca 100644
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -19,7 +19,7 @@
from tempest.common import waiters
from tempest import exceptions
from tempest.services.volume.base import base_volumes_client
-from tempest.tests.lib import base
+from tempest.tests import base
import tempest.tests.utils as utils
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index 22cf47a..e9146bc 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -19,15 +19,16 @@
from tempest.common.utils.linux import remote_client
from tempest import config
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class TestRemoteClient(base.TestCase):
def setUp(self):
super(TestRemoteClient, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
cfg.CONF.set_default('ip_version_for_ssh', 4, group='validation')
cfg.CONF.set_default('network_for_ssh', 'public', group='validation')
cfg.CONF.set_default('connect_timeout', 1, group='validation')
diff --git a/tempest/tests/common/utils/test_file_utils.py b/tempest/tests/common/utils/test_file_utils.py
index 1a14592..937aefa 100644
--- a/tempest/tests/common/utils/test_file_utils.py
+++ b/tempest/tests/common/utils/test_file_utils.py
@@ -16,7 +16,7 @@
import mock
from tempest.common.utils import file_utils
-from tempest.tests.lib import base
+from tempest.tests import base
class TestFileUtils(base.TestCase):
diff --git a/tempest/tests/fake_http.py b/tempest/tests/fake_http.py
deleted file mode 100644
index d714055..0000000
--- a/tempest/tests/fake_http.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright 2013 IBM Corp.
-#
-# 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.
-
-import copy
-
-import httplib2
-
-
-class fake_httplib2(object):
-
- def __init__(self, return_type=None, *args, **kwargs):
- self.return_type = return_type
-
- def request(self, uri, method="GET", body=None, headers=None,
- redirections=5, connection_type=None):
- if not self.return_type:
- fake_headers = httplib2.Response(headers)
- return_obj = {
- 'uri': uri,
- 'method': method,
- 'body': body,
- 'headers': headers
- }
- return (fake_headers, return_obj)
- elif isinstance(self.return_type, int):
- body = "fake_body"
- header_info = {
- 'content-type': 'text/plain',
- 'status': str(self.return_type),
- 'content-length': len(body)
- }
- resp_header = httplib2.Response(header_info)
- return (resp_header, body)
- else:
- msg = "unsupported return type %s" % self.return_type
- raise TypeError(msg)
-
-
-class fake_httplib(object):
- def __init__(self, headers, body=None,
- version=1.0, status=200, reason="Ok"):
- """Initialization of fake httplib
-
- :param headers: dict representing HTTP response headers
- :param body: file-like object
- :param version: HTTP Version
- :param status: Response status code
- :param reason: Status code related message.
- """
- self.body = body
- self.status = status
- self.reason = reason
- self.version = version
- self.headers = headers
-
- def getheaders(self):
- return copy.deepcopy(self.headers).items()
-
- def getheader(self, key, default):
- return self.headers.get(key, default)
-
- def read(self, amt):
- return self.body.read(amt)
diff --git a/tempest/tests/fake_identity.py b/tempest/tests/fake_identity.py
deleted file mode 100644
index d0de927..0000000
--- a/tempest/tests/fake_identity.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# Copyright 2014 IBM Corp.
-# All Rights Reserved.
-#
-# 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.
-
-import httplib2
-from oslo_serialization import jsonutils as json
-
-FAKE_AUTH_URL = 'http://fake_uri.com/auth'
-
-TOKEN = "fake_token"
-ALT_TOKEN = "alt_fake_token"
-
-# Fake Identity v2 constants
-COMPUTE_ENDPOINTS_V2 = {
- "endpoints": [
- {
- "adminURL": "http://fake_url/v2/first_endpoint/admin",
- "region": "NoMatchRegion",
- "internalURL": "http://fake_url/v2/first_endpoint/internal",
- "publicURL": "http://fake_url/v2/first_endpoint/public"
- },
- {
- "adminURL": "http://fake_url/v2/second_endpoint/admin",
- "region": "FakeRegion",
- "internalURL": "http://fake_url/v2/second_endpoint/internal",
- "publicURL": "http://fake_url/v2/second_endpoint/public"
- },
- ],
- "type": "compute",
- "name": "nova"
-}
-
-CATALOG_V2 = [COMPUTE_ENDPOINTS_V2, ]
-
-ALT_IDENTITY_V2_RESPONSE = {
- "access": {
- "token": {
- "expires": "2020-01-01T00:00:10Z",
- "id": ALT_TOKEN,
- "tenant": {
- "id": "fake_tenant_id"
- },
- },
- "user": {
- "id": "fake_user_id",
- },
- "serviceCatalog": CATALOG_V2,
- },
-}
-
-IDENTITY_V2_RESPONSE = {
- "access": {
- "token": {
- "expires": "2020-01-01T00:00:10Z",
- "id": TOKEN,
- "tenant": {
- "id": "fake_tenant_id"
- },
- },
- "user": {
- "id": "fake_user_id",
- },
- "serviceCatalog": CATALOG_V2,
- },
-}
-
-# Fake Identity V3 constants
-COMPUTE_ENDPOINTS_V3 = {
- "endpoints": [
- {
- "id": "first_compute_fake_service",
- "interface": "public",
- "region": "NoMatchRegion",
- "url": "http://fake_url/v3/first_endpoint/api"
- },
- {
- "id": "second_fake_service",
- "interface": "public",
- "region": "FakeRegion",
- "url": "http://fake_url/v3/second_endpoint/api"
- },
- {
- "id": "third_fake_service",
- "interface": "admin",
- "region": "MiddleEarthRegion",
- "url": "http://fake_url/v3/third_endpoint/api"
- }
-
- ],
- "type": "compute",
- "id": "fake_compute_endpoint"
-}
-
-CATALOG_V3 = [COMPUTE_ENDPOINTS_V3, ]
-
-IDENTITY_V3_RESPONSE = {
- "token": {
- "methods": [
- "token",
- "password"
- ],
- "expires_at": "2020-01-01T00:00:10.000123Z",
- "project": {
- "domain": {
- "id": "fake_domain_id",
- "name": "fake"
- },
- "id": "project_id",
- "name": "project_name"
- },
- "user": {
- "domain": {
- "id": "fake_domain_id",
- "name": "domain_name"
- },
- "id": "fake_user_id",
- "name": "username"
- },
- "issued_at": "2013-05-29T16:55:21.468960Z",
- "catalog": CATALOG_V3
- }
-}
-
-ALT_IDENTITY_V3 = IDENTITY_V3_RESPONSE
-
-
-def _fake_v3_response(self, uri, method="GET", body=None, headers=None,
- redirections=5, connection_type=None):
- fake_headers = {
- "status": "201",
- "x-subject-token": TOKEN
- }
- return (httplib2.Response(fake_headers),
- json.dumps(IDENTITY_V3_RESPONSE))
-
-
-def _fake_v2_response(self, uri, method="GET", body=None, headers=None,
- redirections=5, connection_type=None):
- return (httplib2.Response({"status": "200"}),
- json.dumps(IDENTITY_V2_RESPONSE))
-
-
-def _fake_auth_failure_response():
- # the response body isn't really used in this case, but lets send it anyway
- # to have a safe check in some future change on the rest client.
- body = {
- "unauthorized": {
- "message": "Unauthorized",
- "code": "401"
- }
- }
- return httplib2.Response({"status": "401"}), json.dumps(body)
diff --git a/tempest/tests/lib/cli/test_command_failed.py b/tempest/tests/lib/cli/test_command_failed.py
index 8ce34c2..388028a 100644
--- a/tempest/tests/lib/cli/test_command_failed.py
+++ b/tempest/tests/lib/cli/test_command_failed.py
@@ -11,7 +11,7 @@
# under the License.
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
class TestOutputParser(base.TestCase):
diff --git a/tempest/tests/lib/cli/test_execute.py b/tempest/tests/lib/cli/test_execute.py
index b5f7145..b846c46 100644
--- a/tempest/tests/lib/cli/test_execute.py
+++ b/tempest/tests/lib/cli/test_execute.py
@@ -14,7 +14,7 @@
from tempest.lib.cli import base as cli_base
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
class TestExecute(base.TestCase):
diff --git a/tempest/tests/lib/cli/test_output_parser.py b/tempest/tests/lib/cli/test_output_parser.py
index a2c1b2d..d88dfc3 100644
--- a/tempest/tests/lib/cli/test_output_parser.py
+++ b/tempest/tests/lib/cli/test_output_parser.py
@@ -16,7 +16,7 @@
from tempest.lib.cli import output_parser
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
class TestOutputParser(base.TestCase):
diff --git a/tempest/tests/lib/common/test_api_version_request.py b/tempest/tests/lib/common/test_api_version_request.py
index bdaa936..58e7040 100644
--- a/tempest/tests/lib/common/test_api_version_request.py
+++ b/tempest/tests/lib/common/test_api_version_request.py
@@ -14,7 +14,7 @@
from tempest.lib.common import api_version_request
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
class APIVersionRequestTests(base.TestCase):
diff --git a/tempest/tests/lib/common/test_api_version_utils.py b/tempest/tests/lib/common/test_api_version_utils.py
index 591b87e..6206379 100644
--- a/tempest/tests/lib/common/test_api_version_utils.py
+++ b/tempest/tests/lib/common/test_api_version_utils.py
@@ -16,7 +16,7 @@
from tempest.lib.common import api_version_utils
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
class TestVersionSkipLogic(base.TestCase):
diff --git a/tempest/tests/lib/common/utils/test_data_utils.py b/tempest/tests/lib/common/utils/test_data_utils.py
index 493df89..f435461 100644
--- a/tempest/tests/lib/common/utils/test_data_utils.py
+++ b/tempest/tests/lib/common/utils/test_data_utils.py
@@ -16,7 +16,7 @@
import netaddr
from tempest.lib.common.utils import data_utils
-from tempest.tests.lib import base
+from tempest.tests import base
class TestDataUtils(base.TestCase):
diff --git a/tempest/tests/lib/common/utils/test_misc.py b/tempest/tests/lib/common/utils/test_misc.py
index e23d7fb..9597f5b 100644
--- a/tempest/tests/lib/common/utils/test_misc.py
+++ b/tempest/tests/lib/common/utils/test_misc.py
@@ -15,7 +15,7 @@
from tempest.lib.common.utils import misc
-from tempest.tests.lib import base
+from tempest.tests import base
@misc.singleton
diff --git a/tempest/tests/lib/fake_http.py b/tempest/tests/lib/fake_http.py
index eda202d..397c856 100644
--- a/tempest/tests/lib/fake_http.py
+++ b/tempest/tests/lib/fake_http.py
@@ -14,8 +14,6 @@
import copy
-import httplib2
-
class fake_httplib2(object):
@@ -25,7 +23,7 @@
def request(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
if not self.return_type:
- fake_headers = httplib2.Response(headers)
+ fake_headers = fake_http_response(headers)
return_obj = {
'uri': uri,
'method': method,
@@ -37,20 +35,20 @@
body = body or "fake_body"
header_info = {
'content-type': 'text/plain',
- 'status': str(self.return_type),
'content-length': len(body)
}
- resp_header = httplib2.Response(header_info)
+ resp_header = fake_http_response(header_info,
+ status=self.return_type)
return (resp_header, body)
else:
msg = "unsupported return type %s" % self.return_type
raise TypeError(msg)
-class fake_httplib(object):
+class fake_http_response(dict):
def __init__(self, headers, body=None,
version=1.0, status=200, reason="Ok"):
- """Fake httplib implementation
+ """Initialization of fake HTTP Response
:param headers: dict representing HTTP response headers
:param body: file-like object
@@ -60,10 +58,15 @@
"""
self.body = body
self.status = status
+ self['status'] = str(self.status)
self.reason = reason
self.version = version
self.headers = headers
+ if headers:
+ for key, value in headers.items():
+ self[key.lower()] = value
+
def getheaders(self):
return copy.deepcopy(self.headers).items()
diff --git a/tempest/tests/lib/fake_identity.py b/tempest/tests/lib/fake_identity.py
index bac2676..5732065 100644
--- a/tempest/tests/lib/fake_identity.py
+++ b/tempest/tests/lib/fake_identity.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import json
+from oslo_serialization import jsonutils as json
-import httplib2
+from tempest.tests.lib import fake_http
FAKE_AUTH_URL = 'http://fake_uri.com/auth'
@@ -139,16 +139,15 @@
def _fake_v3_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
fake_headers = {
- "status": "201",
"x-subject-token": TOKEN
}
- return (httplib2.Response(fake_headers),
+ return (fake_http.fake_http_response(fake_headers, status=201),
json.dumps(IDENTITY_V3_RESPONSE))
def _fake_v2_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
- return (httplib2.Response({"status": "200"}),
+ return (fake_http.fake_http_response({}, status=200),
json.dumps(IDENTITY_V2_RESPONSE))
@@ -161,4 +160,4 @@
"code": "401"
}
}
- return httplib2.Response({"status": "401"}), json.dumps(body)
+ return fake_http.fake_http_response({}, status=401), json.dumps(body)
diff --git a/tempest/tests/lib/services/compute/base.py b/tempest/tests/lib/services/compute/base.py
index 5602044..e77b436 100644
--- a/tempest/tests/lib/services/compute/base.py
+++ b/tempest/tests/lib/services/compute/base.py
@@ -12,11 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import httplib2
from oslo_serialization import jsonutils as json
from oslotest import mockpatch
-from tempest.tests.lib import base
+from tempest.tests import base
+from tempest.tests.lib import fake_http
class BaseComputeServiceTest(base.TestCase):
@@ -26,11 +26,8 @@
json_body = json.dumps(body)
if to_utf:
json_body = json_body.encode('utf-8')
- resp_dict = {'status': status}
- if headers:
- resp_dict.update(headers)
- response = (httplib2.Response(resp_dict), json_body)
- return response
+ resp = fake_http.fake_http_response(headers, status=status), json_body
+ return resp
def check_service_client_function(self, function, function2mock,
body, to_utf=False, status=200,
diff --git a/tempest/tests/lib/services/compute/test_base_compute_client.py b/tempest/tests/lib/services/compute/test_base_compute_client.py
index f552ef5..49d29b3 100644
--- a/tempest/tests/lib/services/compute/test_base_compute_client.py
+++ b/tempest/tests/lib/services/compute/test_base_compute_client.py
@@ -12,14 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
-import httplib2
import mock
-from oslotest import mockpatch
from tempest.lib.common import rest_client
from tempest.lib import exceptions
from tempest.lib.services.compute import base_compute_client
from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib import fake_http
from tempest.tests.lib.services.compute import base
@@ -36,28 +35,29 @@
super(TestMicroversionHeaderCheck, self).tearDown()
base_compute_client.COMPUTE_MICROVERSION = None
- def _check_microverion_header_in_response(self, fake_response):
- def request(*args, **kwargs):
- return (httplib2.Response(fake_response), {})
-
- self.useFixture(mockpatch.PatchObject(
- rest_client.RestClient,
- 'request',
- side_effect=request))
-
- def test_correct_microverion_in_response(self):
- fake_response = {self.client.api_microversion_header_name: '2.2'}
- self._check_microverion_header_in_response(fake_response)
+ @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+ def test_correct_microverion_in_response(self, mock_request):
+ response = fake_http.fake_http_response(
+ headers={self.client.api_microversion_header_name: '2.2'},
+ )
+ mock_request.return_value = response, ''
self.client.get('fake_url')
- def test_incorrect_microverion_in_response(self):
- fake_response = {self.client.api_microversion_header_name: '2.3'}
- self._check_microverion_header_in_response(fake_response)
+ @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+ def test_incorrect_microverion_in_response(self, mock_request):
+ response = fake_http.fake_http_response(
+ headers={self.client.api_microversion_header_name: '2.3'},
+ )
+ mock_request.return_value = response, ''
self.assertRaises(exceptions.InvalidHTTPResponseHeader,
self.client.get, 'fake_url')
- def test_no_microverion_header_in_response(self):
- self._check_microverion_header_in_response({})
+ @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+ def test_no_microverion_header_in_response(self, mock_request):
+ response = fake_http.fake_http_response(
+ headers={},
+ )
+ mock_request.return_value = response, ''
self.assertRaises(exceptions.InvalidHTTPResponseHeader,
self.client.get, 'fake_url')
@@ -164,7 +164,7 @@
def test_no_microverion_header_in_raw_request(self):
def raw_request(*args, **kwargs):
self.assertNotIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
- return (httplib2.Response({'status': 200}), {})
+ return (fake_http.fake_http_response({}, status=200), '')
with mock.patch.object(rest_client.RestClient,
'raw_request') as mock_get:
@@ -196,9 +196,9 @@
self.assertIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
self.assertEqual('2.2',
kwargs['headers']['X-OpenStack-Nova-API-Version'])
- return (httplib2.Response(
- {'status': 200,
- self.client.api_microversion_header_name: '2.2'}), {})
+ return (fake_http.fake_http_response(
+ headers={self.client.api_microversion_header_name: '2.2'},
+ status=200), '')
with mock.patch.object(rest_client.RestClient,
'raw_request') as mock_get:
diff --git a/tempest/tests/lib/services/compute/test_flavors_client.py b/tempest/tests/lib/services/compute/test_flavors_client.py
index 795aff7..e22b4fe 100644
--- a/tempest/tests/lib/services/compute/test_flavors_client.py
+++ b/tempest/tests/lib/services/compute/test_flavors_client.py
@@ -13,13 +13,13 @@
# under the License.
import copy
-import httplib2
from oslo_serialization import jsonutils as json
from oslotest import mockpatch
from tempest.lib.services.compute import flavors_client
from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib import fake_http
from tempest.tests.lib.services.compute import base
@@ -117,7 +117,7 @@
body = json.dumps({'flavors': [TestFlavorsClient.FAKE_FLAVOR]})
if bytes_body:
body = body.encode('utf-8')
- response = (httplib2.Response({'status': 200}), body)
+ response = fake_http.fake_http_response({}, status=200), body
self.useFixture(mockpatch.Patch(
'tempest.lib.common.rest_client.RestClient.get',
return_value=response))
diff --git a/tempest/tests/lib/services/compute/test_images_client.py b/tempest/tests/lib/services/compute/test_images_client.py
index 28757c3..3ebc27f 100644
--- a/tempest/tests/lib/services/compute/test_images_client.py
+++ b/tempest/tests/lib/services/compute/test_images_client.py
@@ -186,7 +186,7 @@
def _test_resource_deleted(self, bytes_body=False):
params = {"id": self.FAKE_IMAGE_ID}
- expected_op = self.FAKE_IMAGE_DATA['show']['image']
+ expected_op = self.FAKE_IMAGE_DATA['show']
self.useFixture(mockpatch.Patch('tempest.lib.services.compute'
'.images_client.ImagesClient.show_image',
side_effect=lib_exc.NotFound))
diff --git a/tempest/tests/lib/services/compute/test_server_groups_client.py b/tempest/tests/lib/services/compute/test_server_groups_client.py
index f1f2906..cb163a8 100644
--- a/tempest/tests/lib/services/compute/test_server_groups_client.py
+++ b/tempest/tests/lib/services/compute/test_server_groups_client.py
@@ -12,12 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import httplib2
-
from oslotest import mockpatch
from tempest.tests.lib import fake_auth_provider
from tempest.lib.services.compute import server_groups_client
+from tempest.tests.lib import fake_http
from tempest.tests.lib.services.compute import base
@@ -50,7 +49,7 @@
self._test_create_server_group(bytes_body=True)
def test_delete_server_group(self):
- response = (httplib2.Response({'status': 204}), None)
+ response = fake_http.fake_http_response({}, status=204), ''
self.useFixture(mockpatch.Patch(
'tempest.lib.common.rest_client.RestClient.delete',
return_value=response))
diff --git a/tempest/tests/lib/services/identity/v2/test_token_client.py b/tempest/tests/lib/services/identity/v2/test_token_client.py
index dd3533a..7925152 100644
--- a/tempest/tests/lib/services/identity/v2/test_token_client.py
+++ b/tempest/tests/lib/services/identity/v2/test_token_client.py
@@ -14,13 +14,12 @@
import json
-import httplib2
-from oslotest import mockpatch
+import mock
from tempest.lib.common import rest_client
from tempest.lib import exceptions
from tempest.lib.services.identity.v2 import token_client
-from tempest.tests.lib import base
+from tempest.tests import base
from tempest.tests.lib import fake_http
@@ -28,7 +27,6 @@
def setUp(self):
super(TestTokenClientV2, self).setUp()
- self.fake_200_http = fake_http.fake_httplib2(return_type=200)
def test_init_without_authurl(self):
self.assertRaises(exceptions.IdentityError,
@@ -36,10 +34,15 @@
def test_auth(self):
token_client_v2 = token_client.TokenClient('fake_url')
- post_mock = self.useFixture(mockpatch.PatchObject(
- token_client_v2, 'post', return_value=self.fake_200_http.request(
- 'fake_url', body={'access': {'token': 'fake_token'}})))
- resp = token_client_v2.auth('fake_user', 'fake_pass')
+ response = fake_http.fake_http_response(
+ None, status=200,
+ )
+ body = {'access': {'token': 'fake_token'}}
+
+ with mock.patch.object(token_client_v2, 'post') as post_mock:
+ post_mock.return_value = response, body
+ resp = token_client_v2.auth('fake_user', 'fake_pass')
+
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@@ -49,15 +52,21 @@
},
}
}, sort_keys=True)
- post_mock.mock.assert_called_once_with('fake_url/tokens',
- body=req_dict)
+ post_mock.assert_called_once_with('fake_url/tokens',
+ body=req_dict)
def test_auth_with_tenant(self):
token_client_v2 = token_client.TokenClient('fake_url')
- post_mock = self.useFixture(mockpatch.PatchObject(
- token_client_v2, 'post', return_value=self.fake_200_http.request(
- 'fake_url', body={'access': {'token': 'fake_token'}})))
- resp = token_client_v2.auth('fake_user', 'fake_pass', 'fake_tenant')
+ response = fake_http.fake_http_response(
+ None, status=200,
+ )
+ body = {'access': {'token': 'fake_token'}}
+
+ with mock.patch.object(token_client_v2, 'post') as post_mock:
+ post_mock.return_value = response, body
+ resp = token_client_v2.auth('fake_user', 'fake_pass',
+ 'fake_tenant')
+
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@@ -68,25 +77,31 @@
},
}
}, sort_keys=True)
- post_mock.mock.assert_called_once_with('fake_url/tokens',
- body=req_dict)
+ post_mock.assert_called_once_with('fake_url/tokens',
+ body=req_dict)
def test_request_with_str_body(self):
token_client_v2 = token_client.TokenClient('fake_url')
- self.useFixture(mockpatch.PatchObject(
- token_client_v2, 'raw_request', return_value=(
- httplib2.Response({'status': '200'}),
- str('{"access": {"token": "fake_token"}}'))))
- resp, body = token_client_v2.request('GET', 'fake_uri')
- self.assertIsInstance(resp, httplib2.Response)
+ response = fake_http.fake_http_response(
+ None, status=200,
+ )
+ body = str('{"access": {"token": "fake_token"}}')
+
+ with mock.patch.object(token_client_v2, 'raw_request') as mock_raw_r:
+ mock_raw_r.return_value = response, body
+ resp, body = token_client_v2.request('GET', 'fake_uri')
self.assertIsInstance(body, dict)
def test_request_with_bytes_body(self):
token_client_v2 = token_client.TokenClient('fake_url')
- self.useFixture(mockpatch.PatchObject(
- token_client_v2, 'raw_request', return_value=(
- httplib2.Response({'status': '200'}),
- bytes(b'{"access": {"token": "fake_token"}}'))))
- resp, body = token_client_v2.request('GET', 'fake_uri')
- self.assertIsInstance(resp, httplib2.Response)
+
+ response = fake_http.fake_http_response(
+ None, status=200,
+ )
+ body = b'{"access": {"token": "fake_token"}}'
+
+ with mock.patch.object(token_client_v2, 'raw_request') as mock_raw_r:
+ mock_raw_r.return_value = response, body
+ resp, body = token_client_v2.request('GET', 'fake_uri')
+
self.assertIsInstance(body, dict)
diff --git a/tempest/tests/lib/services/identity/v3/test_token_client.py b/tempest/tests/lib/services/identity/v3/test_token_client.py
index bb4dae3..e9ef740 100644
--- a/tempest/tests/lib/services/identity/v3/test_token_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_token_client.py
@@ -14,21 +14,19 @@
import json
-import httplib2
-from oslotest import mockpatch
+import mock
from tempest.lib.common import rest_client
from tempest.lib import exceptions
from tempest.lib.services.identity.v3 import token_client
-from tempest.tests.lib import base
+from tempest.tests import base
from tempest.tests.lib import fake_http
-class TestTokenClientV2(base.TestCase):
+class TestTokenClientV3(base.TestCase):
def setUp(self):
- super(TestTokenClientV2, self).setUp()
- self.fake_201_http = fake_http.fake_httplib2(return_type=201)
+ super(TestTokenClientV3, self).setUp()
def test_init_without_authurl(self):
self.assertRaises(exceptions.IdentityError,
@@ -36,10 +34,16 @@
def test_auth(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
- post_mock = self.useFixture(mockpatch.PatchObject(
- token_client_v3, 'post', return_value=self.fake_201_http.request(
- 'fake_url', body={'access': {'token': 'fake_token'}})))
- resp = token_client_v3.auth(username='fake_user', password='fake_pass')
+ response = fake_http.fake_http_response(
+ None, status=201,
+ )
+ body = {'access': {'token': 'fake_token'}}
+
+ with mock.patch.object(token_client_v3, 'post') as post_mock:
+ post_mock.return_value = response, body
+ resp = token_client_v3.auth(username='fake_user',
+ password='fake_pass')
+
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@@ -54,19 +58,24 @@
},
}
}, sort_keys=True)
- post_mock.mock.assert_called_once_with('fake_url/auth/tokens',
- body=req_dict)
+ post_mock.assert_called_once_with('fake_url/auth/tokens',
+ body=req_dict)
def test_auth_with_project_id_and_domain_id(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
- post_mock = self.useFixture(mockpatch.PatchObject(
- token_client_v3, 'post', return_value=self.fake_201_http.request(
- 'fake_url', body={'access': {'token': 'fake_token'}})))
- resp = token_client_v3.auth(
- username='fake_user', password='fake_pass',
- project_id='fcac2a055a294e4c82d0a9c21c620eb4',
- user_domain_id='14f4a9a99973404d8c20ba1d2af163ff',
- project_domain_id='291f63ae9ac54ee292ca09e5f72d9676')
+ response = fake_http.fake_http_response(
+ None, status=201,
+ )
+ body = {'access': {'token': 'fake_token'}}
+
+ with mock.patch.object(token_client_v3, 'post') as post_mock:
+ post_mock.return_value = response, body
+ resp = token_client_v3.auth(
+ username='fake_user', password='fake_pass',
+ project_id='fcac2a055a294e4c82d0a9c21c620eb4',
+ user_domain_id='14f4a9a99973404d8c20ba1d2af163ff',
+ project_domain_id='291f63ae9ac54ee292ca09e5f72d9676')
+
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@@ -92,16 +101,22 @@
}
}
}, sort_keys=True)
- post_mock.mock.assert_called_once_with('fake_url/auth/tokens',
- body=req_dict)
+ post_mock.assert_called_once_with('fake_url/auth/tokens',
+ body=req_dict)
def test_auth_with_tenant(self):
- token_client_v2 = token_client.V3TokenClient('fake_url')
- post_mock = self.useFixture(mockpatch.PatchObject(
- token_client_v2, 'post', return_value=self.fake_201_http.request(
- 'fake_url', body={'access': {'token': 'fake_token'}})))
- resp = token_client_v2.auth(username='fake_user', password='fake_pass',
- project_name='fake_tenant')
+ token_client_v3 = token_client.V3TokenClient('fake_url')
+ response = fake_http.fake_http_response(
+ None, status=201,
+ )
+ body = {'access': {'token': 'fake_token'}}
+
+ with mock.patch.object(token_client_v3, 'post') as post_mock:
+ post_mock.return_value = response, body
+ resp = token_client_v3.auth(username='fake_user',
+ password='fake_pass',
+ project_name='fake_tenant')
+
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@@ -121,25 +136,32 @@
}
}, sort_keys=True)
- post_mock.mock.assert_called_once_with('fake_url/auth/tokens',
- body=req_dict)
+ post_mock.assert_called_once_with('fake_url/auth/tokens',
+ body=req_dict)
def test_request_with_str_body(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
- self.useFixture(mockpatch.PatchObject(
- token_client_v3, 'raw_request', return_value=(
- httplib2.Response({"status": "200"}),
- str('{"access": {"token": "fake_token"}}'))))
- resp, body = token_client_v3.request('GET', 'fake_uri')
- self.assertIsInstance(resp, httplib2.Response)
+ response = fake_http.fake_http_response(
+ None, status=200,
+ )
+ body = str('{"access": {"token": "fake_token"}}')
+
+ with mock.patch.object(token_client_v3, 'raw_request') as mock_raw_r:
+ mock_raw_r.return_value = response, body
+ resp, body = token_client_v3.request('GET', 'fake_uri')
+
self.assertIsInstance(body, dict)
def test_request_with_bytes_body(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
- self.useFixture(mockpatch.PatchObject(
- token_client_v3, 'raw_request', return_value=(
- httplib2.Response({"status": "200"}),
- bytes(b'{"access": {"token": "fake_token"}}'))))
- resp, body = token_client_v3.request('GET', 'fake_uri')
- self.assertIsInstance(resp, httplib2.Response)
+
+ response = fake_http.fake_http_response(
+ None, status=200,
+ )
+ body = b'{"access": {"token": "fake_token"}}'
+
+ with mock.patch.object(token_client_v3, 'raw_request') as mock_raw_r:
+ mock_raw_r.return_value = response, body
+ resp, body = token_client_v3.request('GET', 'fake_uri')
+
self.assertIsInstance(body, dict)
diff --git a/tempest/tests/lib/test_auth.py b/tempest/tests/lib/test_auth.py
index 55f0c4e..cc71c92 100644
--- a/tempest/tests/lib/test_auth.py
+++ b/tempest/tests/lib/test_auth.py
@@ -22,9 +22,8 @@
from tempest.lib import exceptions
from tempest.lib.services.identity.v2 import token_client as v2_client
from tempest.lib.services.identity.v3 import token_client as v3_client
-from tempest.tests.lib import base
+from tempest.tests import base
from tempest.tests.lib import fake_credentials
-from tempest.tests.lib import fake_http
from tempest.tests.lib import fake_identity
@@ -42,8 +41,7 @@
def setUp(self):
super(BaseAuthTestsSetUp, self).setUp()
- self.fake_http = fake_http.fake_httplib2(return_type=200)
- self.stubs.Set(auth, 'get_credentials', fake_get_credentials)
+ self.patchobject(auth, 'get_credentials', fake_get_credentials)
self.auth_provider = self._auth(self.credentials,
fake_identity.FAKE_AUTH_URL)
@@ -120,8 +118,8 @@
def setUp(self):
super(TestKeystoneV2AuthProvider, self).setUp()
- self.stubs.Set(v2_client.TokenClient, 'raw_request',
- fake_identity._fake_v2_response)
+ self.patchobject(v2_client.TokenClient, 'raw_request',
+ fake_identity._fake_v2_response)
self.target_url = 'test_api'
def _get_fake_identity(self):
@@ -435,8 +433,8 @@
def setUp(self):
super(TestKeystoneV3AuthProvider, self).setUp()
- self.stubs.Set(v3_client.V3TokenClient, 'raw_request',
- fake_identity._fake_v3_response)
+ self.patchobject(v3_client.V3TokenClient, 'raw_request',
+ fake_identity._fake_v3_response)
def _get_fake_identity(self):
return fake_identity.IDENTITY_V3_RESPONSE['token']
@@ -570,3 +568,65 @@
attrs = {'tenant_name': 'tenant', 'project_name': 'project'}
self.assertRaises(
exceptions.InvalidCredentials, auth.KeystoneV3Credentials, **attrs)
+
+
+class TestReplaceVersion(base.TestCase):
+ def test_version_no_trailing_path(self):
+ self.assertEqual(
+ 'http://localhost:35357/v2.0',
+ auth.replace_version('http://localhost:35357/v3', 'v2.0'))
+
+ def test_version_no_trailing_path_solidus(self):
+ self.assertEqual(
+ 'http://localhost:35357/v2.0/',
+ auth.replace_version('http://localhost:35357/v3/', 'v2.0'))
+
+ def test_version_trailing_path(self):
+ self.assertEqual(
+ 'http://localhost:35357/v2.0/uuid',
+ auth.replace_version('http://localhost:35357/v3/uuid', 'v2.0'))
+
+ def test_version_trailing_path_solidus(self):
+ self.assertEqual(
+ 'http://localhost:35357/v2.0/uuid/',
+ auth.replace_version('http://localhost:35357/v3/uuid/', 'v2.0'))
+
+ def test_no_version_base(self):
+ self.assertEqual(
+ 'http://localhost:35357/v2.0',
+ auth.replace_version('http://localhost:35357', 'v2.0'))
+
+ def test_no_version_base_solidus(self):
+ self.assertEqual(
+ 'http://localhost:35357/v2.0',
+ auth.replace_version('http://localhost:35357/', 'v2.0'))
+
+ def test_no_version_path(self):
+ self.assertEqual(
+ 'http://localhost/identity/v2.0',
+ auth.replace_version('http://localhost/identity', 'v2.0'))
+
+ def test_no_version_path_solidus(self):
+ self.assertEqual(
+ 'http://localhost/identity/v2.0',
+ auth.replace_version('http://localhost/identity/', 'v2.0'))
+
+ def test_path_version(self):
+ self.assertEqual(
+ 'http://localhost/identity/v2.0',
+ auth.replace_version('http://localhost/identity/v3', 'v2.0'))
+
+ def test_path_version_solidus(self):
+ self.assertEqual(
+ 'http://localhost/identity/v2.0/',
+ auth.replace_version('http://localhost/identity/v3/', 'v2.0'))
+
+ def test_path_version_trailing_path(self):
+ self.assertEqual(
+ 'http://localhost/identity/v2.0/uuid',
+ auth.replace_version('http://localhost/identity/v3/uuid', 'v2.0'))
+
+ def test_path_version_trailing_path_solidus(self):
+ self.assertEqual(
+ 'http://localhost/identity/v2.0/uuid/',
+ auth.replace_version('http://localhost/identity/v3/uuid/', 'v2.0'))
diff --git a/tempest/tests/lib/test_credentials.py b/tempest/tests/lib/test_credentials.py
index 791fbb5..ca3baa1 100644
--- a/tempest/tests/lib/test_credentials.py
+++ b/tempest/tests/lib/test_credentials.py
@@ -19,7 +19,7 @@
from tempest.lib import exceptions
from tempest.lib.services.identity.v2 import token_client as v2_client
from tempest.lib.services.identity.v3 import token_client as v3_client
-from tempest.tests.lib import base
+from tempest.tests import base
from tempest.tests.lib import fake_identity
@@ -72,8 +72,8 @@
def setUp(self):
super(KeystoneV2CredentialsTests, self).setUp()
- self.stubs.Set(self.tokenclient_class, 'raw_request',
- self.identity_response)
+ self.patchobject(self.tokenclient_class, 'raw_request',
+ self.identity_response)
def _verify_credentials(self, credentials_class, creds_dict, filled=True):
creds = auth.get_credentials(fake_identity.FAKE_AUTH_URL,
diff --git a/tempest/tests/lib/test_decorators.py b/tempest/tests/lib/test_decorators.py
index 07b577c..f3a4e9c 100644
--- a/tempest/tests/lib/test_decorators.py
+++ b/tempest/tests/lib/test_decorators.py
@@ -13,13 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
import testtools
from tempest.lib import base as test
+from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest.tests.lib import base
+from tempest.tests import base
class TestSkipBecauseDecorator(base.TestCase):
@@ -78,13 +77,13 @@
return foo
def test_positive(self):
- _id = str(uuid.uuid4())
+ _id = data_utils.rand_uuid()
foo = self._test_helper(_id)
self.assertIn('id-%s' % _id, getattr(foo, '__testtools_attrs'))
self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
def test_positive_without_doc(self):
- _id = str(uuid.uuid4())
+ _id = data_utils.rand_uuid()
foo = self._test_helper_without_doc(_id)
self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
diff --git a/tempest/tests/lib/test_rest_client.py b/tempest/tests/lib/test_rest_client.py
index 87af455..2959294 100644
--- a/tempest/tests/lib/test_rest_client.py
+++ b/tempest/tests/lib/test_rest_client.py
@@ -15,14 +15,14 @@
import copy
import json
-import httplib2
import jsonschema
from oslotest import mockpatch
import six
+from tempest.lib.common import http
from tempest.lib.common import rest_client
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib import fake_http
import tempest.tests.utils as utils
@@ -37,7 +37,7 @@
self.fake_auth_provider = fake_auth_provider.FakeAuthProvider()
self.rest_client = rest_client.RestClient(
self.fake_auth_provider, None, None)
- self.stubs.Set(httplib2.Http, 'request', self.fake_http.request)
+ self.patchobject(http.ClosingHttp, 'request', self.fake_http.request)
self.useFixture(mockpatch.PatchObject(self.rest_client,
'_log_request'))
@@ -292,7 +292,9 @@
if absolute_limit is False:
resp_dict.update({'retry-after': 120})
resp_body.update({'overLimit': {'message': 'fake_message'}})
- resp = httplib2.Response(resp_dict)
+ resp = fake_http.fake_http_response(headers=resp_dict,
+ status=int(r_code),
+ body=json.dumps(resp_body))
data = {
"method": "fake_method",
"url": "fake_url",
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index f6efd47..b07f6bc 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -21,7 +21,7 @@
from tempest.lib.common import ssh
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
import tempest.tests.utils as utils
@@ -141,8 +141,6 @@
def test_exec_command(self):
chan_mock, poll_mock, select_mock = (
self._set_mocks_for_select([[1, 0, 0]], True))
- closed_prop = mock.PropertyMock(return_value=True)
- type(chan_mock).closed = closed_prop
chan_mock.recv_exit_status.return_value = 0
chan_mock.recv.return_value = b''
@@ -164,7 +162,6 @@
chan_mock.recv_stderr_ready.assert_called_once_with()
chan_mock.recv_stderr.assert_called_once_with(1024)
chan_mock.recv_exit_status.assert_called_once_with()
- closed_prop.assert_called_once_with()
def _set_mocks_for_select(self, poll_data, ito_value=False):
gsc_mock = self.patch('tempest.lib.common.ssh.Client.'
@@ -184,7 +181,7 @@
gsc_mock.return_value = client_mock
ito_mock.return_value = ito_value
client_mock.get_transport.return_value = tran_mock
- tran_mock.open_session.return_value = chan_mock
+ tran_mock.open_session().__enter__.return_value = chan_mock
if isinstance(poll_data[0], list):
poll_mock.poll.side_effect = poll_data
else:
@@ -242,7 +239,7 @@
gsc_mock.return_value = client_mock
client_mock.get_transport.return_value = tran_mock
- tran_mock.open_session.return_value = chan_mock
+ tran_mock.open_session().__enter__.return_value = chan_mock
chan_mock.recv_exit_status.return_value = 0
std_out_mock = mock.MagicMock(StringIO)
diff --git a/tempest/tests/lib/test_tempest_lib.py b/tempest/tests/lib/test_tempest_lib.py
index 9731e96..d70e53d 100644
--- a/tempest/tests/lib/test_tempest_lib.py
+++ b/tempest/tests/lib/test_tempest_lib.py
@@ -19,7 +19,7 @@
Tests for `tempest.lib` module.
"""
-from tempest.tests.lib import base
+from tempest.tests import base
class TestTempest_lib(base.TestCase):
diff --git a/tempest/tests/negative/test_negative_auto_test.py b/tempest/tests/negative/test_negative_auto_test.py
index c666bd3..44ce567 100644
--- a/tempest/tests/negative/test_negative_auto_test.py
+++ b/tempest/tests/negative/test_negative_auto_test.py
@@ -15,8 +15,8 @@
from tempest import config
import tempest.test as test
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class TestNegativeAutoTest(base.TestCase):
@@ -37,7 +37,8 @@
def setUp(self):
super(TestNegativeAutoTest, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
def _check_prop_entries(self, result, entry):
entries = [a for a in result if entry in a[0]]
diff --git a/tempest/tests/negative/test_negative_generators.py b/tempest/tests/negative/test_negative_generators.py
index e0d7f42..78fd80d 100644
--- a/tempest/tests/negative/test_negative_generators.py
+++ b/tempest/tests/negative/test_negative_generators.py
@@ -22,7 +22,7 @@
from tempest.common.generator import base_generator
from tempest.common.generator import negative_generator
from tempest.common.generator import valid_generator
-from tempest.tests.lib import base
+from tempest.tests import base
class TestNegativeBasicGenerator(base.TestCase):
diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
index a35b4d7..dfe0291 100644
--- a/tempest/tests/stress/test_stress.py
+++ b/tempest/tests/stress/test_stress.py
@@ -18,7 +18,7 @@
from oslo_log import log as logging
from tempest.lib import exceptions
-from tempest.tests.lib import base
+from tempest.tests import base
LOG = logging.getLogger(__name__)
diff --git a/tempest/tests/test_base_test.py b/tempest/tests/test_base_test.py
index 9ffb7a1..dc355b4 100644
--- a/tempest/tests/test_base_test.py
+++ b/tempest/tests/test_base_test.py
@@ -19,8 +19,8 @@
from tempest.common import fixed_network
from tempest import config
from tempest import test
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class TestBaseTestCase(base.TestCase):
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index 4c9a3b7..7c9579b 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
import mock
from oslo_config import cfg
from oslotest import mockpatch
@@ -21,16 +19,18 @@
from tempest import config
from tempest import exceptions
+from tempest.lib.common.utils import data_utils
from tempest import test
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class BaseDecoratorsTest(base.TestCase):
def setUp(self):
super(BaseDecoratorsTest, self).setUp()
self.config_fixture = self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
class TestAttrDecorator(BaseDecoratorsTest):
@@ -79,13 +79,13 @@
return foo
def test_positive(self):
- _id = str(uuid.uuid4())
+ _id = data_utils.rand_uuid()
foo = self._test_helper(_id)
self.assertIn('id-%s' % _id, getattr(foo, '__testtools_attrs'))
self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
def test_positive_without_doc(self):
- _id = str(uuid.uuid4())
+ _id = data_utils.rand_uuid()
foo = self._test_helper_without_doc(_id)
self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
diff --git a/tempest/tests/test_glance_http.py b/tempest/tests/test_glance_http.py
index 10f80a7..768cd05 100644
--- a/tempest/tests/test_glance_http.py
+++ b/tempest/tests/test_glance_http.py
@@ -22,20 +22,15 @@
from tempest.common import glance_http
from tempest import exceptions
+from tempest.tests import base
from tempest.tests import fake_auth_provider
-from tempest.tests import fake_http
-from tempest.tests.lib import base
+from tempest.tests.lib import fake_http
class TestGlanceHTTPClient(base.TestCase):
def setUp(self):
super(TestGlanceHTTPClient, self).setUp()
- self.fake_http = fake_http.fake_httplib2(return_type=200)
- # NOTE(maurosr): using http here implies that we will be using httplib
- # directly. With https glance_client would use an httpS version, but
- # the real backend would still be httplib anyway and since we mock it
- # that there is no reason to care.
self.endpoint = 'http://fake_url.com'
self.fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -44,12 +39,12 @@
self.useFixture(mockpatch.PatchObject(
httplib.HTTPConnection,
'request',
- side_effect=self.fake_http.request(self.endpoint)[1]))
+ side_effect=b'fake_body'))
self.client = glance_http.HTTPClient(self.fake_auth, {})
def _set_response_fixture(self, header, status, resp_body):
- resp = fake_http.fake_httplib(header, status=status,
- body=six.StringIO(resp_body))
+ resp = fake_http.fake_http_response(header, status=status,
+ body=six.StringIO(resp_body))
self.useFixture(mockpatch.PatchObject(httplib.HTTPConnection,
'getresponse', return_value=resp))
return resp
@@ -223,7 +218,7 @@
class TestResponseBodyIterator(base.TestCase):
def test_iter_default_chunk_size_64k(self):
- resp = fake_http.fake_httplib({}, six.StringIO(
+ resp = fake_http.fake_http_response({}, six.StringIO(
'X' * (glance_http.CHUNKSIZE + 1)))
iterator = glance_http.ResponseBodyIterator(resp)
chunks = list(iterator)
diff --git a/tempest/tests/test_hacking.py b/tempest/tests/test_hacking.py
index 6b3aa0d..aba2aab 100644
--- a/tempest/tests/test_hacking.py
+++ b/tempest/tests/test_hacking.py
@@ -13,7 +13,7 @@
# under the License.
from tempest.hacking import checks
-from tempest.tests.lib import base
+from tempest.tests import base
class HackingTestCase(base.TestCase):
diff --git a/tempest/tests/test_list_tests.py b/tempest/tests/test_list_tests.py
index 69527b1..38d4c5c 100644
--- a/tempest/tests/test_list_tests.py
+++ b/tempest/tests/test_list_tests.py
@@ -17,7 +17,7 @@
import six
import subprocess
-from tempest.tests.lib import base
+from tempest.tests import base
class TestTestList(base.TestCase):
diff --git a/tempest/tests/test_microversions.py b/tempest/tests/test_microversions.py
index 1ac1232..173accb 100644
--- a/tempest/tests/test_microversions.py
+++ b/tempest/tests/test_microversions.py
@@ -18,8 +18,8 @@
from tempest.api.compute import base as compute_base
from tempest import config
from tempest.lib import exceptions
+from tempest.tests import base
from tempest.tests import fake_config
-from tempest.tests.lib import base
class VersionTestNoneTolatest(compute_base.BaseV2ComputeTest):
@@ -57,8 +57,8 @@
def setUp(self):
super(TestMicroversionsTestsClass, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate',
- fake_config.FakePrivate)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
def _test_version(self, cfg_min, cfg_max,
expected_pass_tests,
diff --git a/tempest/tests/test_negative_rest_client.py b/tempest/tests/test_negative_rest_client.py
index 6a071b1..9d9c20f 100644
--- a/tempest/tests/test_negative_rest_client.py
+++ b/tempest/tests/test_negative_rest_client.py
@@ -15,15 +15,14 @@
# License for the specific language governing permissions and limitations
# under the License.
-import httplib2
+import mock
from oslotest import mockpatch
from tempest.common import negative_rest_client
from tempest import config
+from tempest.tests import base
from tempest.tests import fake_auth_provider
from tempest.tests import fake_config
-from tempest.tests import fake_http
-from tempest.tests.lib import base
class TestNegativeRestClient(base.TestCase):
@@ -31,59 +30,70 @@
url = 'fake_endpoint'
def setUp(self):
- self.fake_http = fake_http.fake_httplib2()
super(TestNegativeRestClient, self).setUp()
self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
- self.stubs.Set(httplib2.Http, 'request', self.fake_http.request)
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
self.negative_rest_client = negative_rest_client.NegativeRestClient(
fake_auth_provider.FakeAuthProvider(), None)
self.useFixture(mockpatch.PatchObject(self.negative_rest_client,
'_log_request'))
- def test_post(self):
+ @mock.patch('tempest.lib.common.rest_client.RestClient.post',
+ return_value=(mock.Mock(), mock.Mock()))
+ def test_post(self, mock_post):
__, return_dict = self.negative_rest_client.send_request('POST',
self.url,
[], {})
- self.assertEqual('POST', return_dict['method'])
+ mock_post.assert_called_once_with(self.url, {})
- def test_get(self):
+ @mock.patch('tempest.lib.common.rest_client.RestClient.get',
+ return_value=(mock.Mock(), mock.Mock()))
+ def test_get(self, mock_get):
__, return_dict = self.negative_rest_client.send_request('GET',
self.url,
[])
- self.assertEqual('GET', return_dict['method'])
+ mock_get.assert_called_once_with(self.url)
- def test_delete(self):
+ @mock.patch('tempest.lib.common.rest_client.RestClient.delete',
+ return_value=(mock.Mock(), mock.Mock()))
+ def test_delete(self, mock_delete):
__, return_dict = self.negative_rest_client.send_request('DELETE',
self.url,
[])
- self.assertEqual('DELETE', return_dict['method'])
+ mock_delete.assert_called_once_with(self.url)
- def test_patch(self):
+ @mock.patch('tempest.lib.common.rest_client.RestClient.patch',
+ return_value=(mock.Mock(), mock.Mock()))
+ def test_patch(self, mock_patch):
__, return_dict = self.negative_rest_client.send_request('PATCH',
self.url,
[], {})
- self.assertEqual('PATCH', return_dict['method'])
+ mock_patch.assert_called_once_with(self.url, {})
- def test_put(self):
+ @mock.patch('tempest.lib.common.rest_client.RestClient.put',
+ return_value=(mock.Mock(), mock.Mock()))
+ def test_put(self, mock_put):
__, return_dict = self.negative_rest_client.send_request('PUT',
self.url,
[], {})
- self.assertEqual('PUT', return_dict['method'])
+ mock_put.assert_called_once_with(self.url, {})
- def test_head(self):
- self.useFixture(mockpatch.PatchObject(self.negative_rest_client,
- 'response_checker'))
+ @mock.patch('tempest.lib.common.rest_client.RestClient.head',
+ return_value=(mock.Mock(), mock.Mock()))
+ def test_head(self, mock_head):
__, return_dict = self.negative_rest_client.send_request('HEAD',
self.url,
[])
- self.assertEqual('HEAD', return_dict['method'])
+ mock_head.assert_called_once_with(self.url)
- def test_copy(self):
+ @mock.patch('tempest.lib.common.rest_client.RestClient.copy',
+ return_value=(mock.Mock(), mock.Mock()))
+ def test_copy(self, mock_copy):
__, return_dict = self.negative_rest_client.send_request('COPY',
self.url,
[])
- self.assertEqual('COPY', return_dict['method'])
+ mock_copy.assert_called_once_with(self.url)
def test_other(self):
self.assertRaises(AssertionError,
diff --git a/tempest/tests/test_tempest_plugin.py b/tempest/tests/test_tempest_plugin.py
index f66dfc8..c07e98c 100644
--- a/tempest/tests/test_tempest_plugin.py
+++ b/tempest/tests/test_tempest_plugin.py
@@ -14,8 +14,8 @@
# under the License.
from tempest.test_discover import plugins
+from tempest.tests import base
from tempest.tests import fake_tempest_plugin as fake_plugin
-from tempest.tests.lib import base
class TestPluginDiscovery(base.TestCase):
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
index edb9061..a4ef699 100644
--- a/tempest/tests/test_wrappers.py
+++ b/tempest/tests/test_wrappers.py
@@ -19,7 +19,7 @@
import six
-from tempest.tests.lib import base
+from tempest.tests import base
DEVNULL = open(os.devnull, 'wb')
diff --git a/test-requirements.txt b/test-requirements.txt
index bb4b27f..9ef956a 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -7,7 +7,6 @@
python-subunit>=0.0.18 # Apache-2.0/BSD
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
reno>=1.6.2 # Apache2
-mox>=0.5.3 # Apache-2.0
mock>=1.2 # BSD
coverage>=3.6 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
diff --git a/tools/install_venv.py b/tools/install_venv.py
deleted file mode 100644
index d6d9c8e..0000000
--- a/tools/install_venv.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# All Rights Reserved.
-#
-# Copyright 2010 OpenStack Foundation
-# Copyright 2013 IBM Corp.
-#
-# 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.
-
-import os
-import sys
-
-import install_venv_common as install_venv # noqa
-
-
-def print_help(venv, root):
- help = """
- OpenStack development environment setup is complete.
-
- OpenStack development uses virtualenv to track and manage Python
- dependencies while in development and testing.
-
- To activate the OpenStack virtualenv for the extent of your current shell
- session you can run:
-
- $ source %s/bin/activate
-
- Or, if you prefer, you can run commands in the virtualenv on a case by case
- basis by running:
-
- $ %s/tools/with_venv.sh <your command>
-
- Also, make test will automatically use the virtualenv.
- """
- print(help % (venv, root))
-
-
-def main(argv):
- root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-
- if os.environ.get('TOOLS_PATH'):
- root = os.environ['TOOLS_PATH']
- venv = os.path.join(root, '.venv')
- if os.environ.get('VENV'):
- venv = os.environ['VENV']
-
- pip_requires = os.path.join(root, 'requirements.txt')
- test_requires = os.path.join(root, 'test-requirements.txt')
- py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1])
- project = 'Tempest'
- install = install_venv.InstallVenv(root, venv, pip_requires, test_requires,
- py_version, project)
- options = install.parse_args(argv)
- install.check_python_version()
- install.check_dependencies()
- install.create_virtualenv(no_site_packages=options.no_site_packages)
- install.install_dependencies()
- print_help(venv, root)
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py
deleted file mode 100644
index e279159..0000000
--- a/tools/install_venv_common.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# Copyright 2013 OpenStack Foundation
-# Copyright 2013 IBM Corp.
-#
-# 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.
-
-"""Provides methods needed by installation script for OpenStack development
-virtual environments.
-
-Since this script is used to bootstrap a virtualenv from the system's Python
-environment, it should be kept strictly compatible with Python 2.6.
-
-Synced in from openstack-common
-"""
-
-from __future__ import print_function
-
-import optparse
-import os
-import subprocess
-import sys
-
-
-class InstallVenv(object):
-
- def __init__(self, root, venv, requirements,
- test_requirements, py_version,
- project):
- self.root = root
- self.venv = venv
- self.requirements = requirements
- self.test_requirements = test_requirements
- self.py_version = py_version
- self.project = project
-
- def die(self, message, *args):
- print(message % args, file=sys.stderr)
- sys.exit(1)
-
- def check_python_version(self):
- if sys.version_info < (2, 6):
- self.die("Need Python Version >= 2.6")
-
- def run_command_with_code(self, cmd, redirect_output=True,
- check_exit_code=True):
- """Runs a command in an out-of-process shell.
-
- Returns the output of that command. Working directory is self.root.
- """
- if redirect_output:
- stdout = subprocess.PIPE
- else:
- stdout = None
-
- proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout)
- output = proc.communicate()[0]
- if check_exit_code and proc.returncode != 0:
- self.die('Command "%s" failed.\n%s', ' '.join(cmd), output)
- return (output, proc.returncode)
-
- def run_command(self, cmd, redirect_output=True, check_exit_code=True):
- return self.run_command_with_code(cmd, redirect_output,
- check_exit_code)[0]
-
- def get_distro(self):
- if (os.path.exists('/etc/fedora-release') or
- os.path.exists('/etc/redhat-release')):
- return Fedora(
- self.root, self.venv, self.requirements,
- self.test_requirements, self.py_version, self.project)
- else:
- return Distro(
- self.root, self.venv, self.requirements,
- self.test_requirements, self.py_version, self.project)
-
- def check_dependencies(self):
- self.get_distro().install_virtualenv()
-
- def create_virtualenv(self, no_site_packages=True):
- """Creates the virtual environment and installs PIP.
-
- Creates the virtual environment and installs PIP only into the
- virtual environment.
- """
- if not os.path.isdir(self.venv):
- print('Creating venv...', end=' ')
- if no_site_packages:
- self.run_command(['virtualenv', '-q', '--no-site-packages',
- self.venv])
- else:
- self.run_command(['virtualenv', '-q', self.venv])
- print('done.')
- else:
- print("venv already exists...")
- pass
-
- def pip_install(self, *args):
- self.run_command(['tools/with_venv.sh',
- 'pip', 'install', '--upgrade'] + list(args),
- redirect_output=False)
-
- def install_dependencies(self):
- print('Installing dependencies with pip (this can take a while)...')
-
- # First things first, make sure our venv has the latest pip and
- # setuptools and pbr
- self.pip_install('pip>=1.4')
- self.pip_install('setuptools')
- self.pip_install('pbr')
-
- self.pip_install('-r', self.requirements, '-r', self.test_requirements)
-
- def parse_args(self, argv):
- """Parses command-line arguments."""
- parser = optparse.OptionParser()
- parser.add_option('-n', '--no-site-packages',
- action='store_true',
- help="Do not inherit packages from global Python "
- "install.")
- return parser.parse_args(argv[1:])[0]
-
-
-class Distro(InstallVenv):
-
- def check_cmd(self, cmd):
- return bool(self.run_command(['which', cmd],
- check_exit_code=False).strip())
-
- def install_virtualenv(self):
- if self.check_cmd('virtualenv'):
- return
-
- if self.check_cmd('easy_install'):
- print('Installing virtualenv via easy_install...', end=' ')
- if self.run_command(['easy_install', 'virtualenv']):
- print('Succeeded')
- return
- else:
- print('Failed')
-
- self.die('ERROR: virtualenv not found.\n\n%s development'
- ' requires virtualenv, please install it using your'
- ' favorite package management tool' % self.project)
-
-
-class Fedora(Distro):
- """This covers all Fedora-based distributions.
-
- Includes: Fedora, RHEL, CentOS, Scientific Linux
- """
-
- def check_pkg(self, pkg):
- return self.run_command_with_code(['rpm', '-q', pkg],
- check_exit_code=False)[1] == 0
-
- def install_virtualenv(self):
- if self.check_cmd('virtualenv'):
- return
-
- if not self.check_pkg('python-virtualenv'):
- self.die("Please install 'python-virtualenv'.")
-
- super(Fedora, self).install_virtualenv()
diff --git a/tox.ini b/tox.ini
index 28dfe8b..e371406 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,23 +5,27 @@
[tempestenv]
sitepackages = False
-setenv = VIRTUAL_ENV={envdir}
- OS_TEST_PATH=./tempest/test_discover
-deps = setuptools
- -r{toxinidir}/requirements.txt
+setenv =
+ VIRTUAL_ENV={envdir}
+ OS_TEST_PATH=./tempest/test_discover
+deps =
+ setuptools
+ -r{toxinidir}/requirements.txt
[testenv]
-setenv = VIRTUAL_ENV={envdir}
- OS_TEST_PATH=./tempest/tests
+setenv =
+ VIRTUAL_ENV={envdir}
+ OS_TEST_PATH=./tempest/tests
passenv = OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_TEST_TIMEOUT OS_TEST_LOCK_PATH OS_TEST_PATH TEMPEST_CONFIG TEMPEST_CONFIG_DIR http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
usedevelop = True
install_command = pip install -U {opts} {packages}
whitelist_externals = *
-deps = -r{toxinidir}/requirements.txt
- -r{toxinidir}/test-requirements.txt
+deps =
+ -r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
commands =
- find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '{posargs}'
+ find . -type f -name "*.pyc" -delete
+ bash tools/pretty_tox.sh '{posargs}'
[testenv:genconfig]
commands = oslo-config-generator --config-file etc/config-generator.tempest.conf
@@ -33,22 +37,35 @@
[testenv:all]
sitepackages = {[tempestenv]sitepackages}
# 'all' includes slow tests
-setenv = {[tempestenv]setenv}
- OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
+setenv =
+ {[tempestenv]setenv}
+ OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
deps = {[tempestenv]deps}
commands =
- find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '{posargs}'
+ find . -type f -name "*.pyc" -delete
+ bash tools/pretty_tox.sh '{posargs}'
+
+[testenv:ostestr]
+sitepackages = {[tempestenv]sitepackages}
+# 'all' includes slow tests
+setenv =
+ {[tempestenv]setenv}
+ OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
+deps = {[tempestenv]deps}
+commands =
+ find . -type f -name "*.pyc" -delete
+ ostestr {posargs}
[testenv:all-plugin]
sitepackages = True
# 'all' includes slow tests
-setenv = {[tempestenv]setenv}
- OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
+setenv =
+ {[tempestenv]setenv}
+ OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
deps = {[tempestenv]deps}
commands =
- find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '{posargs}'
+ find . -type f -name "*.pyc" -delete
+ bash tools/pretty_tox.sh '{posargs}'
[testenv:full]
sitepackages = {[tempestenv]sitepackages}
@@ -57,8 +74,8 @@
# The regex below is used to select which tests to run and exclude the slow tag:
# See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
commands =
- find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
+ find . -type f -name "*.pyc" -delete
+ bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
[testenv:full-serial]
sitepackages = {[tempestenv]sitepackages}
@@ -67,16 +84,16 @@
# The regex below is used to select which tests to run and exclude the slow tag:
# See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
commands =
- find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
+ find . -type f -name "*.pyc" -delete
+ bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
[testenv:smoke]
sitepackages = {[tempestenv]sitepackages}
setenv = {[tempestenv]setenv}
deps = {[tempestenv]deps}
commands =
- find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '\[.*\bsmoke\b.*\] {posargs}'
+ find . -type f -name "*.pyc" -delete
+ bash tools/pretty_tox.sh '\[.*\bsmoke\b.*\] {posargs}'
[testenv:smoke-serial]
sitepackages = {[tempestenv]sitepackages}
@@ -86,8 +103,8 @@
# https://bugs.launchpad.net/tempest/+bug/1216076 so the neutron smoke
# job would fail if we moved it to parallel.
commands =
- find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox_serial.sh '\[.*\bsmoke\b.*\] {posargs}'
+ find . -type f -name "*.pyc" -delete
+ bash tools/pretty_tox_serial.sh '\[.*\bsmoke\b.*\] {posargs}'
[testenv:stress]
sitepackages = {[tempestenv]sitepackages}
@@ -101,16 +118,16 @@
[testenv:docs]
commands =
- python setup.py build_sphinx {posargs}
+ python setup.py build_sphinx {posargs}
[testenv:pep8]
commands =
- flake8 {posargs}
- check-uuid
+ flake8 {posargs}
+ check-uuid
[testenv:uuidgen]
commands =
- check-uuid --fix
+ check-uuid --fix
[hacking]
local-check-factory = tempest.hacking.checks.factory