Merge "Keep py3.X compatibility for urllib.urlencode"
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 12d1d40..7e4503d 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -127,8 +127,11 @@
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
-git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1"
-html_last_updated_fmt = os.popen(git_cmd).read()
+git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local",
+ "-n1"]
+html_last_updated_fmt = subprocess.Popen(git_cmd,
+ stdout=subprocess.PIPE).\
+ communicate()[0]
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index a16f3b7..7f1e292 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -14,11 +14,11 @@
Tempest currently has 2 different ways in configuration to provide credentials
to use when running tempest. One is a traditional set of configuration options
-in the tempest.conf file. These options are in the identity section and let you
-specify a regular user, a global admin user, and an alternate user set of
-credentials. (which consist of a username, password, and project/tenant name)
-These options should be clearly labelled in the sample config file in the
-identity section.
+in the tempest.conf file. These options are in the auth and identity sections
+and let you specify a global admin user, a regular user and an alternate user
+set of credentials. (which consist of a username, password, and project/tenant
+name) These options should be clearly labelled in the sample config file in the
+auth and identity sections.
The other method to provide credentials is using the accounts.yaml file. This
file is used to specify an arbitrary number of users available to run tests
@@ -109,6 +109,9 @@
#. Provide tempest with the location of your accounts.yaml file with the
test_accounts_file option in the auth section
+ *NOTE: Be sure to use a full path for the file otherwise Tempest will
+ likely not find it.*
+
#. Set use_dynamic_credentials = False in the auth group
It is worth pointing out that each set of credentials in the accounts.yaml
@@ -126,21 +129,21 @@
non-tenant isolated case was converted to internally work similarly to the
accounts.yaml file. This mechanism was then called the legacy test accounts
provider. To use the legacy test accounts provider you can specify the sets of
-credentials in the configuration file like detailed above with following 9
+credentials in the configuration file like detailed above with following 6
options in the identity section:
#. username
#. password
#. tenant_name
- #. admin_username
- #. admin_password
- #. admin_tenant_name
#. alt_username
#. alt_password
#. alt_tenant_name
And in the auth section:
-
+
+ #. admin_username
+ #. admin_password
+ #. admin_tenant_name
#. use_dynamic_credentials = False
#. comment out 'test_accounts_file' or keep it as empty
diff --git a/requirements.txt b/requirements.txt
index 1f225c3..aa304a4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,15 +12,16 @@
testrepository>=0.0.18
pyOpenSSL>=0.14
oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=2.7.0 # Apache-2.0
+oslo.config>=3.2.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
-oslo.log>=1.12.0 # Apache-2.0
+oslo.log>=1.14.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
-oslo.utils>=2.8.0 # Apache-2.0
+oslo.utils>=3.2.0 # Apache-2.0
six>=1.9.0
iso8601>=0.1.9
fixtures>=1.3.1
testscenarios>=0.4
-tempest-lib>=0.12.0
+tempest-lib>=0.13.0
PyYAML>=3.1.0
stevedore>=1.5.0 # Apache-2.0
+PrettyTable<0.8,>=0.7
diff --git a/setup.cfg b/setup.cfg
index 4415063..b94a4f4 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -36,6 +36,7 @@
init = tempest.cmd.init:TempestInit
cleanup = tempest.cmd.cleanup:TempestCleanup
run-stress = tempest.cmd.run_stress:TempestRunStress
+ list-plugins = tempest.cmd.list_plugins:TempestListPlugins
oslo.config.opts =
tempest.config = tempest.config:list_opts
diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py
index d2b3a81..9f7bbae 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -53,7 +53,7 @@
if rand_key in kwargs:
# NOTE: The rand_name is for avoiding agent conflicts.
# If you try to create an agent with the same hypervisor,
- # os and architecture as an exising agent, Nova will return
+ # os and architecture as an existing agent, Nova will return
# an HTTPConflict or HTTPServerError.
kwargs[rand_key] = data_utils.rand_name(kwargs[rand_key])
return kwargs
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index ddd9aa0..1d83fec 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -145,7 +145,7 @@
@test.idempotent_id('c8e85064-e79b-4906-9931-c11c24294d02')
def test_aggregate_add_remove_host(self):
- # Add an host to the given aggregate and remove.
+ # Add a host to the given aggregate and remove.
self.useFixture(fixtures.LockFixture('availability_zone'))
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = (self.client.create_aggregate(name=aggregate_name)
@@ -168,7 +168,7 @@
@test.idempotent_id('7f6a1cc5-2446-4cdb-9baa-b6ae0a919b72')
def test_aggregate_add_host_list(self):
- # Add an host to the given aggregate and list.
+ # Add a host to the given aggregate and list.
self.useFixture(fixtures.LockFixture('availability_zone'))
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = (self.client.create_aggregate(name=aggregate_name)
@@ -188,7 +188,7 @@
@test.idempotent_id('eeef473c-7c52-494d-9f09-2ed7fc8fc036')
def test_aggregate_add_host_get_details(self):
- # Add an host to the given aggregate and get details.
+ # Add a host to the given aggregate and get details.
self.useFixture(fixtures.LockFixture('availability_zone'))
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = (self.client.create_aggregate(name=aggregate_name)
@@ -205,7 +205,7 @@
@test.idempotent_id('96be03c7-570d-409c-90f8-e4db3c646996')
def test_aggregate_add_host_create_server_with_az(self):
- # Add an host to the given aggregate and create a server.
+ # Add a host to the given aggregate and create a server.
self.useFixture(fixtures.LockFixture('availability_zone'))
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
az_name = data_utils.rand_name(self.az_name_prefix)
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index e31129b..1494745 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
-
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
@@ -38,9 +36,6 @@
self.client.delete_security_group(securitygroup_id)
@test.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1')
- @testtools.skipIf(CONF.service_available.neutron,
- "Skipped because neutron does not support all_tenants "
- "search filter.")
@test.services('network')
def test_list_security_groups_list_all_tenants_filter(self):
# Admin can list security groups of all tenants
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index aa8ee3f..8a27929 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -55,6 +55,13 @@
@classmethod
def setup_credentials(cls):
cls.set_network_resources()
+ cls.request_microversion = (
+ api_version_utils.select_request_microversion(
+ cls.min_microversion,
+ CONF.compute_feature_enabled.min_microversion))
+ if cls.request_microversion:
+ cls.services_microversion = {
+ CONF.compute.catalog_type: cls.request_microversion}
super(BaseV2ComputeTest, cls).setup_credentials()
@classmethod
@@ -63,12 +70,13 @@
cls.servers_client = cls.os.servers_client
cls.server_groups_client = cls.os.server_groups_client
cls.flavors_client = cls.os.flavors_client
- cls.images_client = cls.os.images_client
+ cls.compute_images_client = cls.os.compute_images_client
cls.extensions_client = cls.os.extensions_client
cls.floating_ip_pools_client = cls.os.floating_ip_pools_client
cls.floating_ips_client = cls.os.compute_floating_ips_client
cls.keypairs_client = cls.os.keypairs_client
- cls.security_group_rules_client = cls.os.security_group_rules_client
+ cls.security_group_rules_client = (
+ cls.os.compute_security_group_rules_client)
cls.security_groups_client = cls.os.compute_security_groups_client
cls.quotas_client = cls.os.quotas_client
cls.quota_classes_client = cls.os.quota_classes_client
@@ -170,7 +178,7 @@
LOG.debug('Clearing images: %s', ','.join(cls.images))
for image_id in cls.images:
try:
- cls.images_client.delete_image(image_id)
+ cls.compute_images_client.delete_image(image_id)
except lib_exc.NotFound:
# The image may have already been deleted which is OK.
pass
@@ -278,8 +286,8 @@
# into the delete_volume method as a convenience to the caller.
volumes_client.wait_for_resource_deletion(volume_id)
except lib_exc.NotFound:
- LOG.warn("Unable to delete volume '%s' since it was not found. "
- "Maybe it was already deleted?" % volume_id)
+ LOG.warning("Unable to delete volume '%s' since it was not found. "
+ "Maybe it was already deleted?" % volume_id)
@classmethod
def prepare_instance_network(cls):
@@ -295,14 +303,14 @@
if 'name' in kwargs:
name = kwargs.pop('name')
- image = cls.images_client.create_image(server_id, name=name)
+ image = cls.compute_images_client.create_image(server_id, name=name)
image_id = data_utils.parse_image_id(image.response['location'])
cls.images.append(image_id)
if 'wait_until' in kwargs:
- waiters.wait_for_image_status(cls.images_client,
+ waiters.wait_for_image_status(cls.compute_images_client,
image_id, kwargs['wait_until'])
- image = cls.images_client.show_image(image_id)['image']
+ image = cls.compute_images_client.show_image(image_id)['image']
if kwargs['wait_until'] == 'ACTIVE':
if kwargs.get('wait_for_server', True):
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index 975b850..0724566 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -37,7 +37,7 @@
def setup_clients(cls):
super(ImagesMetadataTestJSON, cls).setup_clients()
cls.glance_client = cls.os.image_client
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 0f02166..85d137b 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -25,7 +25,7 @@
@classmethod
def setup_clients(cls):
super(ImagesMetadataTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
@test.attr(type=['negative'])
@test.idempotent_id('94069db2-792f-4fa8-8bd3-2271a6e0c095')
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index dc62620..150e8af 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -37,7 +37,7 @@
@classmethod
def setup_clients(cls):
super(ImagesTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
cls.servers_client = cls.servers_client
@test.idempotent_id('aa06b52b-2db5-4807-b218-9441f75d74e3')
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 9197adf..8f6ede9 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -39,7 +39,7 @@
@classmethod
def setup_clients(cls):
super(ImagesNegativeTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
cls.servers_client = cls.servers_client
@test.attr(type=['negative'])
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 37c2bb6..7b978ab 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -62,7 +62,7 @@
@classmethod
def setup_clients(cls):
super(ImagesOneServerTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 9ea62fb..2fc9ef8 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -76,7 +76,7 @@
@classmethod
def setup_clients(cls):
super(ImagesOneServerNegativeTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 9f3ba71..49d9bc8 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -42,7 +42,7 @@
@classmethod
def setup_clients(cls):
super(ListImageFiltersTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
cls.glance_client = cls.os.image_client
@classmethod
diff --git a/tempest/api/compute/images/test_list_image_filters_negative.py b/tempest/api/compute/images/test_list_image_filters_negative.py
index 82062bd..34d26e2 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_negative.py
@@ -34,7 +34,7 @@
@classmethod
def setup_clients(cls):
super(ListImageFiltersNegativeTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
@test.attr(type=['negative'])
@test.idempotent_id('391b0440-432c-4d4b-b5da-c5096aa247eb')
diff --git a/tempest/api/compute/images/test_list_images.py b/tempest/api/compute/images/test_list_images.py
index 6ca15d6..ae3667d 100644
--- a/tempest/api/compute/images/test_list_images.py
+++ b/tempest/api/compute/images/test_list_images.py
@@ -32,7 +32,7 @@
@classmethod
def setup_clients(cls):
super(ListImagesTestJSON, cls).setup_clients()
- cls.client = cls.images_client
+ cls.client = cls.compute_images_client
@test.idempotent_id('490d0898-e12a-463f-aef0-c50156b9f789')
def test_get_image(self):
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 24d503f..a6ccdd3 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -47,7 +47,7 @@
cls.client = cls.os.interfaces_client
def wait_for_interface_status(self, server, port_id, status):
- """Waits for a interface to reach a given status."""
+ """Waits for an interface to reach a given status."""
body = (self.client.show_interface(server, port_id)
['interfaceAttachment'])
interface_status = body['port_state']
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index f51c2db..e1c22e5 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -262,13 +262,16 @@
'Instance validation tests are disabled.')
def test_verify_created_server_ephemeral_disk(self):
# Verify that the ephemeral disk is created when creating server
+ flavor_base = self.flavors_client.show_flavor(
+ self.flavor_ref)['flavor']
def create_flavor_with_extra_specs():
flavor_with_eph_disk_name = data_utils.rand_name('eph_flavor')
flavor_with_eph_disk_id = data_utils.rand_int_id(start=1000)
- ram = 64
- vcpus = 1
- disk = 0
+
+ ram = flavor_base['ram']
+ vcpus = flavor_base['vcpus']
+ disk = flavor_base['disk']
# Create a flavor with extra specs
flavor = (self.flavor_client.
@@ -284,9 +287,9 @@
flavor_no_eph_disk_name = data_utils.rand_name('no_eph_flavor')
flavor_no_eph_disk_id = data_utils.rand_int_id(start=1000)
- ram = 64
- vcpus = 1
- disk = 0
+ ram = flavor_base['ram']
+ vcpus = flavor_base['vcpus']
+ disk = flavor_base['disk']
# Create a flavor without extra specs
flavor = (self.flavor_client.
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 3acff98..d1ec064 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -43,7 +43,7 @@
super(ListServerFiltersTestJSON, cls).resource_setup()
# Check to see if the alternate image ref actually exists...
- images_client = cls.images_client
+ images_client = cls.compute_images_client
images = images_client.list_images()['images']
if cls.image_ref != cls.image_ref_alt and \
@@ -56,13 +56,13 @@
# Do some sanity checks here. If one of the images does
# not exist, fail early since the tests won't work...
try:
- cls.images_client.show_image(cls.image_ref)
+ cls.compute_images_client.show_image(cls.image_ref)
except lib_exc.NotFound:
raise RuntimeError("Image %s (image_ref) was not found!" %
cls.image_ref)
try:
- cls.images_client.show_image(cls.image_ref_alt)
+ cls.compute_images_client.show_image(cls.image_ref_alt)
except lib_exc.NotFound:
raise RuntimeError("Image %s (image_ref_alt) was not found!" %
cls.image_ref_alt)
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 71dfd96..d7f0d75 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -453,7 +453,7 @@
server = self.client.show_server(self.server_id)['server']
image_name = server['name'] + '-shelved'
params = {'name': image_name}
- images = self.images_client.list_images(**params)['images']
+ images = self.compute_images_client.list_images(**params)['images']
self.assertEqual(1, len(images))
self.assertEqual(image_name, images[0]['name'])
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index ed8484e..681b5db 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -490,7 +490,7 @@
server = self.client.show_server(self.server_id)['server']
image_name = server['name'] + '-shelved'
params = {'name': image_name}
- images = self.images_client.list_images(**params)['images']
+ images = self.compute_images_client.list_images(**params)['images']
self.assertEqual(1, len(images))
self.assertEqual(image_name, images[0]['name'])
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index e363fc4..bf4396d 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -48,18 +48,19 @@
def setup_clients(cls):
super(AuthorizationTestJSON, cls).setup_clients()
cls.client = cls.os.servers_client
- cls.images_client = cls.os.images_client
+ cls.compute_images_client = cls.os.compute_images_client
cls.glance_client = cls.os.image_client
cls.keypairs_client = cls.os.keypairs_client
cls.security_client = cls.os.compute_security_groups_client
- cls.rule_client = cls.os.security_group_rules_client
+ cls.rule_client = cls.os.compute_security_group_rules_client
cls.alt_client = cls.alt_manager.servers_client
- cls.alt_images_client = cls.alt_manager.images_client
+ cls.alt_compute_images_client = cls.alt_manager.compute_images_client
cls.alt_keypairs_client = cls.alt_manager.keypairs_client
cls.alt_security_client = (
cls.alt_manager.compute_security_groups_client)
- cls.alt_rule_client = cls.alt_manager.security_group_rules_client
+ cls.alt_rule_client = (
+ cls.alt_manager.compute_security_group_rules_client)
@classmethod
def resource_setup(cls):
@@ -77,7 +78,7 @@
body = cls.glance_client.update_image(image_id,
data=image_file)['image']
cls.glance_client.wait_for_image_status(image_id, 'active')
- cls.image = cls.images_client.show_image(image_id)['image']
+ cls.image = cls.compute_images_client.show_image(image_id)['image']
cls.keypairname = data_utils.rand_name('keypair')
cls.keypairs_client.create_keypair(name=cls.keypairname)
@@ -98,7 +99,7 @@
@classmethod
def resource_cleanup(cls):
if hasattr(cls, 'image'):
- cls.images_client.delete_image(cls.image['id'])
+ cls.compute_images_client.delete_image(cls.image['id'])
if hasattr(cls, 'keypairname'):
cls.keypairs_client.delete_keypair(cls.keypairname)
if hasattr(cls, 'security_group'):
@@ -175,7 +176,7 @@
def test_create_image_for_alt_account_fails(self):
# A create image request for another user's server should fail
self.assertRaises(lib_exc.NotFound,
- self.alt_images_client.create_image,
+ self.alt_compute_images_client.create_image,
self.server['id'], name='testImage')
@test.idempotent_id('95d445f6-babc-4f2e-aea3-aa24ec5e7f0d')
@@ -261,13 +262,14 @@
def test_get_image_for_alt_account_fails(self):
# A GET request for an image on another user's account should fail
self.assertRaises(lib_exc.NotFound,
- self.alt_images_client.show_image, self.image['id'])
+ self.alt_compute_images_client.show_image,
+ self.image['id'])
@test.idempotent_id('9facb962-f043-4a9d-b9ee-166a32dea098')
def test_delete_image_for_alt_account_fails(self):
# A DELETE request for another user's image should fail
self.assertRaises(lib_exc.NotFound,
- self.alt_images_client.delete_image,
+ self.alt_compute_images_client.delete_image,
self.image['id'])
@test.idempotent_id('752c917e-83be-499d-a422-3559127f7d3c')
@@ -390,7 +392,7 @@
# A set metadata for another user's image should fail
req_metadata = {'meta1': 'value1', 'meta2': 'value2'}
self.assertRaises(lib_exc.NotFound,
- self.alt_images_client.set_image_metadata,
+ self.alt_compute_images_client.set_image_metadata,
self.image['id'], req_metadata)
@test.idempotent_id('dea1936a-473d-49f2-92ad-97bb7aded22e')
@@ -408,13 +410,14 @@
def test_get_metadata_of_alt_account_image_fails(self):
# A get metadata for another user's image should fail
req_metadata = {'meta1': 'value1'}
- self.addCleanup(self.images_client.delete_image_metadata_item,
+ self.addCleanup(self.compute_images_client.delete_image_metadata_item,
self.image['id'], 'meta1')
- self.images_client.set_image_metadata(self.image['id'],
- req_metadata)
- self.assertRaises(lib_exc.NotFound,
- self.alt_images_client.show_image_metadata_item,
- self.image['id'], 'meta1')
+ self.compute_images_client.set_image_metadata(self.image['id'],
+ req_metadata)
+ self.assertRaises(
+ lib_exc.NotFound,
+ self.alt_compute_images_client.show_image_metadata_item,
+ self.image['id'], 'meta1')
@test.idempotent_id('79531e2e-e721-493c-8b30-a35db36fdaa6')
def test_delete_metadata_of_alt_account_server_fails(self):
@@ -431,13 +434,14 @@
def test_delete_metadata_of_alt_account_image_fails(self):
# A delete metadata for another user's image should fail
req_metadata = {'meta1': 'data1'}
- self.addCleanup(self.images_client.delete_image_metadata_item,
+ self.addCleanup(self.compute_images_client.delete_image_metadata_item,
self.image['id'], 'meta1')
- self.images_client.set_image_metadata(self.image['id'],
- req_metadata)
- self.assertRaises(lib_exc.NotFound,
- self.alt_images_client.delete_image_metadata_item,
- self.image['id'], 'meta1')
+ self.compute_images_client.set_image_metadata(self.image['id'],
+ req_metadata)
+ self.assertRaises(
+ lib_exc.NotFound,
+ self.alt_compute_images_client.delete_image_metadata_item,
+ self.image['id'], 'meta1')
@test.idempotent_id('b0c1e7a0-8853-40fd-8384-01f93d116cae')
def test_get_console_output_of_alt_account_server_fails(self):
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index b4837f7..468c79a 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -75,7 +75,7 @@
# Create a volume and wait for it to become ready
self.volume = self.volumes_client.create_volume(
- CONF.volume.volume_size, display_name='test')['volume']
+ size=CONF.volume.volume_size, display_name='test')['volume']
self.addCleanup(self._delete_volume)
self.volumes_client.wait_for_volume_status(self.volume['id'],
'available')
diff --git a/tempest/api/identity/admin/v2/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
index e547bdd..3f3d16e 100644
--- a/tempest/api/identity/admin/v2/test_roles.py
+++ b/tempest/api/identity/admin/v2/test_roles.py
@@ -27,7 +27,7 @@
super(RolesTestJSON, cls).resource_setup()
for _ in moves.xrange(5):
role_name = data_utils.rand_name(name='role')
- role = cls.roles_client.create_role(role_name)['role']
+ role = cls.roles_client.create_role(name=role_name)['role']
cls.data.roles.append(role)
def _get_role_params(self):
@@ -57,7 +57,7 @@
def test_role_create_delete(self):
"""Role should be created, verified, and deleted."""
role_name = data_utils.rand_name(name='role-test')
- body = self.roles_client.create_role(role_name)['role']
+ body = self.roles_client.create_role(name=role_name)['role']
self.assertEqual(role_name, body['name'])
body = self.roles_client.list_roles()['roles']
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index a57163d..c9af7c6 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -53,7 +53,7 @@
def test_role_create_blank_name(self):
# Should not be able to create a role with a blank name
self.assertRaises(lib_exc.BadRequest, self.roles_client.create_role,
- '')
+ name='')
@test.attr(type=['negative'])
@test.idempotent_id('585c8998-a8a4-4641-a5dd-abef7a8ced00')
@@ -61,7 +61,8 @@
# Non-administrator user should not be able to create role
role_name = data_utils.rand_name(name='role')
self.assertRaises(lib_exc.Forbidden,
- self.non_admin_roles_client.create_role, role_name)
+ self.non_admin_roles_client.create_role,
+ name=role_name)
@test.attr(type=['negative'])
@test.idempotent_id('a7edd17a-e34a-4aab-8bb7-fa6f498645b8')
@@ -71,7 +72,7 @@
self.client.delete_token(token)
role_name = data_utils.rand_name(name='role')
self.assertRaises(lib_exc.Unauthorized,
- self.roles_client.create_role, role_name)
+ self.roles_client.create_role, name=role_name)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative'])
@@ -79,18 +80,18 @@
def test_role_create_duplicate(self):
# Role names should be unique
role_name = data_utils.rand_name(name='role-dup')
- body = self.roles_client.create_role(role_name)['role']
+ body = self.roles_client.create_role(name=role_name)['role']
role1_id = body.get('id')
self.addCleanup(self.roles_client.delete_role, role1_id)
self.assertRaises(lib_exc.Conflict, self.roles_client.create_role,
- role_name)
+ name=role_name)
@test.attr(type=['negative'])
@test.idempotent_id('15347635-b5b1-4a87-a280-deb2bd6d865e')
def test_delete_role_by_unauthorized_user(self):
# Non-administrator user should not be able to delete role
role_name = data_utils.rand_name(name='role')
- body = self.roles_client.create_role(role_name)['role']
+ body = self.roles_client.create_role(name=role_name)['role']
self.data.roles.append(body)
role_id = body.get('id')
self.assertRaises(lib_exc.Forbidden,
@@ -101,7 +102,7 @@
def test_delete_role_request_without_token(self):
# Request to delete role without a valid token should fail
role_name = data_utils.rand_name(name='role')
- body = self.roles_client.create_role(role_name)['role']
+ body = self.roles_client.create_role(name=role_name)['role']
self.data.roles.append(body)
role_id = body.get('id')
token = self.client.auth_provider.get_token()
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index e752b02..fdb5a5a 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -77,7 +77,7 @@
# Create a role
role_name = data_utils.rand_name(name='role')
- role = self.roles_client.create_role(role_name)['role']
+ role = self.roles_client.create_role(name=role_name)['role']
self.data.roles.append(role)
# Grant the user the role on the tenants.
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index 2e9714e..d886524 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -202,7 +202,7 @@
# Updating the user with new password
new_pass = data_utils.rand_password()
update_user = self.client.update_user_password(
- self.data.user['id'], new_pass)['user']
+ self.data.user['id'], password=new_pass)['user']
self.assertEqual(update_user['id'], self.data.user['id'])
# Validate the updated password
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index e022023..21fc62a 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -86,8 +86,7 @@
def test_list_user_groups(self):
# create a user
user = self.client.create_user(
- data_utils.rand_name('User'),
- password=data_utils.rand_name('Pass'))['user']
+ data_utils.rand_name('User'), data_utils.rand_password())['user']
self.addCleanup(self.client.delete_user, user['id'])
# create two groups, and add user into them
groups = []
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index f38d25d..3b5e5d4 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -21,7 +21,7 @@
class PoliciesTestJSON(base.BaseIdentityV3AdminTest):
def _delete_policy(self, policy_id):
- self.policy_client.delete_policy(policy_id)
+ self.policies_client.delete_policy(policy_id)
@test.idempotent_id('1a0ad286-2d06-4123-ab0d-728893a76201')
def test_list_policies(self):
@@ -31,13 +31,13 @@
for _ in range(3):
blob = data_utils.rand_name('BlobName')
policy_type = data_utils.rand_name('PolicyType')
- policy = self.policy_client.create_policy(
+ policy = self.policies_client.create_policy(
blob=blob, type=policy_type)['policy']
# Delete the Policy at the end of this method
self.addCleanup(self._delete_policy, policy['id'])
policy_ids.append(policy['id'])
# List and Verify Policies
- body = self.policy_client.list_policies()['policies']
+ body = self.policies_client.list_policies()['policies']
for p in body:
fetched_ids.append(p['id'])
missing_pols = [p for p in policy_ids if p not in fetched_ids]
@@ -49,8 +49,8 @@
# Test to update policy
blob = data_utils.rand_name('BlobName')
policy_type = data_utils.rand_name('PolicyType')
- policy = self.policy_client.create_policy(blob=blob,
- type=policy_type)['policy']
+ policy = self.policies_client.create_policy(blob=blob,
+ type=policy_type)['policy']
self.addCleanup(self._delete_policy, policy['id'])
self.assertIn('id', policy)
self.assertIn('type', policy)
@@ -60,11 +60,12 @@
self.assertEqual(policy_type, policy['type'])
# Update policy
update_type = data_utils.rand_name('UpdatedPolicyType')
- data = self.policy_client.update_policy(
+ data = self.policies_client.update_policy(
policy['id'], type=update_type)['policy']
self.assertIn('type', data)
# Assertion for updated value with fetched value
- fetched_policy = self.policy_client.show_policy(policy['id'])['policy']
+ fetched_policy = self.policies_client.show_policy(
+ policy['id'])['policy']
self.assertIn('id', fetched_policy)
self.assertIn('blob', fetched_policy)
self.assertIn('type', fetched_policy)
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index ec1b12e..8bba3cb 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -25,7 +25,7 @@
@classmethod
def setup_clients(cls):
super(RegionsTestJSON, cls).setup_clients()
- cls.client = cls.region_client
+ cls.client = cls.regions_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index f194d9c..ae714aa 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -25,7 +25,7 @@
super(RolesV3TestJSON, cls).resource_setup()
for _ in range(3):
role_name = data_utils.rand_name(name='role')
- role = cls.client.create_role(role_name)['role']
+ role = cls.client.create_role(name=role_name)['role']
cls.data.v3_roles.append(role)
cls.fetched_role_ids = list()
u_name = data_utils.rand_name('user')
@@ -47,7 +47,7 @@
email=u_email, project_id=cls.project['id'],
domain_id=cls.domain['id'])['user']
cls.role = cls.client.create_role(
- data_utils.rand_name('Role'))['role']
+ name=data_utils.rand_name('Role'))['role']
@classmethod
def resource_cleanup(cls):
@@ -69,13 +69,14 @@
@test.idempotent_id('18afc6c0-46cf-4911-824e-9989cc056c3a')
def test_role_create_update_get_list(self):
r_name = data_utils.rand_name('Role')
- role = self.client.create_role(r_name)['role']
+ role = self.client.create_role(name=r_name)['role']
self.addCleanup(self.client.delete_role, role['id'])
self.assertIn('name', role)
self.assertEqual(role['name'], r_name)
new_name = data_utils.rand_name('NewRole')
- updated_role = self.client.update_role(new_name, role['id'])['role']
+ updated_role = self.client.update_role(role['id'],
+ name=new_name)['role']
self.assertIn('name', updated_role)
self.assertIn('id', updated_role)
self.assertIn('links', updated_role)
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index f5b20d5..b1446cf 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -76,7 +76,7 @@
# Create a role
role_name = data_utils.rand_name(name='role')
- role = self.client.create_role(role_name)['role']
+ role = self.client.create_role(name=role_name)['role']
self.addCleanup(self.client.delete_role, role['id'])
# Grant the user the role on both projects.
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index bf7ad71..85961b4 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -69,10 +69,10 @@
self.delegated_role = data_utils.rand_name('DelegatedRole')
self.not_delegated_role = data_utils.rand_name('NotDelegatedRole')
- role = self.client.create_role(self.delegated_role)['role']
+ role = self.client.create_role(name=self.delegated_role)['role']
self.delegated_role_id = role['id']
- role = self.client.create_role(self.not_delegated_role)['role']
+ role = self.client.create_role(name=self.not_delegated_role)['role']
self.not_delegated_role_id = role['id']
# Assign roles to trustor
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 6dbd443..a402b3f 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -117,7 +117,7 @@
self.addCleanup(self.client.delete_user, user_body['id'])
# Creating Role
role_body = self.client.create_role(
- data_utils.rand_name('role'))['role']
+ name=data_utils.rand_name('role'))['role']
# Delete the Role at the end of this method
self.addCleanup(self.client.delete_role, role_body['id'])
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index d98e3b1..d68a204 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -30,7 +30,7 @@
@classmethod
def disable_user(cls, user_name):
user = cls.get_user_by_name(user_name)
- cls.client.enable_disable_user(user['id'], False)
+ cls.client.enable_disable_user(user['id'], enabled=False)
@classmethod
def disable_tenant(cls, tenant_name):
@@ -143,9 +143,9 @@
cls.client = cls.os_adm.identity_v3_client
cls.token = cls.os_adm.token_v3_client
cls.endpoints_client = cls.os_adm.endpoints_client
- cls.region_client = cls.os_adm.region_client
+ cls.regions_client = cls.os_adm.regions_client
cls.services_client = cls.os_adm.identity_services_client
- cls.policy_client = cls.os_adm.policy_client
+ cls.policies_client = cls.os_adm.policies_client
cls.creds_client = cls.os_adm.credentials_client
cls.groups_client = cls.os_adm.groups_client
@@ -237,7 +237,8 @@
def setup_test_role(self):
"""Set up a test role."""
self.test_role = data_utils.rand_name('role')
- self.role = self.roles_client.create_role(self.test_role)['role']
+ self.role = self.roles_client.create_role(
+ name=self.test_role)['role']
self.roles.append(self.role)
def setup_test_v3_user(self):
@@ -265,7 +266,7 @@
def setup_test_v3_role(self):
"""Set up a test v3 role."""
self.test_role = data_utils.rand_name('role')
- self.v3_role = self.client.create_role(self.test_role)['role']
+ self.v3_role = self.client.create_role(name=self.test_role)['role']
self.v3_roles.append(self.v3_role)
def setup_test_domain(self):
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 5f2a8c4..98a2e68 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -51,14 +51,10 @@
# to change password back. important for allow_tenant_isolation = false
self.addCleanup(
self.non_admin_client_for_cleanup.update_user_own_password,
- user_id=user_id,
- new_pass=old_pass,
- old_pass=new_pass)
-
+ user_id, original_password=new_pass, password=old_pass)
# user updates own password
self.non_admin_client.update_user_own_password(
- user_id=user_id, new_pass=new_pass, old_pass=old_pass)
-
+ user_id, password=new_pass, original_password=old_pass)
# TODO(lbragstad): Sleeping after the response status has been checked
# and the body loaded as JSON allows requests to fail-fast. The sleep
# is necessary because keystone will err on the side of security and
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index c3205ce..18d0446 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -62,18 +62,12 @@
@classmethod
def create_image(cls, **kwargs):
"""Wrapper that returns a test image."""
- name = data_utils.rand_name(cls.__name__ + "-instance")
- if 'name' in kwargs:
- name = kwargs.pop('name')
+ if 'name' not in kwargs:
+ name = data_utils.rand_name(cls.__name__ + "-instance")
+ kwargs['name'] = name
- container_format = kwargs.pop('container_format')
- disk_format = kwargs.pop('disk_format')
-
- image = cls.client.create_image(name=name,
- container_format=container_format,
- disk_format=disk_format,
- **kwargs)
+ image = cls.client.create_image(**kwargs)
# Image objects returned by the v1 client have the image
# data inside a dict that is keyed against 'image'.
if 'image' in image:
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index 3d94408..f16b80e 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -27,13 +27,17 @@
def test_register_with_invalid_container_format(self):
# Negative tests for invalid data supplied to POST /images
self.assertRaises(lib_exc.BadRequest, self.client.create_image,
- 'test', 'wrong', 'vhd')
+ name='test',
+ container_format='wrong',
+ disk_format='vhd',)
@test.attr(type=['negative'])
@test.idempotent_id('993face5-921d-4e84-aabf-c1bba4234a67')
def test_register_with_invalid_disk_format(self):
self.assertRaises(lib_exc.BadRequest, self.client.create_image,
- 'test', 'bare', 'wrong')
+ name='test',
+ container_format='bare',
+ disk_format='wrong',)
@test.attr(type=['negative'])
@test.idempotent_id('bb016f15-0820-4f27-a92d-09b2f67d2488')
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 2e6c268..04582c6 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -147,7 +147,7 @@
for disk_fmt in disk_fmts]
for (container_fmt, disk_fmt) in all_pairs[:6]:
- LOG.debug("Creating a image"
+ LOG.debug("Creating an image"
"(Container format: %s, Disk format: %s).",
container_fmt, disk_fmt)
cls._create_standard_image(container_fmt, disk_fmt)
diff --git a/tempest/api/network/admin/test_agent_management.py b/tempest/api/network/admin/test_agent_management.py
index 64802aa..61f8e15 100644
--- a/tempest/api/network/admin/test_agent_management.py
+++ b/tempest/api/network/admin/test_agent_management.py
@@ -29,13 +29,13 @@
@classmethod
def resource_setup(cls):
super(AgentManagementTestJSON, cls).resource_setup()
- body = cls.admin_client.list_agents()
+ body = cls.admin_agents_client.list_agents()
agents = body['agents']
cls.agent = agents[0]
@test.idempotent_id('9c80f04d-11f3-44a4-8738-ed2f879b0ff4')
def test_list_agent(self):
- body = self.admin_client.list_agents()
+ body = self.admin_agents_client.list_agents()
agents = body['agents']
# Hearthbeats must be excluded from comparison
self.agent.pop('heartbeat_timestamp', None)
@@ -47,12 +47,12 @@
@test.idempotent_id('e335be47-b9a1-46fd-be30-0874c0b751e6')
def test_list_agents_non_admin(self):
- body = self.client.list_agents()
+ body = self.agents_client.list_agents()
self.assertEqual(len(body["agents"]), 0)
@test.idempotent_id('869bc8e8-0fda-4a30-9b71-f8a7cf58ca9f')
def test_show_agent(self):
- body = self.admin_client.show_agent(self.agent['id'])
+ body = self.admin_agents_client.show_agent(self.agent['id'])
agent = body['agent']
self.assertEqual(agent['id'], self.agent['id'])
@@ -62,8 +62,8 @@
# Try to update the 'admin_state_up' to the original
# one to avoid the negative effect.
agent_status = {'admin_state_up': origin_status}
- body = self.admin_client.update_agent(agent_id=self.agent['id'],
- agent=agent_status)
+ body = self.admin_agents_client.update_agent(agent_id=self.agent['id'],
+ agent=agent_status)
updated_status = body['agent']['admin_state_up']
self.assertEqual(origin_status, updated_status)
@@ -72,8 +72,8 @@
self.useFixture(fixtures.LockFixture('agent_description'))
description = 'description for update agent.'
agent_description = {'description': description}
- body = self.admin_client.update_agent(agent_id=self.agent['id'],
- agent=agent_description)
+ body = self.admin_agents_client.update_agent(agent_id=self.agent['id'],
+ agent=agent_description)
self.addCleanup(self._restore_agent)
updated_description = body['agent']['description']
self.assertEqual(updated_description, description)
@@ -83,5 +83,5 @@
description = self.agent['description'] or ''
origin_agent = {'description': description}
- self.admin_client.update_agent(agent_id=self.agent['id'],
- agent=origin_agent)
+ self.admin_agents_client.update_agent(agent_id=self.agent['id'],
+ agent=origin_agent)
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index f186b36..5ff465b 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -51,7 +51,7 @@
def _check_network_in_dhcp_agent(self, network_id, agent):
network_ids = []
- body = self.admin_client.list_networks_hosted_by_one_dhcp_agent(
+ body = self.admin_agents_client.list_networks_hosted_by_one_dhcp_agent(
agent['id'])
networks = body['networks']
for network in networks:
@@ -65,7 +65,7 @@
self.ports.remove(self.port)
agent = dict()
agent['agent_type'] = None
- body = self.admin_client.list_agents()
+ body = self.admin_agents_client.list_agents()
agents = body['agents']
for a in agents:
if a['agent_type'] == 'DHCP agent':
@@ -84,14 +84,14 @@
self._remove_network_from_dhcp_agent(network_id, agent)
def _remove_network_from_dhcp_agent(self, network_id, agent):
- self.admin_client.remove_network_from_dhcp_agent(
+ self.admin_agents_client.remove_network_from_dhcp_agent(
agent_id=agent['id'],
network_id=network_id)
self.assertFalse(self._check_network_in_dhcp_agent(
network_id, agent))
def _add_dhcp_agent_to_network(self, network_id, agent):
- self.admin_client.add_dhcp_agent_to_network(agent['id'],
- network_id=network_id)
+ self.admin_agents_client.add_dhcp_agent_to_network(
+ agent['id'], network_id=network_id)
self.assertTrue(self._check_network_in_dhcp_agent(
network_id, agent))
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index 36747a3..c64cf77 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -14,9 +14,11 @@
from tempest.api.network import base
from tempest.common.utils import data_utils
+from tempest import config
from tempest import exceptions
from tempest import test
+CONF = config.CONF
AGENT_TYPE = 'L3 agent'
AGENT_MODES = (
'legacy',
@@ -51,7 +53,7 @@
@classmethod
def resource_setup(cls):
super(L3AgentSchedulerTestJSON, cls).resource_setup()
- body = cls.admin_client.list_agents()
+ body = cls.admin_agents_client.list_agents()
agents = body['agents']
for agent in agents:
# TODO(armax): falling back on default _agent_mode can be
@@ -80,6 +82,19 @@
cls.port = cls.create_port(cls.network)
cls.client.add_router_interface_with_port_id(
cls.router['id'], cls.port['id'])
+ # NOTE: Sometimes we have seen this test fail with dvr in,
+ # multinode tests, since the dhcp port is not created before
+ # the test gets executed and so the router is not scheduled
+ # on the given agent. By adding the external gateway info to
+ # the router, the router should be properly scheduled in the
+ # dvr_snat node.
+ # This is a temporary work around to prevent a race condition.
+ external_gateway_info = {
+ 'network_id': CONF.network.public_network_id,
+ 'enable_snat': True}
+ cls.admin_client.update_router_with_snat_gw_info(
+ cls.router['id'],
+ external_gateway_info=external_gateway_info)
@classmethod
def resource_cleanup(cls):
@@ -90,12 +105,12 @@
@test.idempotent_id('b7ce6e89-e837-4ded-9b78-9ed3c9c6a45a')
def test_list_routers_on_l3_agent(self):
- self.admin_client.list_routers_on_l3_agent(self.agent['id'])
+ self.admin_agents_client.list_routers_on_l3_agent(self.agent['id'])
@test.idempotent_id('9464e5e7-8625-49c3-8fd1-89c52be59d66')
def test_add_list_remove_router_on_l3_agent(self):
l3_agent_ids = list()
- self.admin_client.add_router_to_l3_agent(
+ self.admin_agents_client.add_router_to_l3_agent(
self.agent['id'],
router_id=self.router['id'])
body = (
@@ -105,7 +120,7 @@
self.assertIn('agent_type', agent)
self.assertEqual('L3 agent', agent['agent_type'])
self.assertIn(self.agent['id'], l3_agent_ids)
- body = self.admin_client.remove_router_from_l3_agent(
+ body = self.admin_agents_client.remove_router_from_l3_agent(
self.agent['id'],
self.router['id'])
# NOTE(afazekas): The deletion not asserted, because neutron
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index e155bd0..2a1776a 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -71,7 +71,9 @@
def setup_clients(cls):
super(BaseNetworkTest, cls).setup_clients()
cls.client = cls.os.network_client
+ cls.agents_client = cls.os.network_agents_client
cls.networks_client = cls.os.networks_client
+ cls.subnetpools_client = cls.os.subnetpools_client
cls.subnets_client = cls.os.subnets_client
cls.ports_client = cls.os.ports_client
cls.quotas_client = cls.os.network_quotas_client
@@ -273,6 +275,7 @@
def setup_clients(cls):
super(BaseAdminNetworkTest, cls).setup_clients()
cls.admin_client = cls.os_adm.network_client
+ cls.admin_agents_client = cls.os_adm.network_agents_client
cls.admin_networks_client = cls.os_adm.networks_client
cls.admin_subnets_client = cls.os_adm.subnets_client
cls.admin_ports_client = cls.os_adm.ports_client
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
index 8a61ff8..e5d0462 100644
--- a/tempest/api/network/test_subnetpools_extensions.py
+++ b/tempest/api/network/test_subnetpools_extensions.py
@@ -50,27 +50,28 @@
subnetpool_name = data_utils.rand_name('subnetpools')
# create subnet pool
prefix = CONF.network.default_network
- body = self.client.create_subnetpools(name=subnetpool_name,
- prefixes=prefix)
+ body = self.subnetpools_client.create_subnetpool(name=subnetpool_name,
+ prefixes=prefix)
subnetpool_id = body["subnetpool"]["id"]
self.addCleanup(self._cleanup_subnetpools, subnetpool_id)
self.assertEqual(subnetpool_name, body["subnetpool"]["name"])
# get detail about subnet pool
- body = self.client.show_subnetpools(subnetpool_id)
+ body = self.subnetpools_client.show_subnetpool(subnetpool_id)
self.assertEqual(subnetpool_name, body["subnetpool"]["name"])
# update the subnet pool
subnetpool_name = data_utils.rand_name('subnetpools_update')
- body = self.client.update_subnetpools(subnetpool_id,
- name=subnetpool_name)
+ body = self.subnetpools_client.update_subnetpool(subnetpool_id,
+ name=subnetpool_name)
self.assertEqual(subnetpool_name, body["subnetpool"]["name"])
# delete subnet pool
- body = self.client.delete_subnetpools(subnetpool_id)
- self.assertRaises(lib_exc.NotFound, self.client.show_subnetpools,
+ body = self.subnetpools_client.delete_subnetpool(subnetpool_id)
+ self.assertRaises(lib_exc.NotFound,
+ self.subnetpools_client.show_subnetpool,
subnetpool_id)
def _cleanup_subnetpools(self, subnetpool_id):
# this is used to cleanup the resources
try:
- self.client.delete_subnetpools(subnetpool_id)
+ self.subnetpools_client.delete_subnetpool(subnetpool_id)
except lib_exc.NotFound:
pass
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index acb591d..c032d9c 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -70,7 +70,7 @@
# Update volume with new volume_type
self.volumes_client.retype_volume(volume['id'],
- volume_type=volume_types[1]['id'])
+ new_type=volume_types[1]['id'])
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
# Get volume details and Verify
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index 6c32321..253a3e1 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -48,12 +48,12 @@
def _reset_volume_status(self, volume_id, status):
# Reset the volume status
body = self.admin_volume_client.reset_volume_status(volume_id,
- status)
+ status=status)
return body
def tearDown(self):
# Set volume's status to available after test
- self._reset_volume_status(self.volume['id'], 'available')
+ self._reset_volume_status(self.volume['id'], status='available')
super(VolumesActionsV2Test, self).tearDown()
def _create_temp_volume(self):
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 5c4d0e1..dc53450 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -62,7 +62,7 @@
super(BaseVolumeTest, cls).setup_clients()
cls.servers_client = cls.os.servers_client
cls.compute_networks_client = cls.os.compute_networks_client
- cls.images_client = cls.os.images_client
+ cls.compute_images_client = cls.os.compute_images_client
if cls._api_version == 1:
cls.snapshots_client = cls.os.snapshots_client
@@ -106,14 +106,14 @@
super(BaseVolumeTest, cls).resource_cleanup()
@classmethod
- def create_volume(cls, size=None, **kwargs):
+ def create_volume(cls, **kwargs):
"""Wrapper utility that returns a test volume."""
name = data_utils.rand_name('Volume')
name_field = cls.special_fields['name_field']
kwargs[name_field] = name
- volume = cls.volumes_client.create_volume(size, **kwargs)['volume']
+ volume = cls.volumes_client.create_volume(**kwargs)['volume']
cls.volumes.append(volume)
cls.volumes_client.wait_for_volume_status(volume['id'], 'available')
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index e50ca95..688baf5 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -45,7 +45,7 @@
def tearDown(self):
# Update the metadata to {}
- self.client.update_snapshot_metadata(self.snapshot_id, {})
+ self.client.update_snapshot_metadata(self.snapshot_id, metadata={})
super(SnapshotV2MetadataTestJSON, self).tearDown()
@test.idempotent_id('a2f20f99-e363-4584-be97-bc33afb1a56c')
@@ -89,7 +89,7 @@
# Update metadata item
body = self.client.update_snapshot_metadata(
- self.snapshot_id, update)['metadata']
+ self.snapshot_id, metadata=update)['metadata']
# Get the metadata of the snapshot
body = self.client.show_snapshot_metadata(
self.snapshot_id)['metadata']
@@ -114,7 +114,7 @@
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
# Update metadata item
body = self.client.update_snapshot_metadata_item(
- self.snapshot_id, "key3", update_item)['meta']
+ self.snapshot_id, "key3", meta=update_item)['meta']
# Get the metadata of the snapshot
body = self.client.show_snapshot_metadata(
self.snapshot_id)['metadata']
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index c0b6b7e..7046dcf 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -47,7 +47,8 @@
self.addCleanup(self._delete_volume, volume['id'])
# Create a volume transfer
- transfer = self.client.create_volume_transfer(volume['id'])['transfer']
+ transfer = self.client.create_volume_transfer(
+ volume_id=volume['id'])['transfer']
transfer_id = transfer['id']
auth_key = transfer['auth_key']
self.client.wait_for_volume_status(volume['id'],
@@ -63,8 +64,8 @@
self.assertThat(len(body), matchers.GreaterThan(0))
# Accept a volume transfer by alt_tenant
- body = self.alt_client.accept_volume_transfer(transfer_id,
- auth_key)['transfer']
+ body = self.alt_client.accept_volume_transfer(
+ transfer_id, auth_key=auth_key)['transfer']
self.alt_client.wait_for_volume_status(volume['id'], 'available')
@test.idempotent_id('ab526943-b725-4c07-b875-8e8ef87a2c30')
@@ -74,7 +75,8 @@
self.addCleanup(self._delete_volume, volume['id'])
# Create a volume transfer
- body = self.client.create_volume_transfer(volume['id'])['transfer']
+ body = self.client.create_volume_transfer(
+ volume_id=volume['id'])['transfer']
transfer_id = body['id']
self.client.wait_for_volume_status(volume['id'],
'awaiting-transfer')
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index d4636ee..5f9ea7f 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -62,8 +62,8 @@
# Volume is attached and detached successfully from an instance
mountpoint = '/dev/vdc'
self.client.attach_volume(self.volume['id'],
- self.server['id'],
- mountpoint)
+ instance_uuid=self.server['id'],
+ mountpoint=mountpoint)
self.client.wait_for_volume_status(self.volume['id'], 'in-use')
self.client.detach_volume(self.volume['id'])
self.client.wait_for_volume_status(self.volume['id'], 'available')
@@ -74,7 +74,8 @@
def test_volume_bootable(self):
# Verify that a volume bootable flag is retrieved
for bool_bootable in [True, False]:
- self.client.set_bootable_volume(self.volume['id'], bool_bootable)
+ self.client.set_bootable_volume(self.volume['id'],
+ bootable=bool_bootable)
fetched_volume = self.client.show_volume(
self.volume['id'])['volume']
# Get Volume information
@@ -88,8 +89,8 @@
# Verify that a volume's attachment information is retrieved
mountpoint = '/dev/vdc'
self.client.attach_volume(self.volume['id'],
- self.server['id'],
- mountpoint)
+ instance_uuid=self.server['id'],
+ mountpoint=mountpoint)
self.client.wait_for_volume_status(self.volume['id'], 'in-use')
# NOTE(gfidente): added in reverse order because functions will be
# called in reverse order to the order they are added (LIFO)
@@ -114,8 +115,8 @@
# using the Glance image_client and from Cinder via tearDownClass.
image_name = data_utils.rand_name('Image')
body = self.client.upload_volume(
- self.volume['id'], image_name,
- CONF.volume.disk_format)['os-volume_upload_image']
+ 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.image_client.wait_for_image_status(image_id, 'active')
@@ -142,7 +143,7 @@
# Update volume readonly true
readonly = True
self.client.update_volume_readonly(self.volume['id'],
- readonly)
+ readonly=readonly)
# Get Volume information
fetched_volume = self.client.show_volume(self.volume['id'])['volume']
bool_flag = self._is_true(fetched_volume['metadata']['readonly'])
@@ -150,7 +151,8 @@
# Update volume readonly false
readonly = False
- self.client.update_volume_readonly(self.volume['id'], readonly)
+ self.client.update_volume_readonly(self.volume['id'],
+ readonly=readonly)
# Get Volume information
fetched_volume = self.client.show_volume(self.volume['id'])['volume']
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 78f5571..ed1e5c5 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -32,7 +32,7 @@
# Extend Volume Test.
self.volume = self.create_volume()
extend_size = int(self.volume['size']) + 1
- self.client.extend_volume(self.volume['id'], extend_size)
+ self.client.extend_volume(self.volume['id'], new_size=extend_size)
self.client.wait_for_volume_status(self.volume['id'], 'available')
volume = self.client.show_volume(self.volume['id'])['volume']
self.assertEqual(int(volume['size']), extend_size)
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 35c8898..aa3ef2f 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -133,7 +133,8 @@
@test.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
@test.services('image')
def test_volume_create_get_update_delete_from_image(self):
- image = self.images_client.show_image(CONF.compute.image_ref)['image']
+ image = self.compute_images_client.show_image(
+ CONF.compute.image_ref)['image']
min_disk = image.get('minDisk')
disk_size = max(min_disk, CONF.volume.volume_size)
self._volume_create_get_update_delete(
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 0af40ea..ad6f556 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -190,8 +190,8 @@
self.assertRaises(lib_exc.NotFound,
self.client.attach_volume,
str(uuid.uuid4()),
- server['id'],
- self.mountpoint)
+ instance_uuid=server['id'],
+ mountpoint=self.mountpoint)
@test.attr(type=['negative'])
@test.idempotent_id('9f9c24e4-011d-46b5-b992-952140ce237a')
@@ -206,7 +206,7 @@
# Extend volume with smaller size than original size.
extend_size = 0
self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
- self.volume['id'], extend_size)
+ self.volume['id'], new_size=extend_size)
@test.attr(type=['negative'])
@test.idempotent_id('5d0b480d-e833-439f-8a5a-96ad2ed6f22f')
@@ -214,7 +214,7 @@
# Extend volume when size is non number.
extend_size = 'abc'
self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
- self.volume['id'], extend_size)
+ self.volume['id'], new_size=extend_size)
@test.attr(type=['negative'])
@test.idempotent_id('355218f1-8991-400a-a6bb-971239287d92')
@@ -222,7 +222,7 @@
# Extend volume with None size.
extend_size = None
self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
- self.volume['id'], extend_size)
+ self.volume['id'], new_size=extend_size)
@test.attr(type=['negative'])
@test.idempotent_id('8f05a943-013c-4063-ac71-7baf561e82eb')
@@ -230,7 +230,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()), extend_size)
+ str(uuid.uuid4()), new_size=extend_size)
@test.attr(type=['negative'])
@test.idempotent_id('aff8ba64-6d6f-4f2e-bc33-41a08ee9f115')
@@ -238,7 +238,7 @@
# Extend volume size when passing volume id is None.
extend_size = int(self.volume['size']) + 1
self.assertRaises(lib_exc.NotFound, self.client.extend_volume,
- None, extend_size)
+ None, new_size=extend_size)
@test.attr(type=['negative'])
@test.idempotent_id('ac6084c0-0546-45f9-b284-38a367e0e0e2')
diff --git a/tempest/clients.py b/tempest/clients.py
index 8564c64..333852e 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -52,7 +52,7 @@
from tempest_lib.services.compute.security_group_default_rules_client import \
SecurityGroupDefaultRulesClient
from tempest_lib.services.compute.security_group_rules_client import \
- SecurityGroupRulesClient
+ SecurityGroupRulesClient as ComputeSecurityGroupRulesClient
from tempest_lib.services.compute.security_groups_client import \
SecurityGroupsClient as ComputeSecurityGroupsClient
from tempest_lib.services.compute.server_groups_client import \
@@ -99,16 +99,18 @@
from tempest.services.identity.v3.json.groups_client import \
GroupsClient as GroupsV3Client
from tempest.services.identity.v3.json.identity_client import IdentityV3Client
-from tempest.services.identity.v3.json.policy_client import \
- PolicyClient as PolicyV3Client
-from tempest.services.identity.v3.json.region_client import \
- RegionClient as RegionV3Client
+from tempest.services.identity.v3.json.policies_client import \
+ PoliciesClient as PoliciesV3Client
+from tempest.services.identity.v3.json.regions_client import \
+ RegionsClient as RegionsV3Client
from tempest.services.identity.v3.json.services_client import \
ServicesClient as IdentityServicesV3Client
from tempest.services.image.v1.json.images_client import ImagesClient
from tempest.services.image.v2.json.images_client import ImagesClientV2
from tempest.services.messaging.json.messaging_client import \
MessagingClient
+from tempest.services.network.json.agents_client import AgentsClient \
+ as NetworkAgentsClient
from tempest.services.network.json.floating_ips_client import FloatingIPsClient
from tempest.services.network.json.metering_label_rules_client import \
MeteringLabelRulesClient
@@ -121,6 +123,7 @@
as NetworkQuotasClient
from tempest.services.network.json.security_groups_client import \
SecurityGroupsClient
+from tempest.services.network.json.subnetpools_client import SubnetpoolsClient
from tempest.services.network.json.subnets_client import SubnetsClient
from tempest.services.object_storage.account_client import AccountClient
from tempest.services.object_storage.container_client import ContainerClient
@@ -189,9 +192,30 @@
}
default_params_with_timeout_values.update(default_params)
- def __init__(self, credentials, service=None):
- super(Manager, self).__init__(credentials=credentials)
+ def __init__(self, credentials, service=None, api_microversions=None):
+ """Initialization of Manager class.
+ Setup all services clients and make them available for tests cases.
+ :param credentials: type Credentials or TestResources
+ :param service: Service name
+ :param api_microversions: This is dict of services catalog type
+ and their microversion which will be set on respective
+ services clients.
+ {<service catalog type>: request_microversion}
+ Example :
+ {'compute': request_microversion}
+ - request_microversion will be set on all compute
+ service clients.
+ OR
+ {'compute': request_microversion,
+ 'volume': request_microversion}
+ - request_microversion of compute will be set on all
+ compute service clients.
+ - request_microversion of volume will be set on all
+ volume service clients.
+ """
+ super(Manager, self).__init__(credentials=credentials)
+ self.api_microversions = api_microversions or {}
self._set_compute_clients()
self._set_database_clients()
self._set_identity_clients()
@@ -204,6 +228,14 @@
CONF.identity.region,
endpoint_type=CONF.baremetal.endpoint_type,
**self.default_params_with_timeout_values)
+ self.network_agents_client = NetworkAgentsClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
self.network_client = NetworkClient(
self.auth_provider,
CONF.network.catalog_type,
@@ -220,6 +252,14 @@
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**self.default_params)
+ self.subnetpools_client = SubnetpoolsClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
self.subnets_client = SubnetsClient(
self.auth_provider,
CONF.network.catalog_type,
@@ -329,6 +369,8 @@
self.negative_client = negative_rest_client.NegativeRestClient(
self.auth_provider, service, **self.default_params)
+ self._set_api_microversions()
+
def _set_compute_clients(self):
params = {
'service': CONF.compute.catalog_type,
@@ -356,7 +398,8 @@
self.server_groups_client = ServerGroupsClient(
self.auth_provider, **params)
self.limits_client = LimitsClient(self.auth_provider, **params)
- self.images_client = ComputeImagesClient(self.auth_provider, **params)
+ self.compute_images_client = ComputeImagesClient(self.auth_provider,
+ **params)
self.keypairs_client = KeyPairsClient(self.auth_provider, **params)
self.quotas_client = QuotasClient(self.auth_provider, **params)
self.quota_classes_client = QuotaClassesClient(self.auth_provider,
@@ -370,8 +413,8 @@
self.auth_provider, **params)
self.compute_floating_ips_client = ComputeFloatingIPsClient(
self.auth_provider, **params)
- self.security_group_rules_client = SecurityGroupRulesClient(
- self.auth_provider, **params)
+ self.compute_security_group_rules_client = \
+ ComputeSecurityGroupRulesClient(self.auth_provider, **params)
self.compute_security_groups_client = ComputeSecurityGroupsClient(
self.auth_provider, **params)
self.interfaces_client = InterfacesClient(self.auth_provider,
@@ -460,8 +503,9 @@
**params_v3)
self.identity_services_client = IdentityServicesV3Client(
self.auth_provider, **params_v3)
- self.policy_client = PolicyV3Client(self.auth_provider, **params_v3)
- self.region_client = RegionV3Client(self.auth_provider, **params_v3)
+ self.policies_client = PoliciesV3Client(self.auth_provider,
+ **params_v3)
+ self.regions_client = RegionsV3Client(self.auth_provider, **params_v3)
self.credentials_client = CredentialsV3Client(self.auth_provider,
**params_v3)
self.groups_client = GroupsV3Client(self.auth_provider, **params_v3)
@@ -546,3 +590,15 @@
self.account_client = AccountClient(self.auth_provider, **params)
self.container_client = ContainerClient(self.auth_provider, **params)
self.object_client = ObjectClient(self.auth_provider, **params)
+
+ def _set_api_microversions(self):
+ service_clients = [x for x in self.__dict__ if x.endswith('_client')]
+ for client in service_clients:
+ client_obj = getattr(self, client)
+ microversion = self.api_microversions.get(client_obj.service)
+ if microversion:
+ if hasattr(client_obj, 'set_api_microversion'):
+ client_obj.set_api_microversion(microversion)
+ else:
+ LOG.debug("Need to implement set_api_microversion on %s"
+ % client)
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index b90ee04..5a2713b 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -201,7 +201,8 @@
if tenant not in existing:
tenants_admin.create_tenant(tenant)
else:
- LOG.warn("Tenant '%s' already exists in this environment" % tenant)
+ LOG.warning("Tenant '%s' already exists in this environment"
+ % tenant)
LOG.info('Tenants created')
for u in resources['users']:
try:
@@ -220,8 +221,8 @@
enabled=True)
break
else:
- LOG.warn("User '%s' already exists in this environment. "
- "New name generated" % u['name'])
+ LOG.warning("User '%s' already exists in this environment. "
+ "New name generated" % u['name'])
u['name'] = random_user_name(opts.tag, u['prefix'])
LOG.info('Users created')
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index b79bff4..7b73a61 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -51,6 +51,7 @@
Please run with **--help** to see full list of options.
"""
import sys
+import traceback
from cliff import command
from oslo_log import log as logging
@@ -74,6 +75,16 @@
super(TempestCleanup, self).__init__(app, cmd)
def take_action(self, parsed_args):
+ try:
+ self.init(parsed_args)
+ self._cleanup()
+ except Exception:
+ LOG.exception("Failure during cleanup")
+ traceback.print_exc()
+ raise
+ return 0
+
+ def init(self, parsed_args):
cleanup_service.init_conf()
self.options = parsed_args
self.admin_mgr = credentials.AdminManager()
@@ -96,10 +107,9 @@
return
self._load_json()
- self._cleanup()
def _cleanup(self):
- LOG.debug("Begin cleanup")
+ print ("Begin cleanup")
is_dry_run = self.options.dry_run
is_preserve = not self.options.delete_tempest_conf_objects
is_save_state = False
@@ -118,7 +128,7 @@
'is_save_state': is_save_state}
tenant_service = cleanup_service.TenantService(admin_mgr, **kwargs)
tenants = tenant_service.list()
- LOG.debug("Process %s tenants" % len(tenants))
+ print ("Process %s tenants" % len(tenants))
# Loop through list of tenants and clean them up.
for tenant in tenants:
@@ -149,7 +159,7 @@
self._remove_admin_role(tenant_id)
def _clean_tenant(self, tenant):
- LOG.debug("Cleaning tenant: %s " % tenant['name'])
+ print ("Cleaning tenant: %s " % tenant['name'])
is_dry_run = self.options.dry_run
dry_run_data = self.dry_run_data
is_preserve = not self.options.delete_tempest_conf_objects
@@ -259,7 +269,7 @@
return False
def _init_state(self):
- LOG.debug("Initializing saved state.")
+ print ("Initializing saved state.")
data = {}
admin_mgr = self.admin_mgr
kwargs = {'data': data,
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 2aeb5b1..8538509 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -775,7 +775,7 @@
class ImageService(BaseService):
def __init__(self, manager, **kwargs):
super(ImageService, self).__init__(kwargs)
- self.client = manager.images_client
+ self.client = manager.compute_images_client
def list(self):
client = self.client
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index fd35eab..9d889bd 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -311,7 +311,8 @@
if tenant not in existing:
admin.tenants.create_tenant(tenant)['tenant']
else:
- LOG.warn("Tenant '%s' already exists in this environment" % tenant)
+ LOG.warning("Tenant '%s' already exists in this environment"
+ % tenant)
def destroy_tenants(tenants):
@@ -376,8 +377,8 @@
try:
identity.get_user_by_username(admin.identity,
tenant['id'], u['name'])
- LOG.warn("User '%s' already exists in this environment"
- % u['name'])
+ LOG.warning("User '%s' already exists in this environment"
+ % u['name'])
except lib_exc.NotFound:
admin.identity.create_user(
u['name'], u['pass'], tenant['id'],
@@ -1022,7 +1023,9 @@
server_id = _get_server_by_name(client, volume['server'])['id']
volume_id = _get_volume_by_name(client, volume['name'])['id']
device = volume['device']
- client.volumes.attach_volume(volume_id, server_id, device)
+ client.volumes.attach_volume(volume_id,
+ instance_uuid=server_id,
+ mountpoint=device)
#######################
@@ -1074,7 +1077,7 @@
destroy_secgroups(RES['secgroups'])
destroy_users(RES['users'])
destroy_tenants(RES['tenants'])
- LOG.warn("Destroy mode incomplete")
+ LOG.warning("Destroy mode incomplete")
def get_options():
diff --git a/tempest/cmd/list_plugins.py b/tempest/cmd/list_plugins.py
new file mode 100644
index 0000000..1f1ff1a
--- /dev/null
+++ b/tempest/cmd/list_plugins.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+# 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.
+
+"""
+Utility for listing all currently installed Tempest plugins.
+
+**Usage:** ``tempest list-plugins``.
+"""
+
+from cliff import command
+from oslo_log import log as logging
+import prettytable
+
+from tempest.test_discover.plugins import TempestTestPluginManager
+
+LOG = logging.getLogger(__name__)
+
+
+class TempestListPlugins(command.Command):
+ def take_action(self, parsed_args):
+ self._list_plugins()
+ return 0
+
+ def get_description(self):
+ return 'List all tempest plugins'
+
+ def _list_plugins(self):
+ plugins = TempestTestPluginManager()
+
+ output = prettytable.PrettyTable(["Name", "EntryPoint"])
+ for plugin in plugins.ext_plugins.extensions:
+ output.add_row([
+ plugin.name, plugin.entry_point_target])
+
+ print(output)
diff --git a/tempest/cmd/run_stress.py b/tempest/cmd/run_stress.py
index 5c6f200..943fe5b 100644
--- a/tempest/cmd/run_stress.py
+++ b/tempest/cmd/run_stress.py
@@ -22,6 +22,7 @@
except ImportError:
# unittest in python 2.6 does not contain loader, so uses unittest2
from unittest2 import loader
+import traceback
from cliff import command
from oslo_log import log as logging
@@ -79,7 +80,13 @@
return pa
def take_action(self, pa):
- return action(pa)
+ try:
+ action(pa)
+ except Exception:
+ LOG.exception("Failure in the stress test framework")
+ traceback.print_exc()
+ raise
+ return 0
def get_description(self):
return 'Run tempest stress tests'
@@ -152,4 +159,5 @@
sys.exit(main())
except Exception:
LOG.exception("Failure in the stress test framework")
+ traceback.print_exc()
sys.exit(1)
diff --git a/tempest/common/api_version_utils.py b/tempest/common/api_version_utils.py
index c499f23..ac3322e 100644
--- a/tempest/common/api_version_utils.py
+++ b/tempest/common/api_version_utils.py
@@ -39,7 +39,7 @@
if ((min_version > max_version) or
(config_min_version > config_max_version)):
msg = ("Min version is greater than Max version. Test Class versions "
- "[%s - %s]. configration versions [%s - %s]."
+ "[%s - %s]. configuration versions [%s - %s]."
% (min_version.get_string(),
max_version.get_string(),
config_min_version.get_string(),
@@ -56,9 +56,16 @@
if (max_version < config_min_version or
config_max_version < min_version):
msg = ("The microversion range[%s - %s] of this test is out of the "
- "configration range[%s - %s]."
+ "configuration range[%s - %s]."
% (min_version.get_string(),
max_version.get_string(),
config_min_version.get_string(),
config_max_version.get_string()))
raise testtools.TestCase.skipException(msg)
+
+
+def select_request_microversion(test_min_version, cfg_min_version):
+ test_version = api_version_request.APIVersionRequest(test_min_version)
+ cfg_version = api_version_request.APIVersionRequest(cfg_min_version)
+ max_version = cfg_version if cfg_version >= test_version else test_version
+ return max_version.get_string()
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 5a14fbe..6e6ada8 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -48,11 +48,7 @@
# TODO(jlanoux) add support of wait_until PINGABLE/SSHABLE
- if 'name' in kwargs:
- name = kwargs.pop('name')
- else:
- name = data_utils.rand_name(__name__ + "-instance")
-
+ name = kwargs.pop('name', data_utils.rand_name(__name__ + "-instance"))
flavor = kwargs.pop('flavor', CONF.compute.flavor_ref)
image_id = kwargs.pop('image_id', CONF.compute.image_ref)
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index a33732e..5d15988 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -61,7 +61,7 @@
def create_user_role(self, role_name):
if not self._check_role_exists(role_name):
- self.roles_client.create_role(role_name)
+ self.roles_client.create_role(name=role_name)
def assign_user_role(self, user, project, role_name):
role = self._check_role_exists(role_name)
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 5bbc93c..0af07f0 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -285,24 +285,24 @@
try:
net_client.delete_router(router_id)
except lib_exc.NotFound:
- LOG.warn('router with name: %s not found for delete' %
- router_name)
+ LOG.warning('router with name: %s not found for delete' %
+ router_name)
def _clear_isolated_subnet(self, subnet_id, subnet_name):
client = self.subnets_admin_client
try:
client.delete_subnet(subnet_id)
except lib_exc.NotFound:
- LOG.warn('subnet with name: %s not found for delete' %
- subnet_name)
+ LOG.warning('subnet with name: %s not found for delete' %
+ subnet_name)
def _clear_isolated_network(self, network_id, network_name):
net_client = self.networks_admin_client
try:
net_client.delete_network(network_id)
except lib_exc.NotFound:
- LOG.warn('network with name: %s not found for delete' %
- network_name)
+ LOG.warning('network with name: %s not found for delete' %
+ network_name)
def _cleanup_default_secgroup(self, tenant):
nsg_client = self.security_groups_admin_client
@@ -313,8 +313,8 @@
try:
nsg_client.delete_security_group(secgroup['id'])
except lib_exc.NotFound:
- LOG.warn('Security group %s, id %s not found for clean-up' %
- (secgroup['name'], secgroup['id']))
+ LOG.warning('Security group %s, id %s not found for clean-up' %
+ (secgroup['name'], secgroup['id']))
def _clear_isolated_net_resources(self):
net_client = self.network_admin_client
@@ -333,8 +333,8 @@
net_client.remove_router_interface_with_subnet_id(
creds.router['id'], creds.subnet['id'])
except lib_exc.NotFound:
- LOG.warn('router with name: %s not found for delete' %
- creds.router['name'])
+ LOG.warning('router with name: %s not found for delete' %
+ creds.router['name'])
self._clear_isolated_router(creds.router['id'],
creds.router['name'])
if (not self.network_resources or
@@ -354,15 +354,15 @@
try:
self.creds_client.delete_user(creds.user_id)
except lib_exc.NotFound:
- LOG.warn("user with name: %s not found for delete" %
- creds.username)
+ LOG.warning("user with name: %s not found for delete" %
+ creds.username)
try:
if CONF.service_available.neutron:
self._cleanup_default_secgroup(creds.tenant_id)
self.creds_client.delete_project(creds.tenant_id)
except lib_exc.NotFound:
- LOG.warn("tenant with name: %s not found for delete" %
- creds.tenant_name)
+ LOG.warning("tenant with name: %s not found for delete" %
+ creds.tenant_name)
self._creds = {}
def is_multi_user(self):
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index 56cd331..3fc1365 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -49,13 +49,13 @@
name, networks))
if caller:
msg = '(%s) %s' % (caller, msg)
- LOG.warn(msg)
+ LOG.warning(msg)
raise exceptions.InvalidTestResource(type='network', name=name)
else:
msg = "Network with name: %s not found" % name
if caller:
msg = '(%s) %s' % (caller, msg)
- LOG.warn(msg)
+ LOG.warning(msg)
raise exceptions.InvalidTestResource(type='network', name=name)
# To be consistent between neutron and nova network always use name even
# if label is used in the api response. If neither is present than then
@@ -65,7 +65,7 @@
msg = "Network found from list doesn't contain a valid name or label"
if caller:
msg = '(%s) %s' % (caller, msg)
- LOG.warn(msg)
+ LOG.warning(msg)
raise exceptions.InvalidTestResource(type='network', name=name)
network['name'] = name
return network
@@ -122,6 +122,6 @@
if 'id' in network.keys():
params.update({"networks": [{'uuid': network['id']}]})
else:
- LOG.warn('The provided network dict: %s was invalid and did not '
- ' contain an id' % network)
+ LOG.warning('The provided network dict: %s was invalid and did '
+ 'not contain an id' % network)
return params
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index f526299..9457a60 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -24,7 +24,7 @@
def create_ssh_security_group(os, add_rule=False):
security_groups_client = os.compute_security_groups_client
- security_group_rules_client = os.security_group_rules_client
+ security_group_rules_client = os.compute_security_group_rules_client
sg_name = data_utils.rand_name('securitygroup-')
sg_description = data_utils.rand_name('description-')
security_group = security_groups_client.create_security_group(
@@ -73,8 +73,8 @@
try:
keypair_client.delete_keypair(keypair_name)
except lib_exc.NotFound:
- LOG.warn("Keypair %s is not found when attempting to delete"
- % keypair_name)
+ LOG.warning("Keypair %s is not found when attempting to delete"
+ % keypair_name)
except Exception as exc:
LOG.exception('Exception raised while deleting key %s'
% keypair_name)
@@ -87,8 +87,8 @@
security_group_client.delete_security_group(sec_id)
security_group_client.wait_for_resource_deletion(sec_id)
except lib_exc.NotFound:
- LOG.warn("Security group %s is not found when attempting to "
- " delete" % sec_id)
+ LOG.warning("Security group %s is not found when attempting "
+ "to delete" % sec_id)
except lib_exc.Conflict as exc:
LOG.exception('Conflict while deleting security '
'group %s VM might not be deleted ' % sec_id)
@@ -105,8 +105,8 @@
try:
floating_client.delete_floating_ip(fip_id)
except lib_exc.NotFound:
- LOG.warn('Floating ip %s not found while attempting to delete'
- % fip_id)
+ LOG.warning('Floating ip %s not found while attempting to '
+ 'delete' % fip_id)
except Exception as exc:
LOG.exception('Exception raised while deleting ip %s '
% fip_id)
diff --git a/tempest/config.py b/tempest/config.py
index 8f2ca4b..92123b9 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -737,7 +737,7 @@
deprecated_for_removal=True),
cfg.ListOpt('backend_names',
default=['BACKEND_1', 'BACKEND_2'],
- help='A list of backend names seperated by comma .'
+ help='A list of backend names separated by comma. '
'The backend name must be declared in cinder.conf',
deprecated_opts=[cfg.DeprecatedOpt('BACKEND_1',
group='volume'),
@@ -785,9 +785,10 @@
default=True,
help="Is the v2 volume API enabled"),
cfg.BoolOpt('bootable',
- default=False,
+ default=True,
help='Update bootable status of a volume '
- 'Not implemented on icehouse ')
+ 'Not implemented on icehouse ',
+ deprecated_for_removal=True)
]
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 1d725af..931737d 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -181,6 +181,11 @@
"be of format MajorNum.MinorNum or string 'latest'.")
+class JSONSchemaNotFound(TempestException):
+ message = ("JSON Schema for %(version)s is not found in \n"
+ " %(schema_versions_info)s")
+
+
class CommandFailed(Exception):
def __init__(self, returncode, cmd, output, stderr):
super(CommandFailed, self).__init__()
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 8a00c65..bb4e521 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -49,16 +49,17 @@
cls.flavors_client = cls.manager.flavors_client
cls.compute_floating_ips_client = (
cls.manager.compute_floating_ips_client)
- # Glance image client v1
- cls.image_client = cls.manager.image_client
+ if CONF.service_available.glance:
+ # Glance image client v1
+ cls.image_client = cls.manager.image_client
# Compute image client
- cls.images_client = cls.manager.images_client
+ cls.compute_images_client = cls.manager.compute_images_client
cls.keypairs_client = cls.manager.keypairs_client
# Nova security groups client
cls.compute_security_groups_client = (
cls.manager.compute_security_groups_client)
- cls.security_group_rules_client = (
- cls.manager.security_group_rules_client)
+ cls.compute_security_group_rules_client = (
+ cls.manager.compute_security_group_rules_client)
cls.servers_client = cls.manager.servers_client
cls.interface_client = cls.manager.interfaces_client
# Neutron network client
@@ -260,9 +261,13 @@
imageRef=None, volume_type=None, wait_on_delete=True):
if name is None:
name = data_utils.rand_name(self.__class__.__name__)
- volume = self.volumes_client.create_volume(
- size=size, display_name=name, snapshot_id=snapshot_id,
- imageRef=imageRef, volume_type=volume_type)['volume']
+ kwargs = {'display_name': name,
+ 'snapshot_id': snapshot_id,
+ 'imageRef': imageRef,
+ 'volume_type': volume_type}
+ if size is not None:
+ kwargs.update({'size': size})
+ volume = self.volumes_client.create_volume(**kwargs)['volume']
if wait_on_delete:
self.addCleanup(self.volumes_client.wait_for_resource_deletion,
@@ -289,7 +294,7 @@
def _create_loginable_secgroup_rule(self, secgroup_id=None):
_client = self.compute_security_groups_client
- _client_rules = self.security_group_rules_client
+ _client_rules = self.compute_security_group_rules_client
if secgroup_id is None:
sgs = _client.list_security_groups()['security_groups']
for sg in sgs:
@@ -344,17 +349,13 @@
return secgroup
- def get_remote_client(self, server_or_ip, username=None, private_key=None,
- log_console_of_servers=None):
+ def get_remote_client(self, server_or_ip, username=None, private_key=None):
"""Get a SSH client to a remote server
@param server_or_ip a server object as returned by Tempest compute
client or an IP address to connect to
@param username name of the Linux account on the remote server
@param private_key the SSH private key to use
- @param log_console_of_servers a list of server objects. Each server
- in the list will have its console printed in the logs in case the
- SSH connection failed to be established
@return a RemoteClient object
"""
if isinstance(server_or_ip, six.string_types):
@@ -391,10 +392,7 @@
if caller:
message = '(%s) %s' % (caller, message)
LOG.exception(message)
- # If we don't explicitly set for which servers we want to
- # log the console output then all the servers will be logged.
- # See the definition of _log_console_output()
- self._log_console_output(log_console_of_servers)
+ self._log_console_output()
raise
return linux_client
@@ -471,7 +469,7 @@
# Glance client
_image_client = self.image_client
# Compute client
- _images_client = self.images_client
+ _images_client = self.compute_images_client
if name is None:
name = data_utils.rand_name('scenario-snapshot')
LOG.debug("Creating a snapshot image for server: %s", server['name'])
@@ -729,7 +727,7 @@
def _list_agents(self, *args, **kwargs):
"""List agents using admin creds """
- agents_list = self.admin_manager.network_client.list_agents(
+ agents_list = self.admin_manager.network_agents_client.list_agents(
*args, **kwargs)
return agents_list['agents']
@@ -932,8 +930,8 @@
try:
source.ping_host(dest, nic=nic)
except lib_exc.SSHExecCommandFailed:
- LOG.warn('Failed to ping IP: %s via a ssh connection from: %s.'
- % (dest, source.ssh_client.host))
+ LOG.warning('Failed to ping IP: %s via a ssh connection '
+ 'from: %s.' % (dest, source.ssh_client.host))
return not should_succeed
return should_succeed
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index 9415629..93b32f7 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -123,23 +123,9 @@
# the same size as our flavor definition.
eph_size = self.get_flavor_ephemeral_size()
if eph_size:
- preserve_ephemeral = True
-
self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
# Create the test file
- timestamp = self.create_timestamp(
+ self.create_timestamp(
floating_ip, private_key=self.keypair['private_key'])
- else:
- preserve_ephemeral = False
- # Rebuild and preserve the ephemeral partition if it exists
- self.rebuild_instance(preserve_ephemeral)
- self.verify_connectivity()
-
- # Check that we maintained our data
- if eph_size:
- self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
- timestamp2 = self.get_timestamp(
- floating_ip, private_key=self.keypair['private_key'])
- self.assertEqual(timestamp, timestamp2)
self.terminate_instance()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 44942b0..b8bec16 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -683,9 +683,9 @@
list_hosts = (self.admin_manager.network_client.
list_l3_agents_hosting_router)
- schedule_router = (self.admin_manager.network_client.
+ schedule_router = (self.admin_manager.network_agents_client.
add_router_to_l3_agent)
- unschedule_router = (self.admin_manager.network_client.
+ unschedule_router = (self.admin_manager.network_agents_client.
remove_router_from_l3_agent)
agent_list = set(a["id"] for a in
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index 7e0e41c..f21ff4f 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -31,6 +31,14 @@
credentials = ['primary', 'admin']
@classmethod
+ def skip_checks(cls):
+ super(TestServerMultinode, cls).skip_checks()
+
+ if CONF.compute.min_compute_nodes < 2:
+ raise cls.skipException(
+ "Less than 2 compute nodes, skipping multinode tests.")
+
+ @classmethod
def setup_clients(cls):
super(TestServerMultinode, cls).setup_clients()
# Use admin client by default
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index fa7c0c9..3cbb3bc 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -40,11 +40,11 @@
self.non_ssh_image_pattern = \
CONF.input_scenario.non_ssh_image_regex
# Setup clients
- self.images_client = os.images_client
+ self.compute_images_client = os.compute_images_client
self.flavors_client = os.flavors_client
def ssh_user(self, image_id):
- _image = self.images_client.show_image(image_id)['image']
+ _image = self.compute_images_client.show_image(image_id)['image']
for regex, user in self.ssh_users:
# First match wins
if re.match(regex, _image['name']) is not None:
@@ -57,14 +57,14 @@
string=str(image['name']))
def is_sshable_image(self, image_id):
- _image = self.images_client.show_image(image_id)['image']
+ _image = self.compute_images_client.show_image(image_id)['image']
return self._is_sshable_image(_image)
def _is_flavor_enough(self, flavor, image):
return image['minDisk'] <= flavor['disk']
def is_flavor_enough(self, flavor_id, image_id):
- _image = self.images_client.show_image(image_id)['image']
+ _image = self.compute_images_client.show_image(image_id)['image']
_flavor = self.flavors_client.show_flavor(flavor_id)['flavor']
return self._is_flavor_enough(_flavor, _image)
@@ -108,7 +108,7 @@
identity_version=CONF.identity.auth_version,
network_resources=network_resources)
os = clients.Manager(self.cred_provider.get_primary_creds())
- self.images_client = os.images_client
+ self.compute_images_client = os.compute_images_client
self.flavors_client = os.flavors_client
self.image_pattern = CONF.input_scenario.image_regex
self.flavor_pattern = CONF.input_scenario.flavor_regex
@@ -128,7 +128,7 @@
return []
if not hasattr(self, '_scenario_images'):
try:
- images = self.images_client.list_images()['images']
+ images = self.compute_images_client.list_images()['images']
self._scenario_images = [
(self._normalize_name(i['name']), dict(image_ref=i['id']))
for i in images if re.search(self.image_pattern,
diff --git a/tempest/services/compute/json/base.py b/tempest/services/compute/json/base.py
index 02e9f8b..40d3056 100644
--- a/tempest/services/compute/json/base.py
+++ b/tempest/services/compute/json/base.py
@@ -12,10 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common import service_client
+from tempest_lib.common import rest_client
+
+from tempest.common import api_version_request
+from tempest import exceptions
-class BaseComputeClient(service_client.ServiceClient):
+class BaseComputeClient(rest_client.RestClient):
api_microversion = None
def get_headers(self):
@@ -23,3 +26,39 @@
if self.api_microversion:
headers['X-OpenStack-Nova-API-Version'] = self.api_microversion
return headers
+
+ def set_api_microversion(self, microversion):
+ self.api_microversion = microversion
+
+ def get_schema(self, schema_versions_info):
+ """Get JSON schema
+
+ This method provides the matching schema for requested
+ microversion (self.api_microversion).
+ :param schema_versions_info: List of dict which provides schema
+ information with range of valid versions.
+ Example -
+ schema_versions_info = [
+ {'min': None, 'max': '2.1', 'schema': schemav21},
+ {'min': '2.2', 'max': '2.9', 'schema': schemav22},
+ {'min': '2.10', 'max': None, 'schema': schemav210}]
+ """
+ schema = None
+ version = api_version_request.APIVersionRequest(self.api_microversion)
+ for items in schema_versions_info:
+ min_version = api_version_request.APIVersionRequest(items['min'])
+ max_version = api_version_request.APIVersionRequest(items['max'])
+ # This is case where self.api_microversion is None, which means
+ # request without microversion So select base v2.1 schema.
+ if version.is_null() and items['min'] is None:
+ schema = items['schema']
+ break
+ # else select appropriate schema as per self.api_microversion
+ elif version.matches(min_version, max_version):
+ schema = items['schema']
+ break
+ if schema is None:
+ raise exceptions.JSONSchemaNotFound(
+ version=version.get_string(),
+ schema_versions_info=schema_versions_info)
+ return schema
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index 54596be..ff6c838 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -71,12 +71,17 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def enable_disable_user(self, user_id, enabled):
- """Enables or disables a user."""
- put_body = {
- 'enabled': enabled
- }
- put_body = json.dumps({'user': put_body})
+ def enable_disable_user(self, user_id, **kwargs):
+ """Enables or disables a user.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v2-ext.html#enableUser
+ """
+ # NOTE: The URL (users/<id>/enabled) is different from the api-site
+ # one (users/<id>/OS-KSADM/enabled) , but they are the same API
+ # because of the fact that in keystone/contrib/admin_crud/core.py
+ # both api use same action='set_user_enabled'
+ put_body = json.dumps({'user': kwargs})
resp, body = self.put('users/%s/enabled' % user_id, put_body)
self.expected_success(200, resp.status)
body = json.loads(body)
@@ -159,25 +164,28 @@
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def update_user_password(self, user_id, new_pass):
+ def update_user_password(self, user_id, **kwargs):
"""Update User Password."""
- put_body = {
- 'password': new_pass,
- 'id': user_id
- }
- put_body = json.dumps({'user': put_body})
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524147
+ put_body = json.dumps({'user': kwargs})
resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
self.expected_success(200, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def update_user_own_password(self, user_id, new_pass, old_pass):
+ def update_user_own_password(self, user_id, **kwargs):
"""User updates own password"""
- patch_body = {
- "password": new_pass,
- "original_password": old_pass
- }
- patch_body = json.dumps({'user': patch_body})
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524153
+ # NOTE: This API is used for updating user password by itself.
+ # Ref: http://lists.openstack.org/pipermail/openstack-dev/2015-December
+ # /081803.html
+ patch_body = json.dumps({'user': kwargs})
resp, body = self.patch('OS-KSCRUD/users/%s' % user_id, patch_body)
self.expected_success(200, resp.status)
body = json.loads(body)
diff --git a/tempest/services/identity/v2/json/roles_client.py b/tempest/services/identity/v2/json/roles_client.py
index de8f9cb..ef6dfe9 100644
--- a/tempest/services/identity/v2/json/roles_client.py
+++ b/tempest/services/identity/v2/json/roles_client.py
@@ -18,12 +18,13 @@
class RolesClient(service_client.ServiceClient):
api_version = "v2.0"
- def create_role(self, name):
- """Create a role."""
- post_body = {
- 'name': name,
- }
- post_body = json.dumps({'role': post_body})
+ def create_role(self, **kwargs):
+ """Create a role.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v2-ext.html#createRole
+ """
+ post_body = json.dumps({'role': kwargs})
resp, body = self.post('OS-KSADM/roles', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 972db99..ab8ba2a 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -180,12 +180,13 @@
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def create_role(self, name):
- """Create a Role."""
- post_body = {
- 'name': name
- }
- post_body = json.dumps({'role': post_body})
+ def create_role(self, **kwargs):
+ """Create a Role.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#createRole
+ """
+ post_body = json.dumps({'role': kwargs})
resp, body = self.post('roles', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
@@ -205,12 +206,13 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def update_role(self, name, role_id):
- """Create a Role."""
- post_body = {
- 'name': name
- }
- post_body = json.dumps({'role': post_body})
+ def update_role(self, role_id, **kwargs):
+ """Update a Role.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#updateRole
+ """
+ post_body = json.dumps({'role': kwargs})
resp, body = self.patch('roles/%s' % str(role_id), post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
diff --git a/tempest/services/identity/v3/json/policy_client.py b/tempest/services/identity/v3/json/policies_client.py
similarity index 97%
rename from tempest/services/identity/v3/json/policy_client.py
rename to tempest/services/identity/v3/json/policies_client.py
index 7927ed5..639ed6d 100644
--- a/tempest/services/identity/v3/json/policy_client.py
+++ b/tempest/services/identity/v3/json/policies_client.py
@@ -22,7 +22,7 @@
from tempest.common import service_client
-class PolicyClient(service_client.ServiceClient):
+class PoliciesClient(service_client.ServiceClient):
api_version = "v3"
def create_policy(self, **kwargs):
diff --git a/tempest/services/identity/v3/json/region_client.py b/tempest/services/identity/v3/json/regions_client.py
similarity index 98%
rename from tempest/services/identity/v3/json/region_client.py
rename to tempest/services/identity/v3/json/regions_client.py
index 3595391..bc4b7a1 100644
--- a/tempest/services/identity/v3/json/region_client.py
+++ b/tempest/services/identity/v3/json/regions_client.py
@@ -23,7 +23,7 @@
from tempest.common import service_client
-class RegionClient(service_client.ServiceClient):
+class RegionsClient(service_client.ServiceClient):
api_version = "v3"
def create_region(self, region_id=None, **kwargs):
diff --git a/tempest/services/image/v1/json/images_client.py b/tempest/services/image/v1/json/images_client.py
index 3406db8..5b6a394 100644
--- a/tempest/services/image/v1/json/images_client.py
+++ b/tempest/services/image/v1/json/images_client.py
@@ -147,50 +147,29 @@
self._http = self._get_http()
return self._http
- def create_image(self, name, container_format, disk_format, **kwargs):
- params = {
- "name": name,
- "container_format": container_format,
- "disk_format": disk_format,
- }
-
+ def create_image(self, **kwargs):
headers = {}
+ data = kwargs.pop('data', None)
+ headers.update(self._image_meta_to_headers(kwargs))
- for option in ['is_public', 'location', 'properties',
- 'copy_from', 'min_ram']:
- if option in kwargs:
- params[option] = kwargs.get(option)
-
- headers.update(self._image_meta_to_headers(params))
-
- if 'data' in kwargs:
- return self._create_with_data(headers, kwargs.get('data'))
+ if data is not None:
+ return self._create_with_data(headers, data)
resp, body = self.post('v1/images', None, headers)
self.expected_success(201, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def update_image(self, image_id, name=None, container_format=None,
- data=None, properties=None):
- params = {}
+ def update_image(self, image_id, **kwargs):
headers = {}
- if name is not None:
- params['name'] = name
-
- if container_format is not None:
- params['container_format'] = container_format
-
- if properties is not None:
- params['properties'] = properties
-
- headers.update(self._image_meta_to_headers(params))
+ data = kwargs.pop('data', None)
+ headers.update(self._image_meta_to_headers(kwargs))
if data is not None:
return self._update_with_data(image_id, headers, data)
url = 'v1/images/%s' % image_id
- resp, body = self.put(url, data, headers)
+ resp, body = self.put(url, None, headers)
self.expected_success(200, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/network/json/agents_client.py b/tempest/services/network/json/agents_client.py
new file mode 100644
index 0000000..07f93b2
--- /dev/null
+++ b/tempest/services/network/json/agents_client.py
@@ -0,0 +1,68 @@
+# Copyright 2015 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.
+
+from tempest.services.network.json import base
+
+
+class AgentsClient(base.BaseNetworkClient):
+
+ def update_agent(self, agent_id, **kwargs):
+ """Update agent."""
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526673
+ uri = '/agents/%s' % agent_id
+ return self.update_resource(uri, kwargs)
+
+ def show_agent(self, agent_id, **fields):
+ uri = '/agents/%s' % agent_id
+ return self.show_resource(uri, **fields)
+
+ def list_agents(self, **filters):
+ uri = '/agents'
+ return self.list_resources(uri, **filters)
+
+ def list_routers_on_l3_agent(self, agent_id):
+ uri = '/agents/%s/l3-routers' % agent_id
+ return self.list_resources(uri)
+
+ def add_router_to_l3_agent(self, agent_id, **kwargs):
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526670
+ uri = '/agents/%s/l3-routers' % agent_id
+ return self.create_resource(uri, kwargs)
+
+ def remove_router_from_l3_agent(self, agent_id, router_id):
+ uri = '/agents/%s/l3-routers/%s' % (agent_id, router_id)
+ return self.delete_resource(uri)
+
+ def list_networks_hosted_by_one_dhcp_agent(self, agent_id):
+ uri = '/agents/%s/dhcp-networks' % agent_id
+ return self.list_resources(uri)
+
+ def remove_network_from_dhcp_agent(self, agent_id, network_id):
+ uri = '/agents/%s/dhcp-networks/%s' % (agent_id,
+ network_id)
+ return self.delete_resource(uri)
+
+ def add_dhcp_agent_to_network(self, agent_id, **kwargs):
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526212
+ uri = '/agents/%s/dhcp-networks' % agent_id
+ return self.create_resource(uri, kwargs)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 24a95e0..e8e21d2 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -229,60 +229,14 @@
uri = '/ports?device_id=%s' % uuid
return self.list_resources(uri)
- def update_agent(self, agent_id, **kwargs):
- """Update agent
-
- :param agent_info: Agent update information.
- E.g {"admin_state_up": True}
- """
- # TODO(piyush): Current api-site doesn't contain this API description.
- # After fixing the api-site, we need to fix here also for putting the
- # link to api-site.
- # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526673
- uri = '/agents/%s' % agent_id
- return self.update_resource(uri, kwargs)
-
- def show_agent(self, agent_id, **fields):
- uri = '/agents/%s' % agent_id
- return self.show_resource(uri, **fields)
-
- def list_agents(self, **filters):
- uri = '/agents'
- return self.list_resources(uri, **filters)
-
- def list_routers_on_l3_agent(self, agent_id):
- uri = '/agents/%s/l3-routers' % agent_id
- return self.list_resources(uri)
-
def list_l3_agents_hosting_router(self, router_id):
uri = '/routers/%s/l3-agents' % router_id
return self.list_resources(uri)
- def add_router_to_l3_agent(self, agent_id, **kwargs):
- # TODO(piyush): Current api-site doesn't contain this API description.
- # After fixing the api-site, we need to fix here also for putting the
- # link to api-site.
- # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526670
- uri = '/agents/%s/l3-routers' % agent_id
- return self.create_resource(uri, kwargs)
-
- def remove_router_from_l3_agent(self, agent_id, router_id):
- uri = '/agents/%s/l3-routers/%s' % (agent_id, router_id)
- return self.delete_resource(uri)
-
def list_dhcp_agent_hosting_network(self, network_id):
uri = '/networks/%s/dhcp-agents' % network_id
return self.list_resources(uri)
- def list_networks_hosted_by_one_dhcp_agent(self, agent_id):
- uri = '/agents/%s/dhcp-networks' % agent_id
- return self.list_resources(uri)
-
- def remove_network_from_dhcp_agent(self, agent_id, network_id):
- uri = '/agents/%s/dhcp-networks/%s' % (agent_id,
- network_id)
- return self.delete_resource(uri)
-
def update_extra_routes(self, router_id, **kwargs):
"""Update Extra routes.
@@ -301,33 +255,3 @@
}
}
return self.update_resource(uri, put_body)
-
- def add_dhcp_agent_to_network(self, agent_id, **kwargs):
- # TODO(piyush): Current api-site doesn't contain this API description.
- # After fixing the api-site, we need to fix here also for putting the
- # link to api-site.
- # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526212
- uri = '/agents/%s/dhcp-networks' % agent_id
- return self.create_resource(uri, kwargs)
-
- def list_subnetpools(self, **filters):
- uri = '/subnetpools'
- return self.list_resources(uri, **filters)
-
- def create_subnetpools(self, **kwargs):
- uri = '/subnetpools'
- post_data = {'subnetpool': kwargs}
- return self.create_resource(uri, post_data)
-
- def show_subnetpools(self, subnetpool_id, **fields):
- uri = '/subnetpools/%s' % subnetpool_id
- return self.show_resource(uri, **fields)
-
- def update_subnetpools(self, subnetpool_id, **kwargs):
- uri = '/subnetpools/%s' % subnetpool_id
- post_data = {'subnetpool': kwargs}
- return self.update_resource(uri, post_data)
-
- def delete_subnetpools(self, subnetpool_id):
- uri = '/subnetpools/%s' % subnetpool_id
- return self.delete_resource(uri)
diff --git a/tempest/services/network/json/subnetpools_client.py b/tempest/services/network/json/subnetpools_client.py
new file mode 100644
index 0000000..f921bb0
--- /dev/null
+++ b/tempest/services/network/json/subnetpools_client.py
@@ -0,0 +1,40 @@
+# Copyright 2015 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.
+
+from tempest.services.network.json import base
+
+
+class SubnetpoolsClient(base.BaseNetworkClient):
+
+ def list_subnetpools(self, **filters):
+ uri = '/subnetpools'
+ return self.list_resources(uri, **filters)
+
+ def create_subnetpool(self, **kwargs):
+ uri = '/subnetpools'
+ post_data = {'subnetpool': kwargs}
+ return self.create_resource(uri, post_data)
+
+ def show_subnetpool(self, subnetpool_id, **fields):
+ uri = '/subnetpools/%s' % subnetpool_id
+ return self.show_resource(uri, **fields)
+
+ def update_subnetpool(self, subnetpool_id, **kwargs):
+ uri = '/subnetpools/%s' % subnetpool_id
+ post_data = {'subnetpool': kwargs}
+ return self.update_resource(uri, post_data)
+
+ def delete_subnetpool(self, subnetpool_id):
+ uri = '/subnetpools/%s' % subnetpool_id
+ return self.delete_resource(uri)
diff --git a/tempest/services/volume/base/base_snapshots_client.py b/tempest/services/volume/base/base_snapshots_client.py
index fac90e4..fb705e1 100644
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/services/volume/base/base_snapshots_client.py
@@ -165,18 +165,26 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
- def update_snapshot_metadata(self, snapshot_id, metadata):
+ def update_snapshot_metadata(self, snapshot_id, **kwargs):
"""Update metadata for the snapshot."""
- put_body = json.dumps({'metadata': metadata})
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1529063
+ put_body = json.dumps(kwargs)
url = "snapshots/%s/metadata" % str(snapshot_id)
resp, body = self.put(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
- def update_snapshot_metadata_item(self, snapshot_id, id, meta_item):
+ def update_snapshot_metadata_item(self, snapshot_id, id, **kwargs):
"""Update metadata item for the snapshot."""
- put_body = json.dumps({'meta': meta_item})
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1529064
+ put_body = json.dumps(kwargs)
url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
resp, body = self.put(url, put_body)
body = json.loads(body)
diff --git a/tempest/services/volume/base/base_volumes_client.py b/tempest/services/volume/base/base_volumes_client.py
index c7302e8..d4435bc 100644
--- a/tempest/services/volume/base/base_volumes_client.py
+++ b/tempest/services/volume/base/base_volumes_client.py
@@ -71,23 +71,15 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
- def create_volume(self, size=None, **kwargs):
+ def create_volume(self, **kwargs):
"""Creates a new Volume.
- size: Size of volume in GB.
- Following optional keyword arguments are accepted:
- display_name: Optional Volume Name(only for V1).
- name: Optional Volume Name(only for V2).
- metadata: A dictionary of values to be used as metadata.
- volume_type: Optional Name of volume_type for the volume
- snapshot_id: When specified the volume is created from this snapshot
- imageRef: When specified the volume is created from this image
+ Available params: see http://developer.openstack.org/
+ api-ref-blockstorage-v2.html#createVolume
"""
- if size is None:
- size = self.default_volume_size
- post_body = {'size': size}
- post_body.update(kwargs)
- post_body = json.dumps({'volume': post_body})
+ if 'size' not in kwargs:
+ kwargs['size'] = self.default_volume_size
+ post_body = json.dumps({'volume': kwargs})
resp, body = self.post('volumes', post_body)
body = json.loads(body)
self.expected_success(self.create_resp, resp.status)
@@ -107,35 +99,26 @@
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def upload_volume(self, volume_id, image_name, disk_format):
+ def upload_volume(self, volume_id, **kwargs):
"""Uploads a volume in Glance."""
- post_body = {
- 'image_name': image_name,
- 'disk_format': disk_format
- }
- post_body = json.dumps({'os-volume_upload_image': post_body})
+ post_body = json.dumps({'os-volume_upload_image': kwargs})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def attach_volume(self, volume_id, instance_uuid, mountpoint):
+ def attach_volume(self, volume_id, **kwargs):
"""Attaches a volume to a given instance on a given mountpoint."""
- post_body = {
- 'instance_uuid': instance_uuid,
- 'mountpoint': mountpoint,
- }
- post_body = json.dumps({'os-attach': post_body})
+ post_body = json.dumps({'os-attach': kwargs})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def set_bootable_volume(self, volume_id, bootable):
+ def set_bootable_volume(self, volume_id, **kwargs):
"""set a bootable flag for a volume - true or false."""
- post_body = {"bootable": bootable}
- post_body = json.dumps({'os-set_bootable': post_body})
+ post_body = json.dumps({'os-set_bootable': kwargs})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(200, resp.status)
@@ -143,8 +126,7 @@
def detach_volume(self, volume_id):
"""Detaches a volume from an instance."""
- post_body = {}
- post_body = json.dumps({'os-detach': post_body})
+ post_body = json.dumps({'os-detach': {}})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
@@ -152,8 +134,7 @@
def reserve_volume(self, volume_id):
"""Reserves a volume."""
- post_body = {}
- post_body = json.dumps({'os-reserve': post_body})
+ post_body = json.dumps({'os-reserve': {}})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
@@ -161,8 +142,7 @@
def unreserve_volume(self, volume_id):
"""Restore a reserved volume ."""
- post_body = {}
- post_body = json.dumps({'os-unreserve': post_body})
+ post_body = json.dumps({'os-unreserve': {}})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
@@ -184,20 +164,17 @@
"""Returns the primary type of resource this client works with."""
return 'volume'
- def extend_volume(self, volume_id, extend_size):
+ def extend_volume(self, volume_id, **kwargs):
"""Extend a volume."""
- post_body = {
- 'new_size': extend_size
- }
- post_body = json.dumps({'os-extend': post_body})
+ post_body = json.dumps({'os-extend': kwargs})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def reset_volume_status(self, volume_id, status):
+ def reset_volume_status(self, volume_id, **kwargs):
"""Reset the Specified Volume's Status."""
- post_body = json.dumps({'os-reset_status': {"status": status}})
+ post_body = json.dumps({'os-reset_status': kwargs})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
@@ -218,14 +195,9 @@
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def create_volume_transfer(self, vol_id, display_name=None):
+ def create_volume_transfer(self, **kwargs):
"""Create a volume transfer."""
- post_body = {
- 'volume_id': vol_id
- }
- if display_name:
- post_body['name'] = display_name
- post_body = json.dumps({'transfer': post_body})
+ post_body = json.dumps({'transfer': kwargs})
resp, body = self.post('os-volume-transfer', post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
@@ -239,7 +211,7 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
- def list_volume_transfers(self, params=None):
+ def list_volume_transfers(self, **params):
"""List all the volume transfers created."""
url = 'os-volume-transfer'
if params:
@@ -255,24 +227,18 @@
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def accept_volume_transfer(self, transfer_id, transfer_auth_key):
+ def accept_volume_transfer(self, transfer_id, **kwargs):
"""Accept a volume transfer."""
- post_body = {
- 'auth_key': transfer_auth_key,
- }
url = 'os-volume-transfer/%s/accept' % transfer_id
- post_body = json.dumps({'accept': post_body})
+ post_body = json.dumps({'accept': kwargs})
resp, body = self.post(url, post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def update_volume_readonly(self, volume_id, readonly):
+ def update_volume_readonly(self, volume_id, **kwargs):
"""Update the Specified Volume readonly."""
- post_body = {
- 'readonly': readonly
- }
- post_body = json.dumps({'os-update_readonly_flag': post_body})
+ post_body = json.dumps({'os-update_readonly_flag': kwargs})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
@@ -327,10 +293,8 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
- def retype_volume(self, volume_id, volume_type, **kwargs):
+ def retype_volume(self, volume_id, **kwargs):
"""Updates volume with new volume type."""
- post_body = {'new_type': volume_type}
- post_body.update(kwargs)
- post_body = json.dumps({'os-retype': post_body})
+ post_body = json.dumps({'os-retype': kwargs})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
self.expected_success(202, resp.status)
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index a550d71..a3e1ea3 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -106,7 +106,7 @@
if process['process'].is_alive():
try:
pid = process['process'].pid
- LOG.warn("Process %d hangs. Send SIGKILL." % pid)
+ LOG.warning("Process %d hangs. Send SIGKILL." % pid)
os.kill(pid, signal.SIGKILL)
except Exception:
pass
@@ -239,14 +239,13 @@
had_errors = True
sum_runs += process['statistic']['runs']
sum_fails += process['statistic']['fails']
- LOG.info(" Process %d (%s): Run %d actions (%d failed)" %
- (process['p_number'],
- process['action'],
- process['statistic']['runs'],
- process['statistic']['fails']))
- LOG.info("Summary:")
- LOG.info("Run %d actions (%d failed)" %
- (sum_runs, sum_fails))
+ print ("Process %d (%s): Run %d actions (%d failed)" % (
+ process['p_number'],
+ process['action'],
+ process['statistic']['runs'],
+ process['statistic']['fails']))
+ print ("Summary:")
+ print ("Run %d actions (%d failed)" % (sum_runs, sum_fails))
if not had_errors and CONF.stress.full_clean_stack:
LOG.info("cleaning up")
diff --git a/tempest/test.py b/tempest/test.py
index c4e93bc..615a6e2 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -226,6 +226,7 @@
# Resources required to validate a server using ssh
validation_resources = {}
network_resources = {}
+ services_microversion = {}
# NOTE(sdague): log_format is defined inline here instead of using the oslo
# default because going through the config path recouples config to the
@@ -375,8 +376,8 @@
cls.validation_resources = vresources.create_validation_resources(
cls.os, cls.validation_resources)
else:
- LOG.warn("Client manager not found, validation resources not"
- " created")
+ LOG.warning("Client manager not found, validation resources not"
+ " created")
@classmethod
def resource_cleanup(cls):
@@ -391,8 +392,8 @@
cls.validation_resources)
cls.validation_resources = {}
else:
- LOG.warn("Client manager not found, validation resources not"
- " deleted")
+ LOG.warning("Client manager not found, validation resources "
+ "not deleted")
def setUp(self):
super(BaseTestCase, self).setUp()
@@ -515,7 +516,8 @@
else:
raise exceptions.InvalidCredentials(
"Invalid credentials type %s" % credential_type)
- return clients.Manager(credentials=creds, service=cls._service)
+ return clients.Manager(credentials=creds, service=cls._service,
+ api_microversions=cls.services_microversion)
@classmethod
def clear_credentials(cls):
@@ -602,7 +604,8 @@
credentials.is_admin_available(
identity_version=cls.get_identity_version())):
admin_creds = cred_provider.get_admin_creds()
- admin_manager = clients.Manager(admin_creds)
+ admin_manager = clients.Manager(
+ admin_creds, api_microversions=cls.services_microversion)
networks_client = admin_manager.compute_networks_client
return fixed_network.get_tenant_network(
cred_provider, networks_client, CONF.compute.fixed_network_name)
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index 56bc96c..62409bf 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -78,8 +78,8 @@
mocked_function = self.fake_client.volumes.attach_volume
mocked_function.assert_called_once_with(
self.fake_object.volume['id'],
- self.fake_object.server['id'],
- self.fake_object['device'])
+ instance_uuid=self.fake_object.server['id'],
+ mountpoint=self.fake_object['device'])
class TestCreateResources(JavelinUnitTest):
diff --git a/tempest/tests/cmd/test_list_plugins.py b/tempest/tests/cmd/test_list_plugins.py
new file mode 100644
index 0000000..17ddb18
--- /dev/null
+++ b/tempest/tests/cmd/test_list_plugins.py
@@ -0,0 +1,24 @@
+# Copyright 2015 Hewlett-Packard Development Company, L.P.
+#
+# 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 subprocess
+
+from tempest.tests import base
+
+
+class TestTempestListPlugins(base.TestCase):
+ def test_run_list_plugins(self):
+ return_code = subprocess.call(
+ ['tempest', 'list-plugins'], stdout=subprocess.PIPE)
+ self.assertEqual(return_code, 0)
diff --git a/tempest/tests/common/test_api_version_utils.py b/tempest/tests/common/test_api_version_utils.py
index 33024b6..9f399a2 100644
--- a/tempest/tests/common/test_api_version_utils.py
+++ b/tempest/tests/common/test_api_version_utils.py
@@ -192,3 +192,30 @@
def test_cfg_version_min_greater_than_max(self):
self.assertRaises(exceptions.InvalidConfiguration,
self._test_version, '2.2', '2.7', '2.9', '2.7')
+
+
+class TestSelectRequestMicroversion(base.TestCase):
+
+ def _test_request_version(self, test_min_version,
+ cfg_min_version, expected_version):
+ selected_version = api_version_utils.select_request_microversion(
+ test_min_version, cfg_min_version)
+ self.assertEqual(expected_version, selected_version)
+
+ def test_cfg_min_version_greater(self):
+ self._test_request_version('2.1', '2.3', expected_version='2.3')
+
+ def test_class_min_version_greater(self):
+ self._test_request_version('2.5', '2.3', expected_version='2.5')
+
+ def test_cfg_min_version_none(self):
+ self._test_request_version('2.5', None, expected_version='2.5')
+
+ def test_class_min_version_none(self):
+ self._test_request_version(None, '2.3', expected_version='2.3')
+
+ def test_both_min_version_none(self):
+ self._test_request_version(None, None, expected_version=None)
+
+ def test_both_min_version_equal(self):
+ self._test_request_version('2.3', '2.3', expected_version='2.3')
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index daeb0c0..f248957 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -26,8 +26,8 @@
from tempest.services.identity.v3.json import endpoints_client
from tempest.services.identity.v3.json import identity_client as \
identity_v3_identity_client
-from tempest.services.identity.v3.json import policy_client
-from tempest.services.identity.v3.json import region_client
+from tempest.services.identity.v3.json import policies_client
+from tempest.services.identity.v3.json import regions_client
from tempest.services.identity.v3.json import services_client
from tempest.services.image.v1.json import images_client
from tempest.services.image.v2.json import images_client as images_v2_client
@@ -118,8 +118,8 @@
credentials_client.CredentialsClient,
endpoints_client.EndPointClient,
identity_v3_identity_client.IdentityV3Client,
- policy_client.PolicyClient,
- region_client.RegionClient,
+ policies_client.PoliciesClient,
+ regions_client.RegionsClient,
services_client.ServicesClient,
images_client.ImagesClient,
images_v2_client.ImagesClientV2
diff --git a/tempest/tests/services/compute/test_base_compute_client.py b/tempest/tests/services/compute/test_base_compute_client.py
index 13461e4..134fe39 100644
--- a/tempest/tests/services/compute/test_base_compute_client.py
+++ b/tempest/tests/services/compute/test_base_compute_client.py
@@ -16,6 +16,7 @@
import mock
from tempest_lib.common import rest_client
+from tempest import exceptions
from tempest.services.compute.json import base as base_compute_client
from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
@@ -70,3 +71,82 @@
'raw_request') as mock_get:
mock_get.side_effect = raw_request
self.client.get('fake_url')
+
+
+class DummyServiceClient1(base_compute_client.BaseComputeClient):
+ schema_versions_info = [
+ {'min': None, 'max': '2.1', 'schema': 'schemav21'},
+ {'min': '2.2', 'max': '2.9', 'schema': 'schemav22'},
+ {'min': '2.10', 'max': None, 'schema': 'schemav210'}]
+
+ def return_selected_schema(self):
+ return self.get_schema(self.schema_versions_info)
+
+
+class TestSchemaVersionsNone(base.BaseComputeServiceTest):
+ api_microversion = None
+ expected_schema = 'schemav21'
+
+ def setUp(self):
+ super(TestSchemaVersionsNone, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = DummyServiceClient1(fake_auth, 'compute', 'regionOne')
+ self.client.api_microversion = self.api_microversion
+
+ def test_schema(self):
+ self.assertEqual(self.expected_schema,
+ self.client.return_selected_schema())
+
+
+class TestSchemaVersionsV21(TestSchemaVersionsNone):
+ api_microversion = '2.1'
+ expected_schema = 'schemav21'
+
+
+class TestSchemaVersionsV22(TestSchemaVersionsNone):
+ api_microversion = '2.2'
+ expected_schema = 'schemav22'
+
+
+class TestSchemaVersionsV25(TestSchemaVersionsNone):
+ api_microversion = '2.5'
+ expected_schema = 'schemav22'
+
+
+class TestSchemaVersionsV29(TestSchemaVersionsNone):
+ api_microversion = '2.9'
+ expected_schema = 'schemav22'
+
+
+class TestSchemaVersionsV210(TestSchemaVersionsNone):
+ api_microversion = '2.10'
+ expected_schema = 'schemav210'
+
+
+class TestSchemaVersionsLatest(TestSchemaVersionsNone):
+ api_microversion = 'latest'
+ expected_schema = 'schemav210'
+
+
+class DummyServiceClient2(base_compute_client.BaseComputeClient):
+ schema_versions_info = [
+ {'min': None, 'max': '2.1', 'schema': 'schemav21'},
+ {'min': '2.2', 'max': '2.9', 'schema': 'schemav22'}]
+
+ def return_selected_schema(self):
+ return self.get_schema(self.schema_versions_info)
+
+
+class TestSchemaVersionsNotFound(base.BaseComputeServiceTest):
+ api_microversion = '2.10'
+ expected_schema = 'schemav210'
+
+ def setUp(self):
+ super(TestSchemaVersionsNotFound, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = DummyServiceClient2(fake_auth, 'compute', 'regionOne')
+ self.client.api_microversion = self.api_microversion
+
+ def test_schema(self):
+ self.assertRaises(exceptions.JSONSchemaNotFound,
+ self.client.return_selected_schema)
diff --git a/tempest/tests/services/compute/test_keypairs_client.py b/tempest/tests/services/compute/test_keypairs_client.py
index 8b1a9a8..03aee53 100644
--- a/tempest/tests/services/compute/test_keypairs_client.py
+++ b/tempest/tests/services/compute/test_keypairs_client.py
@@ -38,7 +38,7 @@
def _test_list_keypairs(self, bytes_body=False):
self.check_service_client_function(
self.client.list_keypairs,
- 'tempest.common.service_client.ServiceClient.get',
+ 'tempest_lib.common.rest_client.RestClient.get',
{"keypairs": []},
bytes_body)
@@ -60,7 +60,7 @@
self.check_service_client_function(
self.client.show_keypair,
- 'tempest.common.service_client.ServiceClient.get',
+ 'tempest_lib.common.rest_client.RestClient.get',
fake_keypair,
bytes_body,
keypair_name="test")
@@ -77,7 +77,7 @@
self.check_service_client_function(
self.client.create_keypair,
- 'tempest.common.service_client.ServiceClient.post',
+ 'tempest_lib.common.rest_client.RestClient.post',
fake_keypair,
bytes_body,
name="test")
@@ -91,5 +91,5 @@
def test_delete_keypair(self):
self.check_service_client_function(
self.client.delete_keypair,
- 'tempest.common.service_client.ServiceClient.delete',
+ 'tempest_lib.common.rest_client.RestClient.delete',
{}, status=202, keypair_name='test')
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index ce3eb7e..98b045a 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -140,7 +140,7 @@
self.fail('%s is not listed in the valid service tag list'
% service)
except KeyError:
- # NOTE(mtreinish): This condition is to test for a entry in
+ # NOTE(mtreinish): This condition is to test for an entry in
# the outer decorator list but not in the service_list dict.
# However, because we're looping over the service_list dict
# it's unlikely we'll trigger this. So manual review is still