Merge "create_router cannot take enable_snat=False"
diff --git a/HACKING.rst b/HACKING.rst
index e15e213..3799046 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -136,7 +136,7 @@
Tear-down is also split in a series of steps (teardown stages), which are
stacked for execution only if the corresponding setup stage had been
reached during the setup phase. Tear-down stages are:
-- `clear_isolated_creds` (defined in the base test class)
+- `clear_credentials` (defined in the base test class)
- `resource_cleanup`
Skipping Tests
@@ -206,9 +206,10 @@
-----------------------
Tempest by default runs its tests in parallel this creates the possibility for
interesting interactions between tests which can cause unexpected failures.
-Tenant isolation provides protection from most of the potential race conditions
-between tests outside the same class. But there are still a few of things to
-watch out for to try to avoid issues when running your tests in parallel.
+Dynamic credentials provides protection from most of the potential race
+conditions between tests outside the same class. But there are still a few of
+things to watch out for to try to avoid issues when running your tests in
+parallel.
- Resources outside of a tenant scope still have the potential to conflict. This
is a larger concern for the admin tests since most resources and actions that
diff --git a/README.rst b/README.rst
index 7108eaf..bf513bd 100644
--- a/README.rst
+++ b/README.rst
@@ -168,7 +168,7 @@
$> cd $TEMPEST_ROOT_DIR
$> oslo-config-generator --config-file \
- tools/config/config-generator.tempest.conf \
+ etc/config-generator.tempest.conf \
--output-file etc/tempest.conf
After that, open up the ``etc/tempest.conf`` file and edit the
diff --git a/doc/source/conf.py b/doc/source/conf.py
index f85899b..12d1d40 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -34,7 +34,7 @@
'oslo_config.sphinxconfiggen',
]
-config_generator_config_file = '../../tools/config/config-generator.tempest.conf'
+config_generator_config_file = '../../etc/config-generator.tempest.conf'
sample_config_basename = '_static/tempest'
todo_include_todos = True
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index ec430b7..f228040 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -63,38 +63,41 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Tempest currently also has 3 different internal methods for providing
-authentication to tests. Tenant isolation, locking test accounts, and
+authentication to tests. Dynamic credentials, locking test accounts, and
non-locking test accounts. Depending on which one is in use the configuration
of tempest is slightly different.
-Tenant Isolation
-""""""""""""""""
-Tenant isolation was originally create to enable running tempest in parallel.
+Dynamic Credentials
+"""""""""""""""""""
+Dynamic Credentials (formerly known as Tenant isolation) was originally created
+to enable running tempest in parallel.
For each test class it creates a unique set of user credentials to use for the
tests in the class. It can create up to 3 sets of username, password, and
tenant/project names for a primary user, an admin user, and an alternate user.
-To enable and use tenant isolation you only need to configure 2 things:
+To enable and use dynamic credentials you only need to configure 2 things:
#. A set of admin credentials with permissions to create users and
- tenants/projects. This is specified in the identity section with the
- admin_username, admin_tenant_name, and admin_password options
- #. To enable tenant_isolation in the auth section with the
- allow_tenant_isolation option.
+ tenants/projects. This is specified in the auth section with the
+ admin_username, admin_tenant_name, admin_domain_name and admin_password
+ options
+ #. To enable dynamic_creds in the auth section with the
+ use_dynamic_credentials option.
This is also the currently the default credential provider enabled by tempest,
due to it's common use and ease of configuration.
It is worth pointing out that depending on your cloud configuration you might
-need to assign a role to each of the users created Tempest's tenant isolation.
+need to assign a role to each of the users created by Tempest's dynamic
+credentials.
This can be set using the *tempest_roles* option. It takes in a list of role
-names each of which will be assigned to each of the users created by tenant
-isolation. This option will not have any effect when set and tempest is not
-configured to use tenant isolation.
+names each of which will be assigned to each of the users created by dynamic
+credentials. This option will not have any effect when set and tempest is not
+configured to use dynamic credentials.
Locking Test Accounts (aka accounts.yaml or accounts file)
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-For a long time using tenant isolation was the only method available if you
+For a long time using dynamic credentials was the only method available if you
wanted to enable parallel execution of tempest tests. However this was
insufficient for certain use cases because of the admin credentials requirement
to create the credential sets on demand. To get around that the accounts.yaml
@@ -102,7 +105,7 @@
using the list of credentials instead of creating them on demand. With locking
test accounts each test class will reserve a set of credentials from the
accounts.yaml before executing any of its tests so that each class is isolated
-like in tenant isolation.
+like with dynamic credentials.
To enable and use locking test accounts you need do a few things:
@@ -116,7 +119,7 @@
#. Provide tempest with the location of your accounts.yaml file with the
test_accounts_file option in the auth section
- #. Set allow_tenant_isolation = False in the auth group
+ #. Set use_dynamic_credentials = False in the auth group
It is worth pointing out that each set of credentials in the accounts.yaml
should have a unique tenant. This is required to provide proper isolation
@@ -126,6 +129,9 @@
Non-locking test accounts (aka credentials config options)
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+**Starting in the Liberty release this mechanism was deprecated and will be
+removed in a future release**
+
When Tempest was refactored to allow for locking test accounts, the original
non-tenant isolated case was converted to internally work similarly to the
accounts.yaml file. This mechanism was then called the non-locking test accounts
@@ -145,7 +151,7 @@
And in the auth section:
- #. allow_tenant_isolation = False
+ #. use_dynamic_credentials = False
#. comment out 'test_accounts_file' or keep it as empty
It only makes sense to use it if parallel execution isn't needed, since tempest
@@ -291,28 +297,28 @@
misconfiguration or a missing network in the accounts file.
-With Tenant Isolation
-"""""""""""""""""""""
-With tenant isolation enabled and using nova-network then nothing changes. Your
-only option for configuration is to either set a fixed network name or not.
+With Dynamic Credentials
+""""""""""""""""""""""""
+With dynamic credentials enabled and using nova-network then nothing changes.
+Your only option for configuration is to either set a fixed network name or not.
However, in most cases it shouldn't matter because nova-network should have no
problem booting a server with multiple networks. If this is not the case for
your cloud then using an accounts file is recommended because it provides the
-necessary flexibility to describe your configuration. Tenant isolation is not
+necessary flexibility to describe your configuration. Dynamic credentials is not
able to dynamically allocate things as necessary if neutron is not enabled.
-With neutron and tenant isolation enabled there should not be any additional
+With neutron and dynamic credentials enabled there should not be any additional
configuration necessary to enable Tempest to create servers with working
networking, assuming you have properly configured the network section to work
for your cloud. Tempest will dynamically create the neutron resources necessary
to enable using servers with that network. Also, just as with the accounts
-file, if you specify a fixed network name while using neutron and tenant
-isolation it will enable running tests which require a static network and it
+file, if you specify a fixed network name while using neutron and dynamic
+credentials it will enable running tests which require a static network and it
will additionally be used as a fallback for server creation. However, unlike
accounts.yaml this should never be triggered.
-However, there is an option *create_isolated_networks* to disable tenant
-isolation's automatic provisioning of network resources. If this option is
+However, there is an option *create_isolated_networks* to disable dynamic
+credentials's automatic provisioning of network resources. If this option is
used you will have to either rely on there only being a single/default network
available for the server creation, or use *fixed_network_name* to inform
Tempest which network to use.
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index f92f63e..a41038c 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -20,32 +20,26 @@
to tempest-lib. In that situation, file a bug, push a migration patch, etc. to
expedite providing the interface in a reliable manner.
-Plugin Class
-------------
+Plugin Cookiecutter
+-------------------
-To provide tempest with all the required information it needs to be able to run
-your plugin you need to create a plugin class which tempest will load and call
-to get information when it needs. To simplify creating this tempest provides an
-abstract class that should be used as the parent for your plugin. To use this
-you would do something like the following::
+In order to create the basic structure with base classes and test directories
+you can use the tempest-plugin-cookiecutter project::
- from tempest.test_discover import plugin
+ > cookiecutter https://git.openstack.org/openstack/tempest-plugin-cookiecutter
- class MyPlugin(plugin.TempestPlugin):
+ Cloning into 'tempest-plugin-cookiecutter'...
+ remote: Counting objects: 17, done.
+ remote: Compressing objects: 100% (13/13), done.
+ remote: Total 17 (delta 1), reused 14 (delta 1)
+ Unpacking objects: 100% (17/17), done.
+ Checking connectivity... done.
+ project (default is "sample")? foo
+ testclass (default is "SampleTempestPlugin")? FooTempestPlugin
-Then you need to ensure you locally define all of the methods in the abstract
-class, you can refer to the api doc below for a reference of what that entails.
-
-Also, note eventually this abstract class will likely live in tempest-lib, when
-that migration occurs a deprecation shim will be added to tempest so as to not
-break any existing plugins. But, when that occurs migrating to using tempest-lib
-as the source for the abstract class will be prudent.
-
-Abstract Plugin Class
-^^^^^^^^^^^^^^^^^^^^^
-
-.. autoclass:: tempest.test_discover.plugins.TempestPlugin
- :members:
+This would create a folder called ``foo_tempest_plugin/`` with all necessary
+basic classes. You only need to move/create your test in
+``foo_tempest_plugin/tests``.
Entry Point
-----------
@@ -61,9 +55,35 @@
tempest.test_plugins =
plugin_name = module.path:PluginClass
-Plugin Structure
-----------------
+Plugin Class
+============
+To provide tempest with all the required information it needs to be able to run
+your plugin you need to create a plugin class which tempest will load and call
+to get information when it needs. To simplify creating this tempest provides an
+abstract class that should be used as the parent for your plugin. To use this
+you would do something like the following::
+
+ from tempest.test_discover import plugins
+
+ class MyPlugin(plugins.TempestPlugin):
+
+Then you need to ensure you locally define all of the methods in the abstract
+class, you can refer to the api doc below for a reference of what that entails.
+
+Also, note eventually this abstract class will likely live in tempest-lib, when
+that migration occurs a deprecation shim will be added to tempest so as to not
+break any existing plugins. But, when that occurs migrating to using tempest-lib
+as the source for the abstract class will be prudent.
+
+Abstract Plugin Class
+---------------------
+
+.. autoclass:: tempest.test_discover.plugins.TempestPlugin
+ :members:
+
+Plugin Structure
+================
While there are no hard and fast rules for the structure a plugin, there are
basically no constraints on what the plugin looks like as long as the 2 steps
above are done. However, there are some recommended patterns to follow to make
@@ -92,7 +112,7 @@
being added in the plugin act and behave like the rest of tempest.
Dealing with configuration options
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+----------------------------------
Historically Tempest didn't provide external guarantees on its configuration
options. However, with the introduction of the plugin interface this is no
diff --git a/tools/config/config-generator.tempest.conf b/etc/config-generator.tempest.conf
similarity index 100%
rename from tools/config/config-generator.tempest.conf
rename to etc/config-generator.tempest.conf
diff --git a/requirements.txt b/requirements.txt
index b25b9d3..c0a9254 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-pbr<2.0,>=1.6
+pbr>=1.6
cliff>=1.14.0 # Apache-2.0
anyjson>=0.3.3
httplib2>=0.7.5
@@ -22,6 +22,6 @@
iso8601>=0.1.9
fixtures>=1.3.1
testscenarios>=0.4
-tempest-lib>=0.6.1
+tempest-lib>=0.10.0
PyYAML>=3.1.0
stevedore>=1.5.0 # Apache-2.0
diff --git a/setup.py b/setup.py
index d8080d0..782bb21 100644
--- a/setup.py
+++ b/setup.py
@@ -25,5 +25,5 @@
pass
setuptools.setup(
- setup_requires=['pbr>=1.3'],
+ setup_requires=['pbr>=1.8'],
pbr=True)
diff --git a/tempest/api/baremetal/admin/test_ports.py b/tempest/api/baremetal/admin/test_ports.py
index 5eaf641..180b848 100644
--- a/tempest/api/baremetal/admin/test_ports.py
+++ b/tempest/api/baremetal/admin/test_ports.py
@@ -11,7 +11,6 @@
# under the License.
import six
-from tempest_lib import decorators
from tempest_lib import exceptions as lib_exc
from tempest.api.baremetal.admin import base
@@ -60,7 +59,6 @@
_, body = self.client.show_port(uuid)
self._assertExpected(port, body)
- @decorators.skip_because(bug='1398350')
@test.idempotent_id('4a02c4b0-6573-42a4-a513-2e36ad485b62')
def test_create_port_with_extra(self):
node_id = self.node['uuid']
@@ -237,7 +235,6 @@
_, body = self.client.show_port(port['uuid'])
self.assertEqual(extra, body['extra'])
- @decorators.skip_because(bug='1398350')
@test.idempotent_id('5309e897-0799-4649-a982-0179b04c3876')
def test_update_port_mixed_ops(self):
node_id = self.node['uuid']
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 42a2984..085916e 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -221,7 +221,8 @@
# Verify flavor is not used by other user
self.assertRaises(lib_exc.BadRequest,
self.os.servers_client.create_server,
- 'test', self.image_ref, flavor['id'])
+ name='test', imageRef=self.image_ref,
+ flavorRef=flavor['id'])
@test.idempotent_id('b345b196-bfbd-4231-8ac1-6d7fe15ff3a3')
def test_list_public_flavor_with_other_user(self):
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 9d49124..12c471e 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -38,8 +38,6 @@
def resource_setup(cls):
super(LiveBlockMigrationTestJSON, cls).resource_setup()
- cls.created_server_ids = []
-
def _get_compute_hostnames(self):
body = self.admin_hosts_client.list_hosts()['hosts']
return [
@@ -55,10 +53,12 @@
def _get_host_for_server(self, server_id):
return self._get_server_details(server_id)[self._host_key]
- def _migrate_server_to(self, server_id, dest_host):
- bmflm = CONF.compute_feature_enabled.block_migration_for_live_migration
+ def _migrate_server_to(self, server_id, dest_host, volume_backed):
+ block_migration = (CONF.compute_feature_enabled.
+ block_migration_for_live_migration and
+ not volume_backed)
body = self.admin_servers_client.live_migrate_server(
- server_id, host=dest_host, block_migration=bmflm,
+ server_id, host=dest_host, block_migration=block_migration,
disk_over_commit=False)
return body
@@ -70,15 +70,10 @@
def _get_server_status(self, server_id):
return self._get_server_details(server_id)['status']
- def _get_an_active_server(self):
- for server_id in self.created_server_ids:
- if 'ACTIVE' == self._get_server_status(server_id):
- return server_id
- else:
- server = self.create_test_server(wait_until="ACTIVE")
- server_id = server['id']
- self.created_server_ids.append(server_id)
- return server_id
+ def _create_server(self, volume_backed=False):
+ server = self.create_test_server(wait_until="ACTIVE",
+ volume_backed=volume_backed)
+ return server['id']
def _volume_clean_up(self, server_id, volume_id):
body = self.volumes_client.show_volume(volume_id)['volume']
@@ -87,20 +82,22 @@
self.volumes_client.wait_for_volume_status(volume_id, 'available')
self.volumes_client.delete_volume(volume_id)
- def _test_live_block_migration(self, state='ACTIVE'):
- """Tests live block migration between two hosts.
+ def _test_live_migration(self, state='ACTIVE', volume_backed=False):
+ """Tests live migration between two hosts.
Requires CONF.compute_feature_enabled.live_migration to be True.
:param state: The vm_state the migrated server should be in before and
after the live migration. Supported values are 'ACTIVE'
and 'PAUSED'.
+ :param volume_backed: If the instance is volume backed or not. If
+ volume_backed, *block* migration is not used.
"""
- # Live block migrate an instance to another host
+ # Live migrate an instance to another host
if len(self._get_compute_hostnames()) < 2:
raise self.skipTest(
"Less than 2 compute nodes, skipping migration test.")
- server_id = self._get_an_active_server()
+ server_id = self._create_server(volume_backed=volume_backed)
actual_host = self._get_host_for_server(server_id)
target_host = self._get_host_other_than(actual_host)
@@ -109,7 +106,7 @@
waiters.wait_for_server_status(self.admin_servers_client,
server_id, state)
- self._migrate_server_to(server_id, target_host)
+ self._migrate_server_to(server_id, target_host, volume_backed)
waiters.wait_for_server_status(self.servers_client, server_id, state)
migration_list = (self.admin_migration_client.list_migrations()
['migrations'])
@@ -127,7 +124,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.live_migration,
'Live migration not available')
def test_live_block_migration(self):
- self._test_live_block_migration()
+ self._test_live_migration()
@test.idempotent_id('1e107f21-61b2-4988-8f22-b196e938ab88')
@testtools.skipUnless(CONF.compute_feature_enabled.live_migration,
@@ -139,7 +136,14 @@
'Live migration of paused instances is not '
'available.')
def test_live_block_migration_paused(self):
- self._test_live_block_migration(state='PAUSED')
+ self._test_live_migration(state='PAUSED')
+
+ @test.idempotent_id('5071cf17-3004-4257-ae61-73a84e28badd')
+ @testtools.skipUnless(CONF.compute_feature_enabled.live_migration,
+ 'Live migration not available')
+ @test.services('volume')
+ def test_volume_backed_live_migration(self):
+ self._test_live_migration(volume_backed=True)
@test.idempotent_id('e19c0cc6-6720-4ed8-be83-b6603ed5c812')
@testtools.skipIf(not CONF.compute_feature_enabled.live_migration or not
@@ -150,11 +154,10 @@
block_migrate_cinder_iscsi,
'Block Live migration not configured for iSCSI')
def test_iscsi_volume(self):
- # Live block migrate an instance to another host
if len(self._get_compute_hostnames()) < 2:
raise self.skipTest(
"Less than 2 compute nodes, skipping migration test.")
- server_id = self._get_an_active_server()
+ server_id = self._create_server()
actual_host = self._get_host_for_server(server_id)
target_host = self._get_host_other_than(actual_host)
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 1849f83..dfaa5d5 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -111,7 +111,8 @@
image_id = self.image_ref
network = self.get_tenant_network()
network_kwargs = fixed_network.set_networks_kwarg(network)
- test_server = self.client.create_server(name, image_id, flavor,
+ test_server = self.client.create_server(name=name, imageRef=image_id,
+ flavorRef=flavor,
**network_kwargs)['server']
self.addCleanup(self.client.delete_server, test_server['id'])
waiters.wait_for_server_status(self.client,
@@ -198,5 +199,5 @@
hints = {
'same_host': self.s1_id
}
- self.create_test_server(sched_hints=hints,
+ self.create_test_server(scheduler_hints=hints,
wait_until='ACTIVE')
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index 7333acb..e5c17ca 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -14,10 +14,14 @@
# under the License.
import datetime
-import time
from tempest.api.compute import base
from tempest import test
+from tempest_lib import exceptions as e
+
+# Time that waits for until returning valid response
+# TODO(takmatsu): Ideally this value would come from configuration.
+VALID_WAIT = 30
class TenantUsagesTestJSON(base.BaseV2ComputeAdminTest):
@@ -35,7 +39,6 @@
# Create a server in the demo tenant
cls.create_test_server(wait_until='ACTIVE')
- time.sleep(2)
now = datetime.datetime.now()
cls.start = cls._parse_strtime(now - datetime.timedelta(days=1))
@@ -46,17 +49,32 @@
# Returns formatted datetime
return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
+ def call_until_valid(self, func, duration, *args, **kwargs):
+ # Call until get valid response for "duration"
+ # because tenant usage doesn't become available immediately
+ # after create VM.
+ def is_valid():
+ try:
+ self.resp = func(*args, **kwargs)
+ return True
+ except e.InvalidHTTPResponseBody:
+ return False
+ test.call_until_true(is_valid, duration, 1)
+ return self.resp
+
@test.idempotent_id('062c8ae9-9912-4249-8b51-e38d664e926e')
def test_list_usage_all_tenants(self):
# Get usage for all tenants
- tenant_usage = self.adm_client.list_tenant_usages(
+ tenant_usage = self.call_until_valid(
+ self.adm_client.list_tenant_usages, VALID_WAIT,
start=self.start, end=self.end, detailed="1")['tenant_usages'][0]
self.assertEqual(len(tenant_usage), 8)
@test.idempotent_id('94135049-a4c5-4934-ad39-08fa7da4f22e')
def test_get_usage_tenant(self):
# Get usage for a specific tenant
- tenant_usage = self.adm_client.show_tenant_usage(
+ tenant_usage = self.call_until_valid(
+ self.adm_client.show_tenant_usage, VALID_WAIT,
self.tenant_id, start=self.start, end=self.end)['tenant_usage']
self.assertEqual(len(tenant_usage), 8)
@@ -64,7 +82,7 @@
@test.idempotent_id('9d00a412-b40e-4fd9-8eba-97b496316116')
def test_get_usage_tenant_with_non_admin_user(self):
# Get usage for a specific tenant with non admin user
- tenant_usage = self.client.show_tenant_usage(
+ tenant_usage = self.call_until_valid(
+ self.client.show_tenant_usage, VALID_WAIT,
self.tenant_id, start=self.start, end=self.end)['tenant_usage']
-
self.assertEqual(len(tenant_usage), 8)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 3952439..ec2192f 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -203,13 +203,17 @@
server_group_id)
@classmethod
- def create_test_server(cls, validatable=False, **kwargs):
+ def create_test_server(cls, validatable=False, volume_backed=False,
+ **kwargs):
"""Wrapper utility that returns a test server.
This wrapper utility calls the common create test server and
returns a test server. The purpose of this wrapper is to minimize
the impact on the code of the tests already using this
function.
+
+ :param validatable: Whether the server will be pingable or sshable.
+ :param volume_backed: Whether the instance is volume backed or not.
"""
tenant_network = cls.get_tenant_network()
body, servers = compute.create_test_server(
@@ -217,6 +221,7 @@
validatable,
validation_resources=cls.validation_resources,
tenant_network=tenant_network,
+ volume_backed=volume_backed,
**kwargs)
cls.servers.extend(servers)
@@ -241,8 +246,8 @@
name = data_utils.rand_name(cls.__name__ + "-Server-Group")
if policy is None:
policy = ['affinity']
- body = (cls.server_groups_client.create_server_group(name, policy)
- ['server_group'])
+ body = cls.server_groups_client.create_server_group(
+ name=name, policies=policy)['server_group']
cls.server_groups.append(body['id'])
return body
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index 78a0a93..0096fc2 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -14,13 +14,22 @@
# under the License.
from tempest.api.compute import base
+from tempest import config
from tempest import test
+CONF = config.CONF
+
class CertificatesV2TestJSON(base.BaseComputeTest):
_api_version = 2
+ @classmethod
+ def skip_checks(cls):
+ super(CertificatesV2TestJSON, cls).skip_checks()
+ if not CONF.compute_feature_enabled.nova_cert:
+ raise cls.skipException("Nova cert is not available")
+
@test.idempotent_id('c070a441-b08e-447e-a733-905909535b1b')
def test_create_root_certificate(self):
# create certificates
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 0324df2..dc62620 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -14,6 +14,7 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
+from tempest.common import waiters
from tempest import config
from tempest import test
@@ -48,3 +49,18 @@
name=snapshot_name,
wait_until='SAVING')
self.client.delete_image(image['id'])
+
+ @test.idempotent_id('aaacd1d0-55a2-4ce8-818a-b5439df8adc9')
+ def test_create_image_from_stopped_server(self):
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.servers_client.stop_server(server['id'])
+ waiters.wait_for_server_status(self.servers_client,
+ server['id'], 'SHUTOFF')
+ self.addCleanup(self.servers_client.delete_server, server['id'])
+ snapshot_name = data_utils.rand_name('test-snap')
+ image = self.create_image_from_server(server['id'],
+ name=snapshot_name,
+ wait_until='ACTIVE',
+ wait_for_server=False)
+ self.addCleanup(self.client.delete_image, image['id'])
+ self.assertEqual(snapshot_name, image['name'])
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 126d092..9197adf 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -71,22 +71,6 @@
'!@#$%^&*()', name=name, meta=meta)
@test.attr(type=['negative'])
- @test.idempotent_id('aaacd1d0-55a2-4ce8-818a-b5439df8adc9')
- def test_create_image_from_stopped_server(self):
- server = self.create_test_server(wait_until='ACTIVE')
- self.servers_client.stop_server(server['id'])
- waiters.wait_for_server_status(self.servers_client,
- server['id'], 'SHUTOFF')
- self.addCleanup(self.servers_client.delete_server, server['id'])
- snapshot_name = data_utils.rand_name('test-snap')
- image = self.create_image_from_server(server['id'],
- name=snapshot_name,
- wait_until='ACTIVE',
- wait_for_server=False)
- self.addCleanup(self.client.delete_image, image['id'])
- self.assertEqual(snapshot_name, image['name'])
-
- @test.attr(type=['negative'])
@test.idempotent_id('ec176029-73dc-4037-8d72-2e4ff60cf538')
def test_create_image_specify_uuid_35_characters_or_less(self):
# Return an error if Image ID passed is 35 characters or less
diff --git a/tempest/api/compute/limits/test_absolute_limits_negative.py b/tempest/api/compute/limits/test_absolute_limits_negative.py
index 5755f5b..73e852f 100644
--- a/tempest/api/compute/limits/test_absolute_limits_negative.py
+++ b/tempest/api/compute/limits/test_absolute_limits_negative.py
@@ -55,4 +55,4 @@
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised when out of quota
self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
- self.create_test_server, meta=meta_data)
+ self.create_test_server, metadata=meta_data)
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 530e422..24d503f 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -186,7 +186,7 @@
self.assertTrue(interface_count > 0)
self._check_interface(ifs[0])
network_id = ifs[0]['net_id']
- self.client.add_fixed_ip(server['id'], networkId=network_id)
+ self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
# Remove the fixed IP from server.
server_detail = self.os.servers_client.show_server(
server['id'])['server']
@@ -199,4 +199,4 @@
break
if fixed_ip is not None:
break
- self.client.remove_fixed_ip(server['id'], address=fixed_ip)
+ self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 419bfd7..902b72c 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import base64
-
import netaddr
import testtools
@@ -41,6 +39,8 @@
super(ServersTestJSON, cls).setup_clients()
cls.client = cls.servers_client
cls.network_client = cls.os.network_client
+ cls.networks_client = cls.os.networks_client
+ cls.subnets_client = cls.os.subnets_client
@classmethod
def resource_setup(cls):
@@ -50,18 +50,14 @@
cls.accessIPv4 = '1.1.1.1'
cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
cls.name = data_utils.rand_name('server')
- file_contents = 'This is a test file.'
- personality = [{'path': '/test.txt',
- 'contents': base64.b64encode(file_contents)}]
disk_config = cls.disk_config
cls.server_initial = cls.create_test_server(
validatable=True,
wait_until='ACTIVE',
name=cls.name,
- meta=cls.meta,
+ metadata=cls.meta,
accessIPv4=cls.accessIPv4,
accessIPv6=cls.accessIPv6,
- personality=personality,
disk_config=disk_config)
cls.password = cls.server_initial['adminPass']
cls.server = (cls.client.show_server(cls.server_initial['id'])
@@ -69,15 +65,15 @@
def _create_net_subnet_ret_net_from_cidr(self, cidr):
name_net = data_utils.rand_name(self.__class__.__name__)
- net = self.network_client.create_network(name=name_net)
- self.addCleanup(self.network_client.delete_network,
+ net = self.networks_client.create_network(name=name_net)
+ self.addCleanup(self.networks_client.delete_network,
net['network']['id'])
- subnet = self.network_client.create_subnet(
+ subnet = self.subnets_client.create_subnet(
network_id=net['network']['id'],
cidr=cidr,
ip_version=4)
- self.addCleanup(self.network_client.delete_subnet,
+ self.addCleanup(self.subnets_client.delete_subnet,
subnet['subnet']['id'])
return net
@@ -150,7 +146,7 @@
group_id)
hints = {'group': group_id}
- server = self.create_test_server(sched_hints=hints,
+ server = self.create_test_server(scheduler_hints=hints,
wait_until='ACTIVE')
# Check a server is in the group
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index c394e44..a59cb16 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import base64
import logging
from six.moves.urllib import parse as urlparse
@@ -145,16 +144,12 @@
# The server should be rebuilt using the provided image and data
meta = {'rebuild': 'server'}
new_name = data_utils.rand_name('server')
- file_contents = 'Test server rebuild.'
- personality = [{'path': 'rebuild.txt',
- 'contents': base64.b64encode(file_contents)}]
password = 'rebuildPassw0rd'
rebuilt_server = self.client.rebuild_server(
self.server_id,
self.image_ref_alt,
name=new_name,
metadata=meta,
- personality=personality,
adminPass=password)['server']
# If the server was rebuilt on a different image, restore it to the
@@ -374,7 +369,7 @@
# for a given server_id and number of lines
# This reboot is necessary for outputting some console log after
- # creating a instance backup. If a instance backup, the console
+ # creating an instance backup. If an instance backup, the console
# log file is truncated and we cannot get any console log through
# "console-log" API.
# The detail is https://bugs.launchpad.net/nova/+bug/1251920
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index f9e8b4f..77ddb3b 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -28,7 +28,7 @@
@classmethod
def resource_setup(cls):
super(ServerMetadataTestJSON, cls).resource_setup()
- server = cls.create_test_server(meta={}, wait_until='ACTIVE')
+ server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
cls.server_id = server['id']
def setUp(self):
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index 5804dbe..cee60fb 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -32,7 +32,7 @@
def resource_setup(cls):
super(ServerMetadataNegativeTestJSON, cls).resource_setup()
cls.tenant_id = cls.client.tenant_id
- server = cls.create_test_server(meta={}, wait_until='ACTIVE')
+ server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
cls.server_id = server['id']
@@ -48,7 +48,7 @@
meta = {key: 'data1'}
self.assertRaises((lib_exc.BadRequest, lib_exc.OverLimit),
self.create_test_server,
- meta=meta)
+ metadata=meta)
# no teardown - all creates should fail
@@ -59,7 +59,7 @@
meta = {'': 'data1'}
self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
- meta=meta)
+ metadata=meta)
@test.attr(type=['negative'])
@test.idempotent_id('4d9cd7a3-2010-4b41-b8fe-3bbf0b169466')
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index a7fc235..77af509 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -17,17 +17,42 @@
from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
+from tempest import config
from tempest import test
+CONF = config.CONF
+
class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
@classmethod
+ def skip_checks(cls):
+ super(ServerPersonalityTestJSON, cls).skip_checks()
+ if not CONF.compute_feature_enabled.personality:
+ raise cls.skipException("Nova personality feature disabled")
+
+ @classmethod
def setup_clients(cls):
super(ServerPersonalityTestJSON, cls).setup_clients()
cls.client = cls.servers_client
cls.user_client = cls.limits_client
+ @test.idempotent_id('3cfe87fd-115b-4a02-b942-7dc36a337fdf')
+ def test_create_server_with_personality(self):
+ file_contents = 'This is a test file.'
+ personality = [{'path': '/test.txt',
+ 'contents': base64.b64encode(file_contents)}]
+ self.create_test_server(personality=personality)
+
+ @test.idempotent_id('128966d8-71fc-443c-8cab-08e24114ecc9')
+ def test_rebuild_server_with_personality(self):
+ server_id = self.rebuild_server(None)
+ file_contents = 'Test server rebuild.'
+ personality = [{'path': 'rebuild.txt',
+ 'contents': base64.b64encode(file_contents)}]
+ self.client.rebuild_server(server_id, self.image_ref_alt,
+ personality=personality)
+
@test.idempotent_id('176cd8c9-b9e8-48ee-a480-180beab292bf')
def test_personality_files_exceed_limit(self):
# Server creation should fail if greater than the maximum allowed
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index dbaa6a1..98b292a 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -66,6 +66,8 @@
@test.attr(type=['negative'])
@test.idempotent_id('b8a7235e-5246-4a8f-a08e-b34877c6586f')
+ @testtools.skipUnless(CONF.compute_feature_enabled.personality,
+ 'Nova personality feature disabled')
def test_personality_file_contents_not_encoded(self):
# Use an unencoded file when creating a server with personality
@@ -236,7 +238,7 @@
metadata = {'a': 'b' * 260}
self.assertRaises((lib_exc.BadRequest, lib_exc.OverLimit),
self.create_test_server,
- meta=metadata)
+ metadata=metadata)
@test.attr(type=['negative'])
@test.idempotent_id('aa8eed43-e2cb-4ebf-930b-da14f6a21d81')
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index e60874f..f8d0cca 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -181,10 +181,19 @@
def test_create_server_with_unauthorized_image(self):
# Server creation with another user's image should fail
self.assertRaises(lib_exc.BadRequest, self.alt_client.create_server,
- 'test', self.image['id'], self.flavor_ref)
+ name='test', imageRef=self.image['id'],
+ flavorRef=self.flavor_ref)
@test.idempotent_id('acf8724b-142b-4044-82c3-78d31a533f24')
def test_create_server_fails_when_tenant_incorrect(self):
+ # BUG(sdague): this test should fail because of bad auth url,
+ # which means that when we run with a service catalog without
+ # project_id in the urls, it should fail to fail, and thus
+ # fail the test. It does not.
+ #
+ # The 400 BadRequest is clearly ambiguous, and something else
+ # is wrong about this request. This should be fixed.
+ #
# A create server request should fail if the tenant id does not match
# the current user
# Change the base URL to impersonate another user
@@ -193,14 +202,27 @@
auth_data=self.client.auth_provider.auth_data
)
self.assertRaises(lib_exc.BadRequest,
- self.alt_client.create_server, 'test',
- self.image['id'], self.flavor_ref)
+ self.alt_client.create_server, name='test',
+ imageRef=self.image['id'], flavorRef=self.flavor_ref)
@test.idempotent_id('f03d1ded-7fd4-4d29-bc13-e2391f29c625')
def test_create_keypair_in_analt_user_tenant(self):
- # A create keypair request should fail if the tenant id does not match
- # the current user
- # POST keypair with other user tenant
+ """create keypair should not function for alternate tenant
+
+ POST {alt_service_url}/os-keypairs
+
+ Attempt to create a keypair against an alternate tenant by
+ changing using a different tenant's service url. This should
+ return a BadRequest. This tests basic tenant isolation protections.
+
+ NOTE(sdague): if the environment does not use project_id in
+ the service urls, this test is not valid. Skip under these
+ conditions.
+
+ """
+ if self.alt_keypairs_client.base_url == self.keypairs_client.base_url:
+ raise self.skipException("Service urls don't include project_id")
+
k_name = data_utils.rand_name('keypair')
try:
# Change the base URL to impersonate another user
@@ -249,9 +271,23 @@
@test.idempotent_id('752c917e-83be-499d-a422-3559127f7d3c')
def test_create_security_group_in_analt_user_tenant(self):
- # A create security group request should fail if the tenant id does not
- # match the current user
- # POST security group with other user tenant
+ """create security group should not function for alternate tenant
+
+ POST {alt_service_url}/os-security-groups
+
+ Attempt to create a security group against an alternate tenant
+ by changing using a different tenant's service url. This
+ should return a BadRequest. This tests basic tenant isolation
+ protections.
+
+ NOTE(sdague): if the environment does not use project_id in
+ the service urls, this test is not valid. Skip under these
+ conditions.
+
+ """
+ if self.alt_security_client.base_url == self.security_client.base_url:
+ raise self.skipException("Service urls don't include project_id")
+
s_name = data_utils.rand_name('security')
s_description = data_utils.rand_name('security')
try:
@@ -288,9 +324,23 @@
@test.idempotent_id('b2b76de0-210a-4089-b921-591c9ec552f6')
def test_create_security_group_rule_in_analt_user_tenant(self):
- # A create security group rule request should fail if the tenant id
- # does not match the current user
- # POST security group rule with other user tenant
+ """create security group rule should not function for alternate tenant
+
+ POST {alt_service_url}/os-security-group-rules
+
+ Attempt to create a security group rule against an alternate
+ tenant by changing using a different tenant's service
+ url. This should return a BadRequest. This tests basic tenant
+ isolation protections.
+
+ NOTE(sdague): if the environment does not use project_id in
+ the service urls, this test is not valid. Skip under these
+ conditions.
+
+ """
+ if self.alt_security_client.base_url == self.security_client.base_url:
+ raise self.skipException("Service urls don't include project_id")
+
parent_group_id = self.security_group['id']
ip_protocol = 'icmp'
from_port = -1
diff --git a/tempest/api/database/limits/test_limits.py b/tempest/api/database/limits/test_limits.py
index 4b7f2d6..ee51b1d 100644
--- a/tempest/api/database/limits/test_limits.py
+++ b/tempest/api/database/limits/test_limits.py
@@ -27,7 +27,7 @@
@test.attr(type='smoke')
@test.idempotent_id('73024538-f316-4829-b3e9-b459290e137a')
def test_absolute_limits(self):
- # Test to verify if all absolute limit paramaters are
+ # Test to verify if all absolute limit parameters are
# present when verb is ABSOLUTE
limits = self.client.list_db_limits()['limits']
expected_abs_limits = ['max_backups', 'max_volumes',
diff --git a/tempest/api/identity/admin/v2/test_endpoints.py b/tempest/api/identity/admin/v2/test_endpoints.py
index 3af2e90..bff4f91 100644
--- a/tempest/api/identity/admin/v2/test_endpoints.py
+++ b/tempest/api/identity/admin/v2/test_endpoints.py
@@ -27,9 +27,8 @@
s_name = data_utils.rand_name('service')
s_type = data_utils.rand_name('type')
s_description = data_utils.rand_name('description')
- cls.service_data =\
- cls.client.create_service(s_name, s_type,
- description=s_description)
+ cls.service_data = cls.client.create_service(
+ s_name, s_type, description=s_description)['OS-KSADM:service']
cls.service_id = cls.service_data['id']
cls.service_ids.append(cls.service_id)
# Create endpoints so as to use for LIST and GET test cases
@@ -41,7 +40,7 @@
region,
publicurl=url,
adminurl=url,
- internalurl=url)
+ internalurl=url)['endpoint']
# list_endpoints() will return 'enabled' field
endpoint['enabled'] = True
cls.setup_endpoints.append(endpoint)
@@ -57,7 +56,7 @@
@test.idempotent_id('11f590eb-59d8-4067-8b2b-980c7f387f51')
def test_list_endpoints(self):
# Get a list of endpoints
- fetched_endpoints = self.client.list_endpoints()
+ fetched_endpoints = self.client.list_endpoints()['endpoints']
# Asserting LIST endpoints
missing_endpoints =\
[e for e in self.setup_endpoints if e not in fetched_endpoints]
@@ -73,18 +72,18 @@
region,
publicurl=url,
adminurl=url,
- internalurl=url)
+ internalurl=url)['endpoint']
# Asserting Create Endpoint response body
self.assertIn('id', endpoint)
self.assertEqual(region, endpoint['region'])
self.assertEqual(url, endpoint['publicurl'])
# Checking if created endpoint is present in the list of endpoints
- fetched_endpoints = self.client.list_endpoints()
+ fetched_endpoints = self.client.list_endpoints()['endpoints']
fetched_endpoints_id = [e['id'] for e in fetched_endpoints]
self.assertIn(endpoint['id'], fetched_endpoints_id)
# Deleting the endpoint created in this method
self.client.delete_endpoint(endpoint['id'])
# Checking whether endpoint is deleted successfully
- fetched_endpoints = self.client.list_endpoints()
+ fetched_endpoints = self.client.list_endpoints()['endpoints']
fetched_endpoints_id = [e['id'] for e in fetched_endpoints]
self.assertNotIn(endpoint['id'], fetched_endpoints_id)
diff --git a/tempest/api/identity/admin/v2/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
index 0b28a07..78beead 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.client.create_role(role_name)
+ role = cls.client.create_role(role_name)['role']
cls.data.roles.append(role)
def _get_role_params(self):
@@ -48,7 +48,7 @@
@test.idempotent_id('75d9593f-50b7-4fcf-bd64-e3fb4a278e23')
def test_list_roles(self):
"""Return a list of all roles."""
- body = self.client.list_roles()
+ body = self.client.list_roles()['roles']
found = [role for role in body if role in self.data.roles]
self.assertTrue(any(found))
self.assertEqual(len(found), len(self.data.roles))
@@ -57,16 +57,16 @@
def test_role_create_delete(self):
"""Role should be created, verified, and deleted."""
role_name = data_utils.rand_name(name='role-test')
- body = self.client.create_role(role_name)
+ body = self.client.create_role(role_name)['role']
self.assertEqual(role_name, body['name'])
- body = self.client.list_roles()
+ body = self.client.list_roles()['roles']
found = [role for role in body if role['name'] == role_name]
self.assertTrue(any(found))
body = self.client.delete_role(found[0]['id'])
- body = self.client.list_roles()
+ body = self.client.list_roles()['roles']
found = [role for role in body if role['name'] == role_name]
self.assertFalse(any(found))
@@ -85,7 +85,7 @@
"""Assign a role to a user on a tenant."""
(user, tenant, role) = self._get_role_params()
self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- roles = self.client.list_user_roles(tenant['id'], user['id'])
+ roles = self.client.list_user_roles(tenant['id'], user['id'])['roles']
self.assert_role_in_role_list(role, roles)
@test.idempotent_id('f0b9292c-d3ba-4082-aa6c-440489beef69')
@@ -93,7 +93,8 @@
"""Remove a role assigned to a user on a tenant."""
(user, tenant, role) = self._get_role_params()
user_role = self.client.assign_user_role(tenant['id'],
- user['id'], role['id'])
+ user['id'],
+ role['id'])['role']
self.client.remove_user_role(tenant['id'], user['id'],
user_role['id'])
@@ -102,5 +103,5 @@
"""List roles assigned to a user on tenant."""
(user, tenant, role) = self._get_role_params()
self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- roles = self.client.list_user_roles(tenant['id'], user['id'])
+ roles = self.client.list_user_roles(tenant['id'], user['id'])['roles']
self.assert_role_in_role_list(role, roles)
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index b38b7dd..5932aba 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -78,7 +78,7 @@
def test_role_create_duplicate(self):
# Role names should be unique
role_name = data_utils.rand_name(name='role-dup')
- body = self.client.create_role(role_name)
+ body = self.client.create_role(role_name)['role']
role1_id = body.get('id')
self.addCleanup(self.client.delete_role, role1_id)
self.assertRaises(lib_exc.Conflict, self.client.create_role,
@@ -89,7 +89,7 @@
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.client.create_role(role_name)
+ body = self.client.create_role(role_name)['role']
self.data.roles.append(body)
role_id = body.get('id')
self.assertRaises(lib_exc.Forbidden,
@@ -100,7 +100,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.client.create_role(role_name)
+ body = self.client.create_role(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_services.py b/tempest/api/identity/admin/v2/test_services.py
index ef93981..eebeedb 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -38,7 +38,7 @@
type = data_utils.rand_name('type')
description = data_utils.rand_name('description')
service_data = self.client.create_service(
- name, type, description=description)
+ name, type, description=description)['OS-KSADM:service']
self.assertFalse(service_data['id'] is None)
self.addCleanup(self._del_service, service_data['id'])
# Verifying response body of create service
@@ -50,7 +50,8 @@
self.assertIn('description', service_data)
self.assertEqual(description, service_data['description'])
# Get service
- fetched_service = self.client.get_service(service_data['id'])
+ fetched_service = (self.client.get_service(service_data['id'])
+ ['OS-KSADM:service'])
# verifying the existence of service created
self.assertIn('id', fetched_service)
self.assertEqual(fetched_service['id'], service_data['id'])
@@ -67,7 +68,7 @@
# Create a service only with name and type
name = data_utils.rand_name('service')
type = data_utils.rand_name('type')
- service = self.client.create_service(name, type)
+ service = self.client.create_service(name, type)['OS-KSADM:service']
self.assertIn('id', service)
self.addCleanup(self._del_service, service['id'])
self.assertIn('name', service)
@@ -85,7 +86,7 @@
type = data_utils.rand_name('type')
description = data_utils.rand_name('description')
service = self.client.create_service(
- name, type, description=description)
+ name, type, description=description)['OS-KSADM:service']
services.append(service)
service_ids = map(lambda x: x['id'], services)
@@ -95,6 +96,6 @@
self.addCleanup(delete_services)
# List and Verify Services
- body = self.client.list_services()
+ body = self.client.list_services()['OS-KSADM:services']
found = [serv for serv in body if serv['id'] in service_ids]
self.assertEqual(len(found), len(services), 'Services not found')
diff --git a/tempest/api/identity/admin/v2/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
index bccb5ca..74558d1 100644
--- a/tempest/api/identity/admin/v2/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.py
@@ -45,7 +45,7 @@
def test_tenant_delete_by_unauthorized_user(self):
# Non-administrator user should not be able to delete a tenant
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)
+ tenant = self.client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
self.assertRaises(lib_exc.Forbidden,
self.non_admin_client.delete_tenant, tenant['id'])
@@ -55,7 +55,7 @@
def test_tenant_delete_request_without_token(self):
# Request to delete a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)
+ tenant = self.client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
@@ -75,7 +75,7 @@
def test_tenant_create_duplicate(self):
# Tenant names should be unique
tenant_name = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(tenant_name)
+ body = self.client.create_tenant(tenant_name)['tenant']
tenant = body
self.data.tenants.append(tenant)
tenant1_id = body.get('id')
@@ -131,7 +131,7 @@
def test_tenant_update_by_unauthorized_user(self):
# Non-administrator user should not be able to update a tenant
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)
+ tenant = self.client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
self.assertRaises(lib_exc.Forbidden,
self.non_admin_client.update_tenant, tenant['id'])
@@ -141,7 +141,7 @@
def test_tenant_update_request_without_token(self):
# Request to update a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)
+ tenant = self.client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
diff --git a/tempest/api/identity/admin/v2/test_tenants.py b/tempest/api/identity/admin/v2/test_tenants.py
index 9fff5f3..2ec5c4f 100644
--- a/tempest/api/identity/admin/v2/test_tenants.py
+++ b/tempest/api/identity/admin/v2/test_tenants.py
@@ -28,7 +28,7 @@
tenants = []
for _ in moves.xrange(3):
tenant_name = data_utils.rand_name(name='tenant-new')
- tenant = self.client.create_tenant(tenant_name)
+ tenant = self.client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
tenants.append(tenant)
tenant_ids = map(lambda x: x['id'], tenants)
@@ -50,14 +50,14 @@
tenant_name = data_utils.rand_name(name='tenant')
tenant_desc = data_utils.rand_name(name='desc')
body = self.client.create_tenant(tenant_name,
- description=tenant_desc)
+ description=tenant_desc)['tenant']
tenant = body
self.data.tenants.append(tenant)
tenant_id = body['id']
desc1 = body['description']
self.assertEqual(desc1, tenant_desc, 'Description should have '
'been sent in response for create')
- body = self.client.get_tenant(tenant_id)
+ body = self.client.get_tenant(tenant_id)['tenant']
desc2 = body['description']
self.assertEqual(desc2, tenant_desc, 'Description does not appear'
'to be set')
@@ -68,13 +68,13 @@
def test_tenant_create_enabled(self):
# Create a tenant that is enabled
tenant_name = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(tenant_name, enabled=True)
+ body = self.client.create_tenant(tenant_name, enabled=True)['tenant']
tenant = body
self.data.tenants.append(tenant)
tenant_id = body['id']
en1 = body['enabled']
self.assertTrue(en1, 'Enable should be True in response')
- body = self.client.get_tenant(tenant_id)
+ body = self.client.get_tenant(tenant_id)['tenant']
en2 = body['enabled']
self.assertTrue(en2, 'Enable should be True in lookup')
self.client.delete_tenant(tenant_id)
@@ -84,14 +84,14 @@
def test_tenant_create_not_enabled(self):
# Create a tenant that is not enabled
tenant_name = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(tenant_name, enabled=False)
+ body = self.client.create_tenant(tenant_name, enabled=False)['tenant']
tenant = body
self.data.tenants.append(tenant)
tenant_id = body['id']
en1 = body['enabled']
self.assertEqual('false', str(en1).lower(),
'Enable should be False in response')
- body = self.client.get_tenant(tenant_id)
+ body = self.client.get_tenant(tenant_id)['tenant']
en2 = body['enabled']
self.assertEqual('false', str(en2).lower(),
'Enable should be False in lookup')
@@ -102,7 +102,7 @@
def test_tenant_update_name(self):
# Update name attribute of a tenant
t_name1 = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(t_name1)
+ body = self.client.create_tenant(t_name1)['tenant']
tenant = body
self.data.tenants.append(tenant)
@@ -110,11 +110,11 @@
resp1_name = body['name']
t_name2 = data_utils.rand_name(name='tenant2')
- body = self.client.update_tenant(t_id, name=t_name2)
+ body = self.client.update_tenant(t_id, name=t_name2)['tenant']
resp2_name = body['name']
self.assertNotEqual(resp1_name, resp2_name)
- body = self.client.get_tenant(t_id)
+ body = self.client.get_tenant(t_id)['tenant']
resp3_name = body['name']
self.assertNotEqual(resp1_name, resp3_name)
@@ -129,7 +129,7 @@
# Update description attribute of a tenant
t_name = data_utils.rand_name(name='tenant')
t_desc = data_utils.rand_name(name='desc')
- body = self.client.create_tenant(t_name, description=t_desc)
+ body = self.client.create_tenant(t_name, description=t_desc)['tenant']
tenant = body
self.data.tenants.append(tenant)
@@ -137,11 +137,11 @@
resp1_desc = body['description']
t_desc2 = data_utils.rand_name(name='desc2')
- body = self.client.update_tenant(t_id, description=t_desc2)
+ body = self.client.update_tenant(t_id, description=t_desc2)['tenant']
resp2_desc = body['description']
self.assertNotEqual(resp1_desc, resp2_desc)
- body = self.client.get_tenant(t_id)
+ body = self.client.get_tenant(t_id)['tenant']
resp3_desc = body['description']
self.assertNotEqual(resp1_desc, resp3_desc)
@@ -156,7 +156,7 @@
# Update the enabled attribute of a tenant
t_name = data_utils.rand_name(name='tenant')
t_en = False
- body = self.client.create_tenant(t_name, enabled=t_en)
+ body = self.client.create_tenant(t_name, enabled=t_en)['tenant']
tenant = body
self.data.tenants.append(tenant)
@@ -164,11 +164,11 @@
resp1_en = body['enabled']
t_en2 = True
- body = self.client.update_tenant(t_id, enabled=t_en2)
+ body = self.client.update_tenant(t_id, enabled=t_en2)['tenant']
resp2_en = body['enabled']
self.assertNotEqual(resp1_en, resp2_en)
- body = self.client.get_tenant(t_id)
+ body = self.client.get_tenant(t_id)['tenant']
resp3_en = body['enabled']
self.assertNotEqual(resp1_en, resp3_en)
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index 66d00d1..981a9ea 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -27,11 +27,11 @@
user_password = data_utils.rand_name(name='pass')
# first:create a tenant
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)
+ tenant = self.client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
# second:create a user
user = self.client.create_user(user_name, user_password,
- tenant['id'], '')
+ tenant['id'], '')['user']
self.data.users.append(user)
# then get a token for the user
body = self.token_client.auth(user_name,
@@ -41,7 +41,7 @@
tenant['name'])
# Perform GET Token
token_id = body['token']['id']
- token_details = self.client.get_token(token_id)
+ token_details = self.client.get_token(token_id)['access']
self.assertEqual(token_id, token_details['token']['id'])
self.assertEqual(user['id'], token_details['user']['id'])
self.assertEqual(user_name, token_details['user']['name'])
@@ -62,21 +62,21 @@
tenant_id = None # No default tenant so will get unscoped token.
email = ''
user = self.client.create_user(user_name, user_password,
- tenant_id, email)
+ tenant_id, email)['user']
self.data.users.append(user)
# Create a couple tenants.
tenant1_name = data_utils.rand_name(name='tenant')
- tenant1 = self.client.create_tenant(tenant1_name)
+ tenant1 = self.client.create_tenant(tenant1_name)['tenant']
self.data.tenants.append(tenant1)
tenant2_name = data_utils.rand_name(name='tenant')
- tenant2 = self.client.create_tenant(tenant2_name)
+ tenant2 = self.client.create_tenant(tenant2_name)['tenant']
self.data.tenants.append(tenant2)
# Create a role
role_name = data_utils.rand_name(name='role')
- role = self.client.create_role(role_name)
+ role = self.client.create_role(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 bfbcfe7..6ee5218 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -36,7 +36,7 @@
self.data.setup_test_tenant()
user = self.client.create_user(self.alt_user, self.alt_password,
self.data.tenant['id'],
- self.alt_email)
+ self.alt_email)['user']
self.data.users.append(user)
self.assertEqual(self.alt_user, user['name'])
@@ -47,7 +47,7 @@
name = data_utils.rand_name('test_user')
user = self.client.create_user(name, self.alt_password,
self.data.tenant['id'],
- self.alt_email, enabled=False)
+ self.alt_email, enabled=False)['user']
self.data.users.append(user)
self.assertEqual(name, user['name'])
self.assertEqual(False, user['enabled'])
@@ -60,7 +60,7 @@
self.data.setup_test_tenant()
user = self.client.create_user(test_user, self.alt_password,
self.data.tenant['id'],
- self.alt_email)
+ self.alt_email)['user']
# Delete the User at the end of this method
self.addCleanup(self.client.delete_user, user['id'])
# Updating user details with new values
@@ -68,12 +68,12 @@
u_email2 = u_name2 + '@testmail.tm'
update_user = self.client.update_user(user['id'], name=u_name2,
email=u_email2,
- enabled=False)
+ enabled=False)['user']
self.assertEqual(u_name2, update_user['name'])
self.assertEqual(u_email2, update_user['email'])
self.assertEqual(False, update_user['enabled'])
# GET by id after updating
- updated_user = self.client.get_user(user['id'])
+ updated_user = self.client.get_user(user['id'])['user']
# Assert response body of GET after updating
self.assertEqual(u_name2, updated_user['name'])
self.assertEqual(u_email2, updated_user['email'])
@@ -86,7 +86,7 @@
self.data.setup_test_tenant()
user = self.client.create_user(test_user, self.alt_password,
self.data.tenant['id'],
- self.alt_email)
+ self.alt_email)['user']
self.client.delete_user(user['id'])
@test.idempotent_id('aca696c3-d645-4f45-b728-63646045beb1')
@@ -121,7 +121,7 @@
def test_get_users(self):
# Get a list of users and find the test user
self.data.setup_test_user()
- users = self.client.get_users()
+ users = self.client.get_users()['users']
self.assertThat([u['name'] for u in users],
matchers.Contains(self.data.test_user),
"Could not find %s" % self.data.test_user)
@@ -135,18 +135,19 @@
alt_tenant_user1 = data_utils.rand_name('tenant_user1')
user1 = self.client.create_user(alt_tenant_user1, 'password1',
self.data.tenant['id'],
- 'user1@123')
+ 'user1@123')['user']
user_ids.append(user1['id'])
self.data.users.append(user1)
alt_tenant_user2 = data_utils.rand_name('tenant_user2')
user2 = self.client.create_user(alt_tenant_user2, 'password2',
self.data.tenant['id'],
- 'user2@123')
+ 'user2@123')['user']
user_ids.append(user2['id'])
self.data.users.append(user2)
# List of users for the respective tenant ID
- body = self.client.list_users_for_tenant(self.data.tenant['id'])
+ body = (self.client.list_users_for_tenant(self.data.tenant['id'])
+ ['users'])
for i in body:
fetched_user_ids.append(i['id'])
# verifying the user Id in the list
@@ -169,19 +170,20 @@
fetched_user_ids = list()
user_ids.append(user['id'])
role = self.client.assign_user_role(tenant['id'], user['id'],
- role['id'])
+ role['id'])['role']
alt_user2 = data_utils.rand_name('second_user')
second_user = self.client.create_user(alt_user2, 'password1',
self.data.tenant['id'],
- 'user2@123')
+ 'user2@123')['user']
user_ids.append(second_user['id'])
self.data.users.append(second_user)
role = self.client.assign_user_role(tenant['id'],
second_user['id'],
- role['id'])
+ role['id'])['role']
# List of users with roles for the respective tenant ID
- body = self.client.list_users_for_tenant(self.data.tenant['id'])
+ body = (self.client.list_users_for_tenant(self.data.tenant['id'])
+ ['users'])
for i in body:
fetched_user_ids.append(i['id'])
# verifying the user Id in the list
@@ -198,7 +200,7 @@
# Updating the user with new password
new_pass = data_utils.rand_name('pass')
update_user = self.client.update_user_password(
- self.data.user['id'], new_pass)
+ self.data.user['id'], new_pass)['user']
self.assertEqual(update_user['id'], self.data.user['id'])
# Validate the updated password
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index ada292f..95826b0 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -39,7 +39,7 @@
@classmethod
def get_user_by_name(cls, name):
- users = cls.client.get_users()
+ users = cls.client.get_users()['users']
user = [u for u in users if u['name'] == name]
if len(user) > 0:
return user[0]
@@ -47,11 +47,7 @@
@classmethod
def get_tenant_by_name(cls, name):
try:
- tenants = cls.client.list_tenants()
- # TODO(jswarren): always retrieve 'tenants' value
- # once both clients return full response objects
- if 'tenants' in tenants:
- tenants = tenants['tenants']
+ tenants = cls.client.list_tenants()['tenants']
except AttributeError:
tenants = cls.client.list_projects()['projects']
tenant = [t for t in tenants if t['name'] == name]
@@ -60,7 +56,7 @@
@classmethod
def get_role_by_name(cls, name):
- roles = cls.client.list_roles()
+ roles = cls.client.list_roles()['roles']
role = [r for r in roles if r['name'] == name]
if len(role) > 0:
return role[0]
@@ -214,7 +210,7 @@
self.user = self.client.create_user(self.test_user,
self.test_password,
self.tenant['id'],
- self.test_email)
+ self.test_email)['user']
self.users.append(self.user)
def setup_test_tenant(self):
@@ -223,13 +219,13 @@
self.test_description = data_utils.rand_name('desc')
self.tenant = self.client.create_tenant(
name=self.test_tenant,
- description=self.test_description)
+ description=self.test_description)['tenant']
self.tenants.append(self.tenant)
def setup_test_role(self):
"""Set up a test role."""
self.test_role = data_utils.rand_name('role')
- self.role = self.client.create_role(self.test_role)
+ self.role = self.client.create_role(self.test_role)['role']
self.roles.append(self.role)
def setup_test_v3_user(self):
diff --git a/tempest/api/identity/test_extension.py b/tempest/api/identity/test_extension.py
index b1d65b4..01e5661 100644
--- a/tempest/api/identity/test_extension.py
+++ b/tempest/api/identity/test_extension.py
@@ -22,7 +22,7 @@
@test.idempotent_id('85f3f661-f54c-4d48-b563-72ae952b9383')
def test_list_extensions(self):
# List all the extensions
- body = self.non_admin_client.list_extensions()
+ body = self.non_admin_client.list_extensions()['extensions']['values']
self.assertNotEmpty(body)
keys = ['name', 'updated', 'alias', 'links',
'namespace', 'description']
diff --git a/tempest/api/identity/v2/test_api_discovery.py b/tempest/api/identity/v2/test_api_discovery.py
index 8132ee1..57c78ef 100644
--- a/tempest/api/identity/v2/test_api_discovery.py
+++ b/tempest/api/identity/v2/test_api_discovery.py
@@ -23,7 +23,7 @@
@test.attr(type='smoke')
@test.idempotent_id('ea889a68-a15f-4166-bfb1-c12456eae853')
def test_api_version_resources(self):
- descr = self.non_admin_client.get_api_description()
+ descr = self.non_admin_client.get_api_description()['version']
expected_resources = ('id', 'links', 'media-types', 'status',
'updated')
@@ -34,7 +34,7 @@
@test.attr(type='smoke')
@test.idempotent_id('007a0be0-78fe-4fdb-bbee-e9216cc17bb2')
def test_api_media_types(self):
- descr = self.non_admin_client.get_api_description()
+ descr = self.non_admin_client.get_api_description()['version']
# Get MIME type bases and descriptions
media_types = [(media_type['base'], media_type['type']) for
media_type in descr['media-types']]
@@ -49,7 +49,7 @@
@test.attr(type='smoke')
@test.idempotent_id('77fd6be0-8801-48e6-b9bf-38cdd2f253ec')
def test_api_version_statuses(self):
- descr = self.non_admin_client.get_api_description()
+ descr = self.non_admin_client.get_api_description()['version']
status = descr['status'].lower()
supported_statuses = ['current', 'stable', 'experimental',
'supported', 'deprecated']
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
index dbb50be..763d8de 100644
--- a/tempest/api/identity/v2/test_ec2_credentials.py
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -38,7 +38,7 @@
"""Create user ec2 credentials."""
resp = self.non_admin_client.create_user_ec2_credentials(
self.creds.credentials.user_id,
- self.creds.credentials.tenant_id)
+ self.creds.credentials.tenant_id)["credential"]
access = resp['access']
self.addCleanup(
self.non_admin_client.delete_user_ec2_credentials,
@@ -55,11 +55,13 @@
fetched_creds = []
# create first ec2 credentials
creds1 = self.non_admin_client.create_user_ec2_credentials(
- self.creds.credentials.user_id, self.creds.credentials.tenant_id)
+ self.creds.credentials.user_id,
+ self.creds.credentials.tenant_id)["credential"]
created_creds.append(creds1['access'])
# create second ec2 credentials
creds2 = self.non_admin_client.create_user_ec2_credentials(
- self.creds.credentials.user_id, self.creds.credentials.tenant_id)
+ self.creds.credentials.user_id,
+ self.creds.credentials.tenant_id)["credential"]
created_creds.append(creds2['access'])
# add credentials to be cleaned up
self.addCleanup(
@@ -70,7 +72,7 @@
self.creds.credentials.user_id, creds2['access'])
# get the list of user ec2 credentials
resp = self.non_admin_client.list_user_ec2_credentials(
- self.creds.credentials.user_id)
+ self.creds.credentials.user_id)["credentials"]
fetched_creds = [cred['access'] for cred in resp]
# created credentials should be in a fetched list
missing = [cred for cred in created_creds
@@ -84,14 +86,14 @@
"""Get the definite user ec2 credentials."""
resp = self.non_admin_client.create_user_ec2_credentials(
self.creds.credentials.user_id,
- self.creds.credentials.tenant_id)
+ self.creds.credentials.tenant_id)["credential"]
self.addCleanup(
self.non_admin_client.delete_user_ec2_credentials,
self.creds.credentials.user_id, resp['access'])
ec2_creds = self.non_admin_client.show_user_ec2_credentials(
self.creds.credentials.user_id, resp['access']
- )
+ )["credential"]
for key in ['access', 'secret', 'user_id', 'tenant_id']:
self.assertEqual(ec2_creds[key], resp[key])
@@ -100,7 +102,7 @@
"""Delete user ec2 credentials."""
resp = self.non_admin_client.create_user_ec2_credentials(
self.creds.credentials.user_id,
- self.creds.credentials.tenant_id)
+ self.creds.credentials.tenant_id)["credential"]
access = resp['access']
self.non_admin_client.delete_user_ec2_credentials(
self.creds.credentials.user_id, access)
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 4e5b41d..3b89b66 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -56,7 +56,7 @@
# user updates own password
resp = self.non_admin_client.update_user_own_password(
- user_id=user_id, new_pass=new_pass, old_pass=old_pass)
+ user_id=user_id, new_pass=new_pass, old_pass=old_pass)['access']
# check authorization with new token
self.non_admin_token_client.auth_token(resp['token']['id'])
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index a336507..bacf211 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -18,10 +18,15 @@
from six import moves
+from oslo_log import log as logging
from tempest.api.image import base
from tempest.common.utils import data_utils
+from tempest import config
from tempest import test
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
class BasicOperationsImagesTest(base.BaseV2ImageTest):
"""
@@ -39,9 +44,11 @@
uuid = '00000000-1111-2222-3333-444455556666'
image_name = data_utils.rand_name('image')
+ container_format = CONF.image.container_formats[0]
+ disk_format = CONF.image.disk_formats[0]
body = self.create_image(name=image_name,
- container_format='bare',
- disk_format='raw',
+ container_format=container_format,
+ disk_format=disk_format,
visibility='private',
ramdisk_id=uuid)
self.assertIn('id', body)
@@ -77,9 +84,11 @@
# Create image
image_name = data_utils.rand_name('image')
+ container_format = CONF.image.container_formats[0]
+ disk_format = CONF.image.disk_formats[0]
body = self.client.create_image(name=image_name,
- container_format='bare',
- disk_format='raw',
+ container_format=container_format,
+ disk_format=disk_format,
visibility='private')
image_id = body['id']
@@ -99,9 +108,11 @@
# Create image
image_name = data_utils.rand_name('image')
+ container_format = CONF.image.container_formats[0]
+ disk_format = CONF.image.disk_formats[0]
body = self.client.create_image(name=image_name,
- container_format='bare',
- disk_format='iso',
+ container_format=container_format,
+ disk_format=disk_format,
visibility='private')
self.addCleanup(self.client.delete_image, body['id'])
self.assertEqual('queued', body['status'])
@@ -133,13 +144,17 @@
super(ListImagesTest, cls).resource_setup()
# We add a few images here to test the listing functionality of
# the images API
- cls._create_standard_image('bare', 'raw')
- cls._create_standard_image('bare', 'raw')
- cls._create_standard_image('ami', 'raw')
- # Add some more for listing
- cls._create_standard_image('ami', 'ami')
- cls._create_standard_image('ari', 'ari')
- cls._create_standard_image('aki', 'aki')
+ container_fmts = CONF.image.container_formats
+ disk_fmts = CONF.image.disk_formats
+ all_pairs = [(container_fmt, disk_fmt)
+ for container_fmt in container_fmts
+ for disk_fmt in disk_fmts]
+
+ for (container_fmt, disk_fmt) in all_pairs[:6]:
+ LOG.debug("Creating a image"
+ "(Container format: %s, Disk format: %s).",
+ container_fmt, disk_fmt)
+ cls._create_standard_image(container_fmt, disk_fmt)
@classmethod
def _create_standard_image(cls, container_format, disk_format):
@@ -201,7 +216,7 @@
@test.idempotent_id('cf1b9a48-8340-480e-af7b-fe7e17690876')
def test_list_images_param_size(self):
# Test to get all images by size
- image_id = self.created_images[1]
+ image_id = self.created_images[0]
# Get image metadata
image = self.client.show_image(image_id)
@@ -211,7 +226,7 @@
@test.idempotent_id('4ad8c157-971a-4ba8-aa84-ed61154b1e7f')
def test_list_images_param_min_max_size(self):
# Test to get all images with size between 2000 to 3000
- image_id = self.created_images[1]
+ image_id = self.created_images[0]
# Get image metadata
image = self.client.show_image(image_id)
@@ -234,7 +249,7 @@
@test.idempotent_id('e914a891-3cc8-4b40-ad32-e0a39ffbddbb')
def test_list_images_param_limit(self):
# Test to get images by limit
- params = {"limit": 2}
+ params = {"limit": 1}
images_list = self.client.list_images(params=params)['images']
self.assertEqual(len(images_list), params['limit'],
diff --git a/tempest/api/image/v2/test_images_metadefs_namespaces.py b/tempest/api/image/v2/test_images_metadefs_namespaces.py
new file mode 100644
index 0000000..21247b1
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_namespaces.py
@@ -0,0 +1,71 @@
+# Copyright 2015 Red Hat, Inc.
+# 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.api.image import base
+from tempest.common.utils import data_utils
+from tempest import test
+from tempest_lib import exceptions as lib_exc
+
+
+class MetadataNamespacesTest(base.BaseV2ImageTest):
+ """
+ Here we will test the Metadata definition Namespaces basic functionality.
+ """
+ @test.idempotent_id('319b765e-7f3d-4b3d-8b37-3ca3876ee768')
+ def test_basic_metadata_definition_namespaces(self):
+ # get the available resource types and use one resource_type
+ body = self.client.list_resource_types()
+ resource_name = body['resource_types'][0]['name']
+ name = [{'name': resource_name}]
+ namespace_name = data_utils.rand_name('namespace')
+ # create the metadef namespaces
+ body = self.client.create_namespaces(namespace=namespace_name,
+ visibility='public',
+ description='Tempest',
+ display_name=namespace_name,
+ resource_type_associations=name,
+ protected=True)
+ self.addCleanup(self._cleanup_namespace, namespace_name)
+ # get namespaces details
+ body = self.client.show_namespaces(namespace_name)
+ self.assertEqual(namespace_name, body['namespace'])
+ self.assertEqual('public', body['visibility'])
+ # unable to delete protected namespace
+ self.assertRaises(lib_exc.Forbidden, self.client.delete_namespaces,
+ namespace_name)
+ # update the visibility to private and protected to False
+ body = self.client.update_namespaces(namespace=namespace_name,
+ description='Tempest',
+ visibility='private',
+ display_name=namespace_name,
+ protected=False)
+ self.assertEqual('private', body['visibility'])
+ self.assertEqual(False, body['protected'])
+ # now able to delete the non-protected namespace
+ self.client.delete_namespaces(namespace_name)
+
+ def _cleanup_namespace(self, namespace_name):
+ # this is used to cleanup the resources
+ try:
+ body = self.client.show_namespaces(namespace_name)
+ self.assertEqual(namespace_name, body['namespace'])
+ body = self.client.update_namespaces(namespace=namespace_name,
+ description='Tempest',
+ visibility='private',
+ display_name=namespace_name,
+ protected=False)
+ self.client.delete_namespaces(namespace_name)
+ except lib_exc.NotFound:
+ pass
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index d942641..ac53587 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -26,9 +26,10 @@
post_body = {'name': data_utils.rand_name('network-')}
if external:
post_body['router:external'] = external
- body = self.admin_client.create_network(**post_body)
+ body = self.admin_networks_client.create_network(**post_body)
network = body['network']
- self.addCleanup(self.admin_client.delete_network, network['id'])
+ self.addCleanup(
+ self.admin_networks_client.delete_network, network['id'])
return network
@test.idempotent_id('462be770-b310-4df9-9c42-773217e4c8b1')
@@ -47,8 +48,8 @@
network = self._create_network(external=False)
self.assertFalse(network.get('router:external', False))
update_body = {'router:external': True}
- body = self.admin_client.update_network(network['id'],
- **update_body)
+ body = self.admin_networks_client.update_network(network['id'],
+ **update_body)
updated_network = body['network']
# Verify that router:external parameter was updated
self.assertTrue(updated_network['router:external'])
@@ -60,7 +61,7 @@
# List networks as a normal user and confirm the external
# network extension attribute is returned for those networks
# that were created as external
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks_list = [net['id'] for net in body['networks']]
self.assertIn(external_network['id'], networks_list)
self.assertIn(self.network['id'], networks_list)
@@ -76,12 +77,12 @@
external_network = self._create_network()
# Show an external network as a normal user and confirm the
# external network extension attribute is returned.
- body = self.client.show_network(external_network['id'])
+ body = self.networks_client.show_network(external_network['id'])
show_ext_net = body['network']
self.assertEqual(external_network['name'], show_ext_net['name'])
self.assertEqual(external_network['id'], show_ext_net['id'])
self.assertTrue(show_ext_net['router:external'])
- body = self.client.show_network(self.network['id'])
+ body = self.networks_client.show_network(self.network['id'])
show_net = body['network']
# Verify with show that router:external is False for network
self.assertEqual(self.network['name'], show_net['name'])
@@ -96,13 +97,15 @@
"""
# Set cls.client to admin to use base.create_subnet()
client = self.admin_client
- body = client.create_network(**{'router:external': True})
+ body = self.admin_networks_client.create_network(
+ **{'router:external': True})
external_network = body['network']
self.addCleanup(self._try_delete_resource,
- client.delete_network,
+ self.admin_networks_client.delete_network,
external_network['id'])
- subnet = self.create_subnet(external_network, client=client,
- enable_dhcp=False)
+ subnet = self.create_subnet(
+ external_network, client=self.admin_subnets_client,
+ enable_dhcp=False)
body = client.create_floatingip(
floating_network_id=external_network['id'])
created_floating_ip = body['floatingip']
@@ -113,13 +116,13 @@
network=external_network['id'])
self.assertIn(created_floating_ip['id'],
(f['id'] for f in floatingip_list['floatingips']))
- client.delete_network(external_network['id'])
+ self.admin_networks_client.delete_network(external_network['id'])
# Verifies floating ip is deleted
floatingip_list = client.list_floatingips()
self.assertNotIn(created_floating_ip['id'],
(f['id'] for f in floatingip_list['floatingips']))
# Verifies subnet is deleted
- subnet_list = client.list_subnets()
+ subnet_list = self.admin_subnets_client.list_subnets()
self.assertNotIn(subnet['id'],
(s['id'] for s in subnet_list))
# Removes subnet from the cleanup list
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index c6b96b7..17adfa5 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -73,6 +73,8 @@
def setup_clients(cls):
super(BaseNetworkTest, cls).setup_clients()
cls.client = cls.os.network_client
+ cls.networks_client = cls.os.networks_client
+ cls.subnets_client = cls.os.subnets_client
@classmethod
def resource_setup(cls):
@@ -114,11 +116,11 @@
router)
# Clean up subnets
for subnet in cls.subnets:
- cls._try_delete_resource(cls.client.delete_subnet,
+ cls._try_delete_resource(cls.subnets_client.delete_subnet,
subnet['id'])
# Clean up networks
for network in cls.networks:
- cls._try_delete_resource(cls.client.delete_network,
+ cls._try_delete_resource(cls.networks_client.delete_network,
network['id'])
super(BaseNetworkTest, cls).resource_cleanup()
@@ -147,7 +149,7 @@
"""Wrapper utility that returns a test network."""
network_name = network_name or data_utils.rand_name('test-network-')
- body = cls.client.create_network(name=network_name)
+ body = cls.networks_client.create_network(name=network_name)
network = body['network']
cls.networks.append(network)
return network
@@ -159,7 +161,7 @@
# allow tests to use admin client
if not client:
- client = cls.client
+ client = cls.subnets_client
# The cidr and mask_bits depend on the ip version.
ip_version = ip_version if ip_version is not None else cls._ip_version
@@ -265,6 +267,8 @@
def setup_clients(cls):
super(BaseAdminNetworkTest, cls).setup_clients()
cls.admin_client = cls.os_adm.network_client
+ cls.admin_networks_client = cls.os_adm.networks_client
+ cls.admin_subnets_client = cls.os_adm.subnets_client
@classmethod
def create_metering_label(cls, name, description):
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index f362f85..631a38b 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -75,11 +75,11 @@
if port['id'] in [p['id'] for p in self.ports]:
self.client.delete_port(port['id'])
self._remove_from_list_by_index(self.ports, port)
- body = self.client.list_subnets()
+ body = self.subnets_client.list_subnets()
subnets = body['subnets']
for subnet in subnets:
if subnet['id'] in [s['id'] for s in self.subnets]:
- self.client.delete_subnet(subnet['id'])
+ self.subnets_client.delete_subnet(subnet['id'])
self._remove_from_list_by_index(self.subnets, subnet)
body = self.client.list_routers()
routers = body['routers']
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 1116573..c5b2080 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -146,7 +146,7 @@
def _delete_network(self, network):
# Deleting network also deletes its subnets if exists
- self.client.delete_network(network['id'])
+ self.networks_client.delete_network(network['id'])
if network in self.networks:
self.networks.remove(network)
for subnet in self.subnets:
@@ -171,7 +171,7 @@
del subnet['dns_nameservers'], compare_args['dns_nameservers']
self._compare_resource_attrs(subnet, compare_args)
- self.client.delete_network(net_id)
+ self.networks_client.delete_network(net_id)
self.networks.pop()
self.subnets.pop()
@@ -186,7 +186,7 @@
self.assertEqual('ACTIVE', network['status'])
# Verify network update
new_name = "New_network"
- body = self.client.update_network(net_id, name=new_name)
+ body = self.networks_client.update_network(net_id, name=new_name)
updated_net = body['network']
self.assertEqual(updated_net['name'], new_name)
# Find a cidr that is not in use yet and create a subnet with it
@@ -194,7 +194,7 @@
subnet_id = subnet['id']
# Verify subnet update
new_name = "New_subnet"
- body = self.client.update_subnet(subnet_id, name=new_name)
+ body = self.subnets_client.update_subnet(subnet_id, name=new_name)
updated_subnet = body['subnet']
self.assertEqual(updated_subnet['name'], new_name)
@@ -202,7 +202,7 @@
@test.idempotent_id('2bf13842-c93f-4a69-83ed-717d2ec3b44e')
def test_show_network(self):
# Verify the details of a network
- body = self.client.show_network(self.network['id'])
+ body = self.networks_client.show_network(self.network['id'])
network = body['network']
for key in ['id', 'name']:
self.assertEqual(network[key], self.network[key])
@@ -211,8 +211,8 @@
def test_show_network_fields(self):
# Verify specific fields of a network
fields = ['id', 'name']
- body = self.client.show_network(self.network['id'],
- fields=fields)
+ body = self.networks_client.show_network(self.network['id'],
+ fields=fields)
network = body['network']
self.assertEqual(sorted(network.keys()), sorted(fields))
for field_name in fields:
@@ -222,7 +222,7 @@
@test.idempotent_id('f7ffdeda-e200-4a7a-bcbe-05716e86bf43')
def test_list_networks(self):
# Verify the network exists in the list of all networks
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks = [network['id'] for network in body['networks']
if network['id'] == self.network['id']]
self.assertNotEmpty(networks, "Created network not found in the list")
@@ -231,7 +231,7 @@
def test_list_networks_fields(self):
# Verify specific fields of the networks
fields = ['id', 'name']
- body = self.client.list_networks(fields=fields)
+ body = self.networks_client.list_networks(fields=fields)
networks = body['networks']
self.assertNotEmpty(networks, "Network list returned is empty")
for network in networks:
@@ -241,7 +241,7 @@
@test.idempotent_id('bd635d81-6030-4dd1-b3b9-31ba0cfdf6cc')
def test_show_subnet(self):
# Verify the details of a subnet
- body = self.client.show_subnet(self.subnet['id'])
+ body = self.subnets_client.show_subnet(self.subnet['id'])
subnet = body['subnet']
self.assertNotEmpty(subnet, "Subnet returned has no fields")
for key in ['id', 'cidr']:
@@ -252,8 +252,8 @@
def test_show_subnet_fields(self):
# Verify specific fields of a subnet
fields = ['id', 'network_id']
- body = self.client.show_subnet(self.subnet['id'],
- fields=fields)
+ body = self.subnets_client.show_subnet(self.subnet['id'],
+ fields=fields)
subnet = body['subnet']
self.assertEqual(sorted(subnet.keys()), sorted(fields))
for field_name in fields:
@@ -263,7 +263,7 @@
@test.idempotent_id('db68ba48-f4ea-49e9-81d1-e367f6d0b20a')
def test_list_subnets(self):
# Verify the subnet exists in the list of all subnets
- body = self.client.list_subnets()
+ body = self.subnets_client.list_subnets()
subnets = [subnet['id'] for subnet in body['subnets']
if subnet['id'] == self.subnet['id']]
self.assertNotEmpty(subnets, "Created subnet not found in the list")
@@ -272,7 +272,7 @@
def test_list_subnets_fields(self):
# Verify specific fields of subnets
fields = ['id', 'network_id']
- body = self.client.list_subnets(fields=fields)
+ body = self.subnets_client.list_subnets(fields=fields)
subnets = body['subnets']
self.assertNotEmpty(subnets, "Subnet list returned is empty")
for subnet in subnets:
@@ -281,7 +281,7 @@
def _try_delete_network(self, net_id):
# delete network, if it exists
try:
- self.client.delete_network(net_id)
+ self.networks_client.delete_network(net_id)
# if network is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
@@ -290,7 +290,7 @@
def test_delete_network_with_subnet(self):
# Creates a network
name = data_utils.rand_name('network-')
- body = self.client.create_network(name=name)
+ body = self.networks_client.create_network(name=name)
network = body['network']
net_id = network['id']
self.addCleanup(self._try_delete_network, net_id)
@@ -300,10 +300,10 @@
subnet_id = subnet['id']
# Delete network while the subnet still exists
- body = self.client.delete_network(net_id)
+ body = self.networks_client.delete_network(net_id)
# Verify that the subnet got automatically deleted.
- self.assertRaises(lib_exc.NotFound, self.client.show_subnet,
+ self.assertRaises(lib_exc.NotFound, self.subnets_client.show_subnet,
subnet_id)
# Since create_subnet adds the subnet to the delete list, and it is
@@ -362,8 +362,8 @@
'gateway_ip': new_gateway, 'enable_dhcp': True}
new_name = "New_subnet"
- body = self.client.update_subnet(subnet_id, name=new_name,
- **kwargs)
+ body = self.subnets_client.update_subnet(subnet_id, name=new_name,
+ **kwargs)
updated_subnet = body['subnet']
kwargs['name'] = new_name
self.assertEqual(sorted(updated_subnet['dns_nameservers']),
@@ -382,7 +382,7 @@
@test.idempotent_id('af774677-42a9-4e4b-bb58-16fe6a5bc1ec')
def test_external_network_visibility(self):
"""Verifies user can see external networks but not subnets."""
- body = self.client.list_networks(**{'router:external': True})
+ body = self.networks_client.list_networks(**{'router:external': True})
networks = [network['id'] for network in body['networks']]
self.assertNotEmpty(networks, "No external networks found")
@@ -398,7 +398,7 @@
# subnets_iter is a list (iterator) of lists. This flattens it to a
# list of UUIDs
public_subnets_iter = itertools.chain(*subnets_iter)
- body = self.client.list_subnets()
+ body = self.subnets_client.list_subnets()
subnets = [sub['id'] for sub in body['subnets']
if sub['id'] in public_subnets_iter]
self.assertEmpty(subnets, "Public subnets visible")
@@ -426,18 +426,18 @@
def _delete_networks(self, created_networks):
for n in created_networks:
- self.client.delete_network(n['id'])
+ self.networks_client.delete_network(n['id'])
# Asserting that the networks are not found in the list after deletion
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks_list = [network['id'] for network in body['networks']]
for n in created_networks:
self.assertNotIn(n['id'], networks_list)
def _delete_subnets(self, created_subnets):
for n in created_subnets:
- self.client.delete_subnet(n['id'])
+ self.subnets_client.delete_subnet(n['id'])
# Asserting that the subnets are not found in the list after deletion
- body = self.client.list_subnets()
+ body = self.subnets_client.list_subnets()
subnets_list = [subnet['id'] for subnet in body['subnets']]
for n in created_subnets:
self.assertNotIn(n['id'], subnets_list)
@@ -461,7 +461,7 @@
created_networks = body['networks']
self.addCleanup(self._delete_networks, created_networks)
# Asserting that the networks are found in the list after creation
- body = self.client.list_networks()
+ body = self.networks_client.list_networks()
networks_list = [network['id'] for network in body['networks']]
for n in created_networks:
self.assertIsNotNone(n['id'])
@@ -496,7 +496,7 @@
created_subnets = body['subnets']
self.addCleanup(self._delete_subnets, created_subnets)
# Asserting that the subnets are found in the list after creation
- body = self.client.list_subnets()
+ body = self.subnets_client.list_subnets()
subnets_list = [subnet['id'] for subnet in body['subnets']]
for n in created_subnets:
self.assertIsNotNone(n['id'])
@@ -576,7 +576,7 @@
# Verifies Subnet GW is None in IPv4
self.assertEqual(subnet2['gateway_ip'], None)
# Verifies all 2 subnets in the same network
- body = self.client.list_subnets()
+ body = self.subnets_client.list_subnets()
subnets = [sub['id'] for sub in body['subnets']
if sub['network_id'] == network['id']]
test_subnet_ids = [sub['id'] for sub in (subnet1, subnet2)]
@@ -621,16 +621,16 @@
'ipv6_address_mode': mode})
port = self.create_port(slaac_network)
self.assertIsNotNone(port['fixed_ips'][0]['ip_address'])
- self.client.delete_subnet(subnet_slaac['id'])
+ self.subnets_client.delete_subnet(subnet_slaac['id'])
self.subnets.pop()
- subnets = self.client.list_subnets()
+ subnets = self.subnets_client.list_subnets()
subnet_ids = [subnet['id'] for subnet in subnets['subnets']]
self.assertNotIn(subnet_slaac['id'], subnet_ids,
"Subnet wasn't deleted")
self.assertRaisesRegexp(
lib_exc.Conflict,
"There are one or more ports still in use on the network",
- self.client.delete_network,
+ self.networks_client.delete_network,
slaac_network['id'])
@test.idempotent_id('88554555-ebf8-41ef-9300-4926d45e06e9')
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 94c3f9a..4fe31cf 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -27,14 +27,14 @@
@test.idempotent_id('9293e937-824d-42d2-8d5b-e985ea67002a')
def test_show_non_existent_network(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.show_network,
+ self.assertRaises(lib_exc.NotFound, self.networks_client.show_network,
non_exist_id)
@test.attr(type=['negative'])
@test.idempotent_id('d746b40c-5e09-4043-99f7-cba1be8b70df')
def test_show_non_existent_subnet(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.show_subnet,
+ self.assertRaises(lib_exc.NotFound, self.subnets_client.show_subnet,
non_exist_id)
@test.attr(type=['negative'])
@@ -48,21 +48,23 @@
@test.idempotent_id('98bfe4e3-574e-4012-8b17-b2647063de87')
def test_update_non_existent_network(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.update_network,
- non_exist_id, name="new_name")
+ self.assertRaises(
+ lib_exc.NotFound, self.networks_client.update_network,
+ non_exist_id, name="new_name")
@test.attr(type=['negative'])
@test.idempotent_id('03795047-4a94-4120-a0a1-bd376e36fd4e')
def test_delete_non_existent_network(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.delete_network,
+ self.assertRaises(lib_exc.NotFound,
+ self.networks_client.delete_network,
non_exist_id)
@test.attr(type=['negative'])
@test.idempotent_id('1cc47884-ac52-4415-a31c-e7ce5474a868')
def test_update_non_existent_subnet(self):
non_exist_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound, self.client.update_subnet,
+ self.assertRaises(lib_exc.NotFound, self.subnets_client.update_subnet,
non_exist_id, name='new_name')
@test.attr(type=['negative'])
@@ -70,7 +72,7 @@
def test_delete_non_existent_subnet(self):
non_exist_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound,
- self.client.delete_subnet, non_exist_id)
+ self.subnets_client.delete_subnet, non_exist_id)
@test.attr(type=['negative'])
@test.idempotent_id('13d3b106-47e6-4b9b-8d53-dae947f092fe')
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 6a8fbec..6f58075 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -106,7 +106,7 @@
allocation_pools = {'allocation_pools': [{'start': str(address + 4),
'end': str(address + 6)}]}
subnet = self.create_subnet(network, **allocation_pools)
- self.addCleanup(self.client.delete_subnet, subnet['id'])
+ self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
body = self.client.create_port(network_id=net_id)
self.addCleanup(self.client.delete_port, body['port']['id'])
port = body['port']
@@ -155,7 +155,7 @@
# Create network and subnet
network = self.create_network()
subnet = self.create_subnet(network)
- self.addCleanup(self.client.delete_subnet, subnet['id'])
+ self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
# Create two ports
port_1 = self.client.create_port(network_id=network['id'])
self.addCleanup(self.client.delete_port, port_1['port']['id'])
@@ -167,19 +167,27 @@
port_list = self.client.list_ports(fixed_ips=fixed_ips)
# Check that we got the desired port
ports = port_list['ports']
- self.assertEqual(len(ports), 1)
- self.assertEqual(ports[0]['id'], port_1['port']['id'])
- self.assertEqual(ports[0]['fixed_ips'][0]['ip_address'],
- port_1_fixed_ip)
- self.assertEqual(ports[0]['network_id'], network['id'])
+ tenant_ids = set([port['tenant_id'] for port in ports])
+ self.assertEqual(len(tenant_ids), 1,
+ 'Ports from multiple tenants are in the list resp')
+ port_ids = [port['id'] for port in ports]
+ fixed_ips = [port['fixed_ips'] for port in ports]
+ port_ips = []
+ for addr in fixed_ips:
+ port_ips.extend([port['ip_address'] for port in addr])
+
+ port_net_ids = [port['network_id'] for port in ports]
+ self.assertIn(port_1['port']['id'], port_ids)
+ self.assertIn(port_1_fixed_ip, port_ips)
+ self.assertIn(network['id'], port_net_ids)
@test.idempotent_id('5ad01ed0-0e6e-4c5d-8194-232801b15c72')
def test_port_list_filter_by_router_id(self):
# Create a router
network = self.create_network()
- self.addCleanup(self.client.delete_network, network['id'])
+ self.addCleanup(self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(network)
- self.addCleanup(self.client.delete_subnet, subnet['id'])
+ self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
router = self.create_router(data_utils.rand_name('router-'))
self.addCleanup(self.client.delete_router, router['id'])
port = self.client.create_port(network_id=network['id'])
@@ -210,11 +218,11 @@
def test_create_update_port_with_second_ip(self):
# Create a network with two subnets
network = self.create_network()
- self.addCleanup(self.client.delete_network, network['id'])
+ self.addCleanup(self.networks_client.delete_network, network['id'])
subnet_1 = self.create_subnet(network)
- self.addCleanup(self.client.delete_subnet, subnet_1['id'])
+ self.addCleanup(self.subnets_client.delete_subnet, subnet_1['id'])
subnet_2 = self.create_subnet(network)
- self.addCleanup(self.client.delete_subnet, subnet_2['id'])
+ self.addCleanup(self.subnets_client.delete_subnet, subnet_2['id'])
fixed_ip_1 = [{'subnet_id': subnet_1['id']}]
fixed_ip_2 = [{'subnet_id': subnet_2['id']}]
@@ -239,7 +247,7 @@
def _update_port_with_security_groups(self, security_groups_names):
subnet_1 = self.create_subnet(self.network)
- self.addCleanup(self.client.delete_subnet, subnet_1['id'])
+ self.addCleanup(self.subnets_client.delete_subnet, subnet_1['id'])
fixed_ip_1 = [{'subnet_id': subnet_1['id']}]
security_groups_list = list()
@@ -318,9 +326,9 @@
@test.idempotent_id('4179dcb9-1382-4ced-84fe-1b91c54f5735')
def test_create_port_with_no_securitygroups(self):
network = self.create_network()
- self.addCleanup(self.client.delete_network, network['id'])
+ self.addCleanup(self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(network)
- self.addCleanup(self.client.delete_subnet, subnet['id'])
+ self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
port = self.create_port(network, security_groups=[])
self.addCleanup(self.client.delete_port, port['id'])
self.assertIsNotNone(port['security_groups'])
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index ca5a868..29855e1 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -188,7 +188,7 @@
gw_port = list_body['ports'][0]
fixed_ips = gw_port['fixed_ips']
self.assertGreaterEqual(len(fixed_ips), 1)
- public_net_body = self.admin_client.show_network(
+ public_net_body = self.admin_networks_client.show_network(
CONF.network.public_network_id)
public_subnet_id = public_net_body['network']['subnets'][0]
self.assertIn(public_subnet_id,
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
new file mode 100644
index 0000000..09478ca
--- /dev/null
+++ b/tempest/api/network/test_subnetpools_extensions.py
@@ -0,0 +1,78 @@
+# Copyright 2015 GlobalLogic. 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.api.network import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import test
+from tempest_lib import exceptions as lib_exc
+
+CONF = config.CONF
+
+
+class SubnetPoolsTestJSON(base.BaseNetworkTest):
+ """
+ Tests the following operations in the subnetpools API using the REST client
+ for Neutron:
+
+ Create a subnet pool.
+ Update a subnet pool.
+ Delete a subnet pool.
+ Lists subnet pool.
+ Show subnet pool details.
+
+ v2.0 of the Neutron API is assumed. It is assumed that subnetpools
+ options mentioned in the [network-feature-enabled] section and
+ default_network option mentioned in the [network] section of
+ etc/tempest.conf:
+
+ """
+
+ @classmethod
+ def skip_checks(cls):
+ super(SubnetPoolsTestJSON, cls).skip_checks()
+ if not test.is_extension_enabled('subnetpools', 'network'):
+ msg = "subnet pools extension not enabled."
+ raise cls.skipException(msg)
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('62595970-ab1c-4b7f-8fcc-fddfe55e9811')
+ def test_create_list_show_update_delete_subnetpools(self):
+ 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)
+ 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)
+ 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)
+ 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,
+ subnetpool_id)
+
+ def _cleanup_subnetpools(self, subnetpool_id):
+ # this is used to cleanup the resources
+ try:
+ self.client.delete_subnetpools(subnetpool_id)
+ except lib_exc.NotFound:
+ pass
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index c78b4c3..896352b 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -26,7 +26,7 @@
class ContainerQuotasTest(base.BaseObjectTest):
- """Attemps to test the perfect behavior of quotas in a container."""
+ """Attempts to test the perfect behavior of quotas in a container."""
def setUp(self):
"""Creates and sets a container with quotas.
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index 4b4b499..18593f3 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -28,7 +28,7 @@
cls.container_name = data_utils.rand_name(name="TestContainer")
# This header should be posted on the container before every test
- cls.headers_public_read_acl = {'Read': '.r:*'}
+ cls.headers_public_read_acl = {'Read': '.r:*,.rlistings'}
# Create test container and create one object in it
cls.container_client.create_container(cls.container_name)
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 5b6b0fa..4968835 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -50,9 +50,15 @@
cls.servers_client = cls.os.servers_client
cls.keypairs_client = cls.os.keypairs_client
cls.network_client = cls.os.network_client
+ cls.networks_client = cls.os.networks_client
cls.volumes_client = cls.os.volumes_client
cls.images_v2_client = cls.os.image_client_v2
+ if CONF.volume_feature_enabled.api_v2:
+ cls.volumes_client = cls.os.volumes_v2_client
+ else:
+ cls.volumes_client = cls.os.volumes_client
+
@classmethod
def resource_setup(cls):
super(BaseOrchestrationTest, cls).resource_setup()
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 8f1f0d6..070150d 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -44,6 +44,7 @@
def setup_clients(cls):
super(NeutronResourcesTestJSON, cls).setup_clients()
cls.network_client = cls.os.network_client
+ cls.subnets_client = cls.os.subnets_client
@classmethod
def resource_setup(cls):
@@ -118,7 +119,7 @@
def test_created_network(self):
"""Verifies created network."""
network_id = self.test_resources.get('Network')['physical_resource_id']
- body = self.network_client.show_network(network_id)
+ body = self.networks_client.show_network(network_id)
network = body['network']
self.assertIsInstance(network, dict)
self.assertEqual(network_id, network['id'])
@@ -130,7 +131,7 @@
def test_created_subnet(self):
"""Verifies created subnet."""
subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
- body = self.network_client.show_subnet(subnet_id)
+ body = self.subnets_client.show_subnet(subnet_id)
subnet = body['subnet']
network_id = self.test_resources.get('Network')['physical_resource_id']
self.assertEqual(subnet_id, subnet['id'])
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index 4ba38ad..ae9a411 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -38,10 +38,19 @@
self.assertEqual('available', volume.get('status'))
self.assertEqual(template['resources']['volume']['properties'][
'size'], volume.get('size'))
+
+ # Some volume properties have been renamed with Cinder v2
+ if CONF.volume_feature_enabled.api_v2:
+ description_field = 'description'
+ name_field = 'name'
+ else:
+ description_field = 'display_description'
+ name_field = 'display_name'
+
self.assertEqual(template['resources']['volume']['properties'][
- 'description'], volume.get('display_description'))
+ 'description'], volume.get(description_field))
self.assertEqual(template['resources']['volume']['properties'][
- 'name'], volume.get('display_name'))
+ 'name'], volume.get(name_field))
def _outputs_verify(self, stack_identifier, template):
self.assertEqual('available',
diff --git a/tempest/api/telemetry/test_alarming_api_negative.py b/tempest/api/telemetry/test_alarming_api_negative.py
new file mode 100644
index 0000000..7d5a0bf
--- /dev/null
+++ b/tempest/api/telemetry/test_alarming_api_negative.py
@@ -0,0 +1,71 @@
+# Copyright 2015 GlobalLogic. 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.api.telemetry import base
+from tempest.common.utils import data_utils
+from tempest import test
+from tempest_lib import exceptions as lib_exc
+
+import uuid
+
+
+class TelemetryAlarmingNegativeTest(base.BaseTelemetryTest):
+ """here we have negative tests for show_alarm, update_alarm, show_alarm_history
+ Tests
+ ** show non-existent alarm
+ ** show the deleted alarm
+ ** delete deleted alarm
+ ** update deleted alarm
+ """
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81e7d')
+ def test_get_non_existent_alarm(self):
+ # get the non-existent alarm
+ non_existent_id = str(uuid.uuid4())
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+ non_existent_id)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('ef45000d-0a72-4781-866d-4cb7bf2582ad')
+ def test_get_update_show_history_delete_deleted_alarm(self):
+ # get, update and delete the deleted alarm
+ alarm_name = data_utils.rand_name('telemetry_alarm')
+ rule = {'meter_name': 'cpu',
+ 'comparison_operator': 'eq',
+ 'threshold': 100.0,
+ 'period': 90}
+ body = self.telemetry_client.create_alarm(
+ name=alarm_name,
+ type='threshold',
+ threshold_rule=rule)
+ alarm_id = body['alarm_id']
+ self.telemetry_client.delete_alarm(alarm_id)
+ # get the deleted alarm
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+ alarm_id)
+
+ # update the deleted alarm
+ updated_alarm_name = data_utils.rand_name('telemetry_alarm_updated')
+ updated_rule = {'meter_name': 'cpu_new',
+ 'comparison_operator': 'eq',
+ 'threshold': 70,
+ 'period': 50}
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.update_alarm,
+ alarm_id, threshold_rule=updated_rule,
+ name=updated_alarm_name,
+ type='threshold')
+ # delete the deleted alarm
+ self.assertRaises(lib_exc.NotFound, self.telemetry_client.delete_alarm,
+ alarm_id)
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index d1a6db0..9185553 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -16,8 +16,11 @@
from tempest_lib import exceptions as lib_exc
from tempest.api.volume import base
+from tempest import config
from tempest import test
+CONF = config.CONF
+
class BaseVolumeQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
force_tenant_isolation = True
@@ -31,11 +34,11 @@
def resource_setup(cls):
super(BaseVolumeQuotasNegativeV2TestJSON, cls).resource_setup()
cls.default_volume_size = cls.volumes_client.default_volume_size
- cls.shared_quota_set = {'gigabytes': 3 * cls.default_volume_size,
- 'volumes': 1, 'snapshots': 1}
+ cls.shared_quota_set = {'gigabytes': 2 * cls.default_volume_size,
+ 'volumes': 1}
# NOTE(gfidente): no need to restore original quota set
- # after the tests as they only work with tenant isolation.
+ # after the tests as they only work with dynamic credentials.
cls.quotas_client.update_quota_set(
cls.demo_tenant_id,
**cls.shared_quota_set)
@@ -43,7 +46,6 @@
# NOTE(gfidente): no need to delete in tearDown as
# they are created using utility wrapper methods.
cls.volume = cls.create_volume()
- cls.snapshot = cls.create_snapshot(cls.volume['id'])
@test.attr(type='negative')
@test.idempotent_id('bf544854-d62a-47f2-a681-90f7a47d86b6')
@@ -52,13 +54,6 @@
self.volumes_client.create_volume)
@test.attr(type='negative')
- @test.idempotent_id('02bbf63f-6c05-4357-9d98-2926a94064ff')
- def test_quota_volume_snapshots(self):
- self.assertRaises(lib_exc.OverLimit,
- self.snapshots_client.create_snapshot,
- self.volume['id'])
-
- @test.attr(type='negative')
@test.idempotent_id('2dc27eee-8659-4298-b900-169d71a91374')
def test_quota_volume_gigabytes(self):
# NOTE(gfidente): quota set needs to be changed for this test
@@ -67,8 +62,7 @@
self.addCleanup(self.quotas_client.update_quota_set,
self.demo_tenant_id,
**self.shared_quota_set)
-
- new_quota_set = {'gigabytes': 2 * self.default_volume_size,
+ new_quota_set = {'gigabytes': self.default_volume_size,
'volumes': 2, 'snapshots': 1}
self.quotas_client.update_quota_set(
self.demo_tenant_id,
@@ -76,15 +70,6 @@
self.assertRaises(lib_exc.OverLimit,
self.volumes_client.create_volume)
- new_quota_set = {'gigabytes': 2 * self.default_volume_size,
- 'volumes': 1, 'snapshots': 2}
- self.quotas_client.update_quota_set(
- self.demo_tenant_id,
- **self.shared_quota_set)
- self.assertRaises(lib_exc.OverLimit,
- self.snapshots_client.create_snapshot,
- self.volume['id'])
-
class VolumeQuotasNegativeV1TestJSON(BaseVolumeQuotasNegativeV2TestJSON):
_api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
new file mode 100644
index 0000000..ce0b618
--- /dev/null
+++ b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
@@ -0,0 +1,81 @@
+# Copyright 2014 OpenStack Foundation
+# 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_lib import exceptions as lib_exc
+
+from tempest.api.volume import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class VolumeSnapshotQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
+ force_tenant_isolation = True
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).skip_checks()
+ if not CONF.volume_feature_enabled.snapshot:
+ raise cls.skipException('Cinder volume snapshots are disabled')
+
+ @classmethod
+ def setup_credentials(cls):
+ super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).setup_credentials()
+ cls.demo_tenant_id = cls.os.credentials.tenant_id
+
+ @classmethod
+ def resource_setup(cls):
+ super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).resource_setup()
+ cls.default_volume_size = cls.volumes_client.default_volume_size
+ cls.shared_quota_set = {'gigabytes': 3 * cls.default_volume_size,
+ 'volumes': 1, 'snapshots': 1}
+
+ # NOTE(gfidente): no need to restore original quota set
+ # after the tests as they only work with tenant isolation.
+ cls.quotas_client.update_quota_set(
+ cls.demo_tenant_id,
+ **cls.shared_quota_set)
+
+ # NOTE(gfidente): no need to delete in tearDown as
+ # they are created using utility wrapper methods.
+ cls.volume = cls.create_volume()
+ cls.snapshot = cls.create_snapshot(cls.volume['id'])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('02bbf63f-6c05-4357-9d98-2926a94064ff')
+ def test_quota_volume_snapshots(self):
+ self.assertRaises(lib_exc.OverLimit,
+ self.snapshots_client.create_snapshot,
+ self.volume['id'])
+
+ @test.attr(type='negative')
+ @test.idempotent_id('c99a1ca9-6cdf-498d-9fdf-25832babef27')
+ def test_quota_volume_gigabytes_snapshots(self):
+ self.addCleanup(self.quotas_client.update_quota_set,
+ self.demo_tenant_id,
+ **self.shared_quota_set)
+ new_quota_set = {'gigabytes': 2 * self.default_volume_size,
+ 'volumes': 1, 'snapshots': 2}
+ self.quotas_client.update_quota_set(
+ self.demo_tenant_id,
+ **new_quota_set)
+ self.assertRaises(lib_exc.OverLimit,
+ self.snapshots_client.create_snapshot,
+ self.volume['id'])
+
+
+class VolumeSnapshotNegativeV1TestJSON(VolumeSnapshotQuotasNegativeV2TestJSON):
+ _api_version = 1
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 7eaa9cc..9866da3 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -85,9 +85,7 @@
snapshot = self.create_snapshot(self.volume_origin['id'],
force=True)
# Delete the snapshot
- self.snapshots_client.delete_snapshot(snapshot['id'])
- self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
- self.snapshots.remove(snapshot)
+ self.cleanup_snapshot(snapshot)
@test.idempotent_id('2a8abbe4-d871-46db-b049-c41f5af8216e')
def test_snapshot_create_get_list_update_delete(self):
@@ -126,9 +124,7 @@
self.assertEqual(new_desc, updated_snapshot[self.descrip_field])
# Delete the snapshot
- self.snapshots_client.delete_snapshot(snapshot['id'])
- self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
- self.snapshots.remove(snapshot)
+ self.cleanup_snapshot(snapshot)
@test.idempotent_id('59f41f43-aebf-48a9-ab5d-d76340fab32b')
def test_snapshots_list_with_params(self):
@@ -137,6 +133,7 @@
display_name = data_utils.rand_name('snap')
params = {self.name_field: display_name}
snapshot = self.create_snapshot(self.volume_origin['id'], **params)
+ self.addCleanup(self.cleanup_snapshot, snapshot)
# Verify list snapshots by display_name filter
params = {self.name_field: snapshot[self.name_field]}
@@ -158,6 +155,7 @@
display_name = data_utils.rand_name('snap')
params = {self.name_field: display_name}
snapshot = self.create_snapshot(self.volume_origin['id'], **params)
+ self.addCleanup(self.cleanup_snapshot, snapshot)
# Verify list snapshot details by display_name filter
params = {self.name_field: snapshot[self.name_field]}
@@ -181,7 +179,13 @@
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
self.volumes_client.delete_volume(volume['id'])
self.volumes_client.wait_for_resource_deletion(volume['id'])
- self.clear_snapshots()
+ self.cleanup_snapshot(snapshot)
+
+ def cleanup_snapshot(self, snapshot):
+ # Delete the snapshot
+ self.snapshots_client.delete_snapshot(snapshot['id'])
+ self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
+ self.snapshots.remove(snapshot)
class VolumesV1SnapshotTestJSON(VolumesV2SnapshotTestJSON):
diff --git a/tempest/api_schema/response/compute/v2_1/aggregates.py b/tempest/api_schema/response/compute/v2_1/aggregates.py
deleted file mode 100644
index 1a9fe41..0000000
--- a/tempest/api_schema/response/compute/v2_1/aggregates.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright 2014 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import copy
-
-# create-aggregate api doesn't have 'hosts' and 'metadata' attributes.
-aggregate_for_create = {
- 'type': 'object',
- 'properties': {
- 'availability_zone': {'type': ['string', 'null']},
- 'created_at': {'type': 'string'},
- 'deleted': {'type': 'boolean'},
- 'deleted_at': {'type': ['string', 'null']},
- 'id': {'type': 'integer'},
- 'name': {'type': 'string'},
- 'updated_at': {'type': ['string', 'null']}
- },
- 'additionalProperties': False,
- 'required': ['availability_zone', 'created_at', 'deleted',
- 'deleted_at', 'id', 'name', 'updated_at'],
-}
-
-common_aggregate_info = copy.deepcopy(aggregate_for_create)
-common_aggregate_info['properties'].update({
- 'hosts': {'type': 'array'},
- 'metadata': {'type': 'object'}
-})
-common_aggregate_info['required'].extend(['hosts', 'metadata'])
-
-list_aggregates = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'aggregates': {
- 'type': 'array',
- 'items': common_aggregate_info
- }
- },
- 'additionalProperties': False,
- 'required': ['aggregates'],
- }
-}
-
-get_aggregate = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'aggregate': common_aggregate_info
- },
- 'additionalProperties': False,
- 'required': ['aggregate'],
- }
-}
-
-aggregate_set_metadata = get_aggregate
-# The 'updated_at' attribute of 'update_aggregate' can't be null.
-update_aggregate = copy.deepcopy(get_aggregate)
-update_aggregate['response_body']['properties']['aggregate']['properties'][
- 'updated_at'] = {
- 'type': 'string'
- }
-
-delete_aggregate = {
- 'status_code': [200]
-}
-
-create_aggregate = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'aggregate': aggregate_for_create
- },
- 'additionalProperties': False,
- 'required': ['aggregate'],
- }
-}
-
-aggregate_add_remove_host = get_aggregate
diff --git a/tempest/api_schema/response/compute/v2_1/availability_zone.py b/tempest/api_schema/response/compute/v2_1/availability_zone.py
deleted file mode 100644
index d9aebce..0000000
--- a/tempest/api_schema/response/compute/v2_1/availability_zone.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2014 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import copy
-
-
-base = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'availabilityZoneInfo': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'zoneName': {'type': 'string'},
- 'zoneState': {
- 'type': 'object',
- 'properties': {
- 'available': {'type': 'boolean'}
- },
- 'additionalProperties': False,
- 'required': ['available']
- },
- # NOTE: Here is the difference between detail and
- # non-detail.
- 'hosts': {'type': 'null'}
- },
- 'additionalProperties': False,
- 'required': ['zoneName', 'zoneState', 'hosts']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['availabilityZoneInfo']
- }
-}
-
-detail = {
- 'type': 'object',
- 'patternProperties': {
- # NOTE: Here is for a hostname
- '^[a-zA-Z0-9-_.]+$': {
- 'type': 'object',
- 'patternProperties': {
- # NOTE: Here is for a service name
- '^.*$': {
- 'type': 'object',
- 'properties': {
- 'available': {'type': 'boolean'},
- 'active': {'type': 'boolean'},
- 'updated_at': {'type': ['string', 'null']}
- },
- 'additionalProperties': False,
- 'required': ['available', 'active', 'updated_at']
- }
- }
- }
- }
-}
-
-list_availability_zone_list = copy.deepcopy(base)
-
-list_availability_zone_list_detail = copy.deepcopy(base)
-list_availability_zone_list_detail['response_body']['properties'][
- 'availabilityZoneInfo']['items']['properties']['hosts'] = detail
diff --git a/tempest/api_schema/response/compute/v2_1/baremetal_nodes.py b/tempest/api_schema/response/compute/v2_1/baremetal_nodes.py
deleted file mode 100644
index d1ee877..0000000
--- a/tempest/api_schema/response/compute/v2_1/baremetal_nodes.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# 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.
-
-import copy
-
-node = {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'interfaces': {'type': 'array'},
- 'host': {'type': 'string'},
- 'task_state': {'type': ['string', 'null']},
- 'cpus': {'type': ['integer', 'string']},
- 'memory_mb': {'type': ['integer', 'string']},
- 'disk_gb': {'type': ['integer', 'string']},
- },
- 'additionalProperties': False,
- 'required': ['id', 'interfaces', 'host', 'task_state', 'cpus', 'memory_mb',
- 'disk_gb']
-}
-
-list_baremetal_nodes = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'nodes': {
- 'type': 'array',
- 'items': node
- }
- },
- 'additionalProperties': False,
- 'required': ['nodes']
- }
-}
-
-baremetal_node = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'node': node
- },
- 'additionalProperties': False,
- 'required': ['node']
- }
-}
-get_baremetal_node = copy.deepcopy(baremetal_node)
-get_baremetal_node['response_body']['properties']['node'][
- 'properties'].update({'instance_uuid': {'type': ['string', 'null']}})
-get_baremetal_node['response_body']['properties']['node'][
- 'required'].append('instance_uuid')
diff --git a/tempest/api_schema/response/compute/v2_1/certificates.py b/tempest/api_schema/response/compute/v2_1/certificates.py
deleted file mode 100644
index 4e7cbe4..0000000
--- a/tempest/api_schema/response/compute/v2_1/certificates.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2014 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import copy
-
-_common_schema = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'certificate': {
- 'type': 'object',
- 'properties': {
- 'data': {'type': 'string'},
- 'private_key': {'type': 'string'},
- },
- 'additionalProperties': False,
- 'required': ['data', 'private_key']
- }
- },
- 'additionalProperties': False,
- 'required': ['certificate']
- }
-}
-
-get_certificate = copy.deepcopy(_common_schema)
-get_certificate['response_body']['properties']['certificate'][
- 'properties']['private_key'].update({'type': 'null'})
-
-create_certificate = copy.deepcopy(_common_schema)
diff --git a/tempest/api_schema/response/compute/v2_1/extensions.py b/tempest/api_schema/response/compute/v2_1/extensions.py
deleted file mode 100644
index a6a455c..0000000
--- a/tempest/api_schema/response/compute/v2_1/extensions.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright 2014 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.
-
-list_extensions = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'extensions': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'updated': {
- 'type': 'string',
- 'format': 'data-time'
- },
- 'name': {'type': 'string'},
- 'links': {'type': 'array'},
- 'namespace': {
- 'type': 'string',
- 'format': 'uri'
- },
- 'alias': {'type': 'string'},
- 'description': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['updated', 'name', 'links', 'namespace',
- 'alias', 'description']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['extensions']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/fixed_ips.py b/tempest/api_schema/response/compute/v2_1/fixed_ips.py
deleted file mode 100644
index 3586b70..0000000
--- a/tempest/api_schema/response/compute/v2_1/fixed_ips.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2014 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.api_schema.response.compute.v2_1 import parameter_types
-
-get_fixed_ip = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'fixed_ip': {
- 'type': 'object',
- 'properties': {
- 'address': parameter_types.ip_address,
- 'cidr': {'type': 'string'},
- 'host': {'type': 'string'},
- 'hostname': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['address', 'cidr', 'host', 'hostname']
- }
- },
- 'additionalProperties': False,
- 'required': ['fixed_ip']
- }
-}
-
-reserve_fixed_ip = {
- 'status_code': [202],
- 'response_body': {'type': 'string'}
-}
diff --git a/tempest/api_schema/response/compute/v2_1/flavors.py b/tempest/api_schema/response/compute/v2_1/flavors.py
deleted file mode 100644
index 5f5b2e3..0000000
--- a/tempest/api_schema/response/compute/v2_1/flavors.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright 2014 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.api_schema.response.compute.v2_1 import parameter_types
-
-list_flavors = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'flavors': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'name': {'type': 'string'},
- 'links': parameter_types.links,
- 'id': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['name', 'links', 'id']
- }
- },
- 'flavors_links': parameter_types.links
- },
- 'additionalProperties': False,
- # NOTE(gmann): flavors_links attribute is not necessary
- # to be present always So it is not 'required'.
- 'required': ['flavors']
- }
-}
-
-common_flavor_info = {
- 'type': 'object',
- 'properties': {
- 'name': {'type': 'string'},
- 'links': parameter_types.links,
- 'ram': {'type': 'integer'},
- 'vcpus': {'type': 'integer'},
- # 'swap' attributes comes as integer value but if it is empty
- # it comes as "". So defining type of as string and integer.
- 'swap': {'type': ['integer', 'string']},
- 'disk': {'type': 'integer'},
- 'id': {'type': 'string'},
- 'OS-FLV-DISABLED:disabled': {'type': 'boolean'},
- 'os-flavor-access:is_public': {'type': 'boolean'},
- 'rxtx_factor': {'type': 'number'},
- 'OS-FLV-EXT-DATA:ephemeral': {'type': 'integer'}
- },
- 'additionalProperties': False,
- # 'OS-FLV-DISABLED', 'os-flavor-access', 'rxtx_factor' and
- # 'OS-FLV-EXT-DATA' are API extensions. So they are not 'required'.
- 'required': ['name', 'links', 'ram', 'vcpus', 'swap', 'disk', 'id']
-}
-
-list_flavors_details = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'flavors': {
- 'type': 'array',
- 'items': common_flavor_info
- },
- # NOTE(gmann): flavors_links attribute is not necessary
- # to be present always So it is not 'required'.
- 'flavors_links': parameter_types.links
- },
- 'additionalProperties': False,
- 'required': ['flavors']
- }
-}
-
-unset_flavor_extra_specs = {
- 'status_code': [200]
-}
-
-create_get_flavor_details = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'flavor': common_flavor_info
- },
- 'additionalProperties': False,
- 'required': ['flavor']
- }
-}
-
-delete_flavor = {
- 'status_code': [202]
-}
diff --git a/tempest/api_schema/response/compute/v2_1/flavors_access.py b/tempest/api_schema/response/compute/v2_1/flavors_access.py
deleted file mode 100644
index a4d6af0..0000000
--- a/tempest/api_schema/response/compute/v2_1/flavors_access.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2014 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.
-
-add_remove_list_flavor_access = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'flavor_access': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'flavor_id': {'type': 'string'},
- 'tenant_id': {'type': 'string'},
- },
- 'additionalProperties': False,
- 'required': ['flavor_id', 'tenant_id'],
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['flavor_access']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py b/tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
deleted file mode 100644
index a438d48..0000000
--- a/tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2014 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.
-
-set_get_flavor_extra_specs = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'extra_specs': {
- 'type': 'object',
- 'patternProperties': {
- '^[a-zA-Z0-9_\-\. :]+$': {'type': 'string'}
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['extra_specs']
- }
-}
-
-set_get_flavor_extra_specs_key = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'patternProperties': {
- '^[a-zA-Z0-9_\-\. :]+$': {'type': 'string'}
- }
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/hosts.py b/tempest/api_schema/response/compute/v2_1/hosts.py
deleted file mode 100644
index ae70ff1..0000000
--- a/tempest/api_schema/response/compute/v2_1/hosts.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright 2014 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import copy
-
-
-list_hosts = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hosts': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'host_name': {'type': 'string'},
- 'service': {'type': 'string'},
- 'zone': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['host_name', 'service', 'zone']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['hosts']
- }
-}
-
-get_host_detail = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'host': {
- 'type': 'array',
- 'item': {
- 'type': 'object',
- 'properties': {
- 'resource': {
- 'type': 'object',
- 'properties': {
- 'cpu': {'type': 'integer'},
- 'disk_gb': {'type': 'integer'},
- 'host': {'type': 'string'},
- 'memory_mb': {'type': 'integer'},
- 'project': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['cpu', 'disk_gb', 'host',
- 'memory_mb', 'project']
- }
- },
- 'additionalProperties': False,
- 'required': ['resource']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['host']
- }
-}
-
-startup_host = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'host': {'type': 'string'},
- 'power_action': {'enum': ['startup']}
- },
- 'additionalProperties': False,
- 'required': ['host', 'power_action']
- }
-}
-
-# The 'power_action' attribute of 'shutdown_host' API is 'shutdown'
-shutdown_host = copy.deepcopy(startup_host)
-
-shutdown_host['response_body']['properties']['power_action'] = {
- 'enum': ['shutdown']
-}
-
-# The 'power_action' attribute of 'reboot_host' API is 'reboot'
-reboot_host = copy.deepcopy(startup_host)
-
-reboot_host['response_body']['properties']['power_action'] = {
- 'enum': ['reboot']
-}
-
-update_host = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'host': {'type': 'string'},
- 'maintenance_mode': {'enum': ['on_maintenance',
- 'off_maintenance']},
- 'status': {'enum': ['enabled', 'disabled']}
- },
- 'additionalProperties': False,
- 'required': ['host', 'maintenance_mode', 'status']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/hypervisors.py b/tempest/api_schema/response/compute/v2_1/hypervisors.py
deleted file mode 100644
index 05901b6..0000000
--- a/tempest/api_schema/response/compute/v2_1/hypervisors.py
+++ /dev/null
@@ -1,195 +0,0 @@
-# Copyright 2014 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import copy
-
-from tempest.api_schema.response.compute.v2_1 import parameter_types
-
-get_hypervisor_statistics = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisor_statistics': {
- 'type': 'object',
- 'properties': {
- 'count': {'type': 'integer'},
- 'current_workload': {'type': 'integer'},
- 'disk_available_least': {'type': ['integer', 'null']},
- 'free_disk_gb': {'type': 'integer'},
- 'free_ram_mb': {'type': 'integer'},
- 'local_gb': {'type': 'integer'},
- 'local_gb_used': {'type': 'integer'},
- 'memory_mb': {'type': 'integer'},
- 'memory_mb_used': {'type': 'integer'},
- 'running_vms': {'type': 'integer'},
- 'vcpus': {'type': 'integer'},
- 'vcpus_used': {'type': 'integer'}
- },
- 'additionalProperties': False,
- 'required': ['count', 'current_workload',
- 'disk_available_least', 'free_disk_gb',
- 'free_ram_mb', 'local_gb', 'local_gb_used',
- 'memory_mb', 'memory_mb_used', 'running_vms',
- 'vcpus', 'vcpus_used']
- }
- },
- 'additionalProperties': False,
- 'required': ['hypervisor_statistics']
- }
-}
-
-
-hypervisor_detail = {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'state': {'type': 'string'},
- 'cpu_info': {'type': 'string'},
- 'current_workload': {'type': 'integer'},
- 'disk_available_least': {'type': ['integer', 'null']},
- 'host_ip': parameter_types.ip_address,
- 'free_disk_gb': {'type': 'integer'},
- 'free_ram_mb': {'type': 'integer'},
- 'hypervisor_hostname': {'type': 'string'},
- 'hypervisor_type': {'type': 'string'},
- 'hypervisor_version': {'type': 'integer'},
- 'id': {'type': ['integer', 'string']},
- 'local_gb': {'type': 'integer'},
- 'local_gb_used': {'type': 'integer'},
- 'memory_mb': {'type': 'integer'},
- 'memory_mb_used': {'type': 'integer'},
- 'running_vms': {'type': 'integer'},
- 'service': {
- 'type': 'object',
- 'properties': {
- 'host': {'type': 'string'},
- 'id': {'type': ['integer', 'string']},
- 'disabled_reason': {'type': ['string', 'null']}
- },
- 'additionalProperties': False,
- 'required': ['host', 'id']
- },
- 'vcpus': {'type': 'integer'},
- 'vcpus_used': {'type': 'integer'}
- },
- 'additionalProperties': False,
- # NOTE: When loading os-hypervisor-status extension,
- # a response contains status and state. So these params
- # should not be required.
- 'required': ['cpu_info', 'current_workload',
- 'disk_available_least', 'host_ip',
- 'free_disk_gb', 'free_ram_mb',
- 'hypervisor_hostname', 'hypervisor_type',
- 'hypervisor_version', 'id', 'local_gb',
- 'local_gb_used', 'memory_mb', 'memory_mb_used',
- 'running_vms', 'service', 'vcpus', 'vcpus_used']
-}
-
-list_hypervisors_detail = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisors': {
- 'type': 'array',
- 'items': hypervisor_detail
- }
- },
- 'additionalProperties': False,
- 'required': ['hypervisors']
- }
-}
-
-get_hypervisor = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisor': hypervisor_detail
- },
- 'additionalProperties': False,
- 'required': ['hypervisor']
- }
-}
-
-list_search_hypervisors = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisors': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'state': {'type': 'string'},
- 'id': {'type': ['integer', 'string']},
- 'hypervisor_hostname': {'type': 'string'}
- },
- 'additionalProperties': False,
- # NOTE: When loading os-hypervisor-status extension,
- # a response contains status and state. So these params
- # should not be required.
- 'required': ['id', 'hypervisor_hostname']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['hypervisors']
- }
-}
-
-get_hypervisor_uptime = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisor': {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'state': {'type': 'string'},
- 'id': {'type': ['integer', 'string']},
- 'hypervisor_hostname': {'type': 'string'},
- 'uptime': {'type': 'string'}
- },
- 'additionalProperties': False,
- # NOTE: When loading os-hypervisor-status extension,
- # a response contains status and state. So these params
- # should not be required.
- 'required': ['id', 'hypervisor_hostname', 'uptime']
- }
- },
- 'additionalProperties': False,
- 'required': ['hypervisor']
- }
-}
-
-get_hypervisors_servers = copy.deepcopy(list_search_hypervisors)
-get_hypervisors_servers['response_body']['properties']['hypervisors']['items'][
- 'properties']['servers'] = {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'uuid': {'type': 'string'},
- 'name': {'type': 'string'}
- },
- 'additionalProperties': False,
- }
- }
-# In V2 API, if there is no servers (VM) on the Hypervisor host then 'servers'
-# attribute will not be present in response body So it is not 'required'.
diff --git a/tempest/api_schema/response/compute/v2_1/services.py b/tempest/api_schema/response/compute/v2_1/services.py
index c2c7a51..ddef7b2 100644
--- a/tempest/api_schema/response/compute/v2_1/services.py
+++ b/tempest/api_schema/response/compute/v2_1/services.py
@@ -43,7 +43,7 @@
}
}
-enable_service = {
+enable_disable_service = {
'status_code': [200],
'response_body': {
'type': 'object',
diff --git a/tempest/clients.py b/tempest/clients.py
index 2756fa8..84e8544 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -16,6 +16,25 @@
import copy
from oslo_log import log as logging
+from tempest_lib.services.compute.agents_client import AgentsClient
+from tempest_lib.services.compute.aggregates_client import AggregatesClient
+from tempest_lib.services.compute.availability_zone_client import \
+ AvailabilityZoneClient
+from tempest_lib.services.compute.baremetal_nodes_client import \
+ BaremetalNodesClient
+from tempest_lib.services.compute.certificates_client import \
+ CertificatesClient
+from tempest_lib.services.compute.extensions_client import \
+ ExtensionsClient
+from tempest_lib.services.compute.fixed_ips_client import FixedIPsClient
+from tempest_lib.services.compute.flavors_client import FlavorsClient
+from tempest_lib.services.compute.floating_ip_pools_client import \
+ FloatingIPPoolsClient
+from tempest_lib.services.compute.floating_ips_bulk_client import \
+ FloatingIPsBulkClient
+from tempest_lib.services.compute.hosts_client import HostsClient
+from tempest_lib.services.compute.hypervisor_client import \
+ HypervisorClient
from tempest_lib.services.identity.v2.token_client import TokenClient
from tempest_lib.services.identity.v3.token_client import V3TokenClient
@@ -27,29 +46,8 @@
from tempest.services.baremetal.v1.json.baremetal_client import \
BaremetalClient
from tempest.services import botoclients
-from tempest.services.compute.json.agents_client import \
- AgentsClient
-from tempest.services.compute.json.aggregates_client import \
- AggregatesClient
-from tempest.services.compute.json.availability_zone_client import \
- AvailabilityZoneClient
-from tempest.services.compute.json.baremetal_nodes_client import \
- BaremetalNodesClient
-from tempest.services.compute.json.certificates_client import \
- CertificatesClient
-from tempest.services.compute.json.extensions_client import \
- ExtensionsClient
-from tempest.services.compute.json.fixed_ips_client import FixedIPsClient
-from tempest.services.compute.json.flavors_client import FlavorsClient
-from tempest.services.compute.json.floating_ip_pools_client import \
- FloatingIPPoolsClient
-from tempest.services.compute.json.floating_ips_bulk_client import \
- FloatingIPsBulkClient
from tempest.services.compute.json.floating_ips_client import \
FloatingIPsClient
-from tempest.services.compute.json.hosts_client import HostsClient
-from tempest.services.compute.json.hypervisor_client import \
- HypervisorClient
from tempest.services.compute.json.images_client import ImagesClient
from tempest.services.compute.json.instance_usage_audit_log_client import \
InstanceUsagesAuditLogClient
@@ -74,15 +72,15 @@
ServerGroupsClient
from tempest.services.compute.json.servers_client import ServersClient
from tempest.services.compute.json.services_client import ServicesClient
-from tempest.services.compute.json.snapshots_extensions_client import \
- SnapshotsExtensionsClient
+from tempest.services.compute.json.snapshots_client import \
+ SnapshotsClient as ComputeSnapshotsClient
from tempest.services.compute.json.tenant_networks_client import \
TenantNetworksClient
from tempest.services.compute.json.tenant_usages_client import \
TenantUsagesClient
from tempest.services.compute.json.versions_client import VersionsClient
-from tempest.services.compute.json.volumes_extensions_client import \
- VolumesExtensionsClient
+from tempest.services.compute.json.volumes_client import \
+ VolumesClient as ComputeVolumesClient
from tempest.services.data_processing.v1_1.data_processing_client import \
DataProcessingClient
from tempest.services.database.json.flavors_client import \
@@ -108,6 +106,8 @@
from tempest.services.messaging.json.messaging_client import \
MessagingClient
from tempest.services.network.json.network_client import NetworkClient
+from tempest.services.network.json.networks_client import NetworksClient
+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
from tempest.services.object_storage.object_client import ObjectClient
@@ -197,6 +197,22 @@
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**self.default_params)
+ self.networks_client = NetworksClient(
+ 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,
+ 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.messaging_client = MessagingClient(
self.auth_provider,
CONF.messaging.catalog_type,
@@ -325,11 +341,11 @@
'build_interval': CONF.volume.build_interval,
'build_timeout': CONF.volume.build_timeout
})
- self.volumes_extensions_client = VolumesExtensionsClient(
+ self.volumes_extensions_client = ComputeVolumesClient(
self.auth_provider, **params_volume)
self.compute_versions_client = VersionsClient(self.auth_provider,
**params_volume)
- self.snapshots_extensions_client = SnapshotsExtensionsClient(
+ self.snapshots_extensions_client = ComputeSnapshotsClient(
self.auth_provider, **params_volume)
def _set_database_clients(self):
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index ce7728e..a90b0ce 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -93,6 +93,8 @@
from tempest import exceptions as exc
from tempest.services.identity.v2.json import identity_client
from tempest.services.network.json import network_client
+from tempest.services.network.json import networks_client
+from tempest.services.network.json import subnets_client
import tempest_lib.auth
from tempest_lib.common.utils import data_utils
import tempest_lib.exceptions
@@ -136,20 +138,38 @@
**params
)
network_admin = None
+ networks_admin = None
+ subnets_admin = None
+ neutron_iso_networks = False
if (CONF.service_available.neutron and
CONF.auth.create_isolated_networks):
+ neutron_iso_networks = True
network_admin = network_client.NetworkClient(
_auth,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type='adminURL',
**params)
- return identity_admin, network_admin
+ networks_admin = networks_client.NetworksClient(
+ _auth,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type='adminURL',
+ **params)
+ subnets_admin = subnets_client.SubnetsClient(
+ _auth,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type='adminURL',
+ **params)
+ return (identity_admin, neutron_iso_networks, network_admin,
+ networks_admin, subnets_admin)
def create_resources(opts, resources):
- identity_admin, network_admin = get_admin_clients(opts)
- roles = identity_admin.list_roles()
+ (identity_admin, neutron_iso_networks,
+ network_admin, networks_admin, subnets_admin) = get_admin_clients(opts)
+ roles = identity_admin.list_roles()['roles']
for u in resources['users']:
u['role_ids'] = []
for r in u.get('roles', ()):
@@ -187,12 +207,12 @@
u['name'] = random_user_name(opts.tag, u['prefix'])
LOG.info('Users created')
- if network_admin:
+ if neutron_iso_networks:
for u in resources['users']:
tenant = identity_admin.get_tenant_by_name(u['tenant'])
- network_name, router_name = create_network_resources(network_admin,
- tenant['id'],
- u['name'])
+ network_name, router_name = create_network_resources(
+ network_admin, networks_admin, subnets_admin, tenant['id'],
+ u['name'])
u['network'] = network_name
u['router'] = router_name
LOG.info('Networks created')
@@ -218,10 +238,11 @@
LOG.info('Resources deployed successfully!')
-def create_network_resources(network_admin_client, tenant_id, name):
+def create_network_resources(network_admin_client, networks_admin_client,
+ subnets_admin_client, tenant_id, name):
def _create_network(name):
- resp_body = network_admin_client.create_network(
+ resp_body = networks_admin_client.create_network(
name=name, tenant_id=tenant_id)
return resp_body['network']
@@ -230,7 +251,7 @@
mask_bits = CONF.network.tenant_network_mask_bits
for subnet_cidr in base_cidr.subnet(mask_bits):
try:
- resp_body = network_admin_client.\
+ resp_body = subnets_admin_client.\
create_subnet(
network_id=network_id, cidr=str(subnet_cidr),
name=subnet_name,
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 6d4e3a9..64e1303 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -83,7 +83,7 @@
def _get_network_id(net_name, tenant_name):
am = clients.AdminManager()
- net_cl = am.network_client
+ net_cl = am.networks_client
id_cl = am.identity_client
networks = net_cl.list_networks()
@@ -381,6 +381,8 @@
def __init__(self, manager, **kwargs):
super(NetworkService, self).__init__(kwargs)
self.client = manager.network_client
+ self.networks_client = manager.networks_client
+ self.subnets_client = manager.subnets_client
def _filter_by_conf_networks(self, item_list):
if not item_list or not all(('network_id' in i for i in item_list)):
@@ -390,7 +392,7 @@
not in CONF_NETWORKS]
def list(self):
- client = self.client
+ client = self.networks_client
networks = client.list_networks(**self.tenant_filter)
networks = networks['networks']
# filter out networks declared in tempest.conf
@@ -401,7 +403,7 @@
return networks
def delete(self):
- client = self.client
+ client = self.networks_client
networks = self.list()
for n in networks:
try:
@@ -675,7 +677,7 @@
class NetworkSubnetService(NetworkService):
def list(self):
- client = self.client
+ client = self.subnets_client
subnets = client.list_subnets(**self.tenant_filter)
subnets = subnets['subnets']
if self.is_preserve:
@@ -684,7 +686,7 @@
return subnets
def delete(self):
- client = self.client
+ client = self.subnets_client
subnets = self.list()
for subnet in subnets:
try:
diff --git a/tempest/cmd/init.py b/tempest/cmd/init.py
index 289b978..af8f270 100644
--- a/tempest/cmd/init.py
+++ b/tempest/cmd/init.py
@@ -52,17 +52,21 @@
real_prefix = getattr(sys, 'real_prefix', None)
base_prefix = getattr(sys, 'base_prefix', None)
prefix = sys.prefix
- if real_prefix is None and base_prefix is None:
- # Not running in a virtual environnment of any kind
- return '/etc/tempest'
- elif (real_prefix is None and base_prefix is not None and
- base_prefix == prefix):
- # Probably not running in a virtual environment
+ if (real_prefix is None and
+ (base_prefix is None or base_prefix == prefix)):
+ # Probably not running in a virtual environment.
# NOTE(andreaf) we cannot distinguish this case from the case of
# a virtual environment created with virtualenv, and running python3.
- return '/etc/tempest'
+ # Also if it appears we are not in virtual env and fail to find
+ # global config: '/etc/tempest', fall back to
+ # '[sys.prefix]/etc/tempest'
+ global_conf_dir = '/etc/tempest'
+ if os.path.isdir(global_conf_dir):
+ return global_conf_dir
+ else:
+ return os.path.join(prefix, 'etc/tempest')
else:
- return os.path.join(sys.prefix, 'etc/tempest')
+ return os.path.join(prefix, 'etc/tempest')
class TempestInit(command.Command):
@@ -99,9 +103,12 @@
def copy_config(self, etc_dir, config_dir):
shutil.copytree(config_dir, etc_dir)
- def generate_sample_config(self, local_dir):
+ def generate_sample_config(self, local_dir, config_dir):
+ conf_generator = os.path.join(config_dir,
+ 'config-generator.tempest.conf')
+
subprocess.call(['oslo-config-generator', '--config-file',
- 'tools/config/config-generator.tempest.conf'],
+ conf_generator],
cwd=local_dir)
def create_working_dir(self, local_dir, config_dir):
@@ -109,6 +116,10 @@
if not os.path.isdir(local_dir):
LOG.debug('Creating local working dir: %s' % local_dir)
os.mkdir(local_dir)
+ else:
+ raise OSError("Directory you are trying to initialize already "
+ "exists: %s" % local_dir)
+
lock_dir = os.path.join(local_dir, 'tempest_lock')
etc_dir = os.path.join(local_dir, 'etc')
config_path = os.path.join(etc_dir, 'tempest.conf')
@@ -125,7 +136,7 @@
# Create and copy local etc dir
self.copy_config(etc_dir, config_dir)
# Generate the sample config file
- self.generate_sample_config(local_dir)
+ self.generate_sample_config(local_dir, config_dir)
# Update local confs to reflect local paths
self.update_local_conf(config_path, lock_dir, log_dir)
# Generate a testr conf file
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 5d06b90..f57e757 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -117,11 +117,11 @@
import six
from tempest_lib import auth
from tempest_lib import exceptions as lib_exc
+from tempest_lib.services.compute import flavors_client
import yaml
from tempest.common import waiters
from tempest import config
-from tempest.services.compute.json import flavors_client
from tempest.services.compute.json import floating_ips_client
from tempest.services.compute.json import security_group_rules_client
from tempest.services.compute.json import security_groups_client
@@ -129,6 +129,7 @@
from tempest.services.identity.v2.json import identity_client
from tempest.services.image.v2.json import image_client
from tempest.services.network.json import network_client
+from tempest.services.network.json import subnets_client
from tempest.services.object_storage import container_client
from tempest.services.object_storage import object_client
from tempest.services.telemetry.json import telemetry_client
@@ -240,6 +241,14 @@
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**default_params)
+ self.subnets = subnets_client.SubnetsClient(
+ _auth,
+ 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,
+ **default_params)
def load_resources(fname):
@@ -278,7 +287,7 @@
existing = [x['name'] for x in body]
for tenant in tenants:
if tenant not in existing:
- admin.identity.create_tenant(tenant)
+ admin.identity.create_tenant(tenant)['tenant']
else:
LOG.warn("Tenant '%s' already exists in this environment" % tenant)
@@ -423,7 +432,7 @@
LOG.info("checking users")
for name, user in six.iteritems(self.users):
client = keystone_admin()
- found = client.identity.get_user(user['id'])
+ found = client.identity.get_user(user['id'])['user']
self.assertEqual(found['name'], user['name'])
self.assertEqual(found['tenantId'], user['tenant_id'])
@@ -769,9 +778,9 @@
LOG.info("Destroying subnets")
for subnet in subnets:
client = client_for_user(subnet['owner'])
- subnet_id = _get_resource_by_name(client.networks,
+ subnet_id = _get_resource_by_name(client.subnets,
'subnets', subnet['name'])['id']
- client.networks.delete_subnet(subnet_id)
+ client.subnets.delete_subnet(subnet_id)
def create_routers(routers):
@@ -869,7 +878,8 @@
kwargs['networks'] = [{'uuid': get_net_id(network)}
for network in server['networks']]
body = client.servers.create_server(
- server['name'], image_id, flavor_id, **kwargs)['server']
+ name=server['name'], imageRef=image_id, flavorRef=flavor_id,
+ **kwargs)['server']
server_id = body['id']
client.servers.wait_for_server_status(server_id, 'ACTIVE')
# create security group(s) after server spawning
diff --git a/tempest/cmd/main.py b/tempest/cmd/main.py
index 762e982..577df9b 100644
--- a/tempest/cmd/main.py
+++ b/tempest/cmd/main.py
@@ -16,8 +16,7 @@
from cliff import app
from cliff import commandmanager
-
-TEMPEST_CLI_VERSION = '0.1'
+from pbr import version
class Main(app.App):
@@ -27,7 +26,7 @@
def __init__(self):
super(Main, self).__init__(
description='Tempest cli application',
- version=TEMPEST_CLI_VERSION,
+ version=version.VersionInfo('tempest').version_string(),
command_manager=commandmanager.CommandManager('tempest.cm'),
)
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 6d53b59..2811070 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -65,10 +65,10 @@
# Check glance api versions
_, versions = os.image_client.get_versions()
if CONF.image_feature_enabled.api_v1 != contains_version('v1.', versions):
- print_and_or_update('api_v1', 'image_feature_enabled',
+ print_and_or_update('api_v1', 'image-feature-enabled',
not CONF.image_feature_enabled.api_v1, update)
if CONF.image_feature_enabled.api_v2 != contains_version('v2.', versions):
- print_and_or_update('api_v2', 'image_feature_enabled',
+ print_and_or_update('api_v2', 'image-feature-enabled',
not CONF.image_feature_enabled.api_v2, update)
@@ -105,11 +105,11 @@
versions = _get_api_versions(os, 'keystone')
if (CONF.identity_feature_enabled.api_v2 !=
contains_version('v2.', versions)):
- print_and_or_update('api_v2', 'identity_feature_enabled',
+ print_and_or_update('api_v2', 'identity-feature-enabled',
not CONF.identity_feature_enabled.api_v2, update)
if (CONF.identity_feature_enabled.api_v3 !=
contains_version('v3.', versions)):
- print_and_or_update('api_v3', 'identity_feature_enabled',
+ print_and_or_update('api_v3', 'identity-feature-enabled',
not CONF.identity_feature_enabled.api_v3, update)
@@ -118,11 +118,11 @@
versions = _get_api_versions(os, 'cinder')
if (CONF.volume_feature_enabled.api_v1 !=
contains_version('v1.', versions)):
- print_and_or_update('api_v1', 'volume_feature_enabled',
+ print_and_or_update('api_v1', 'volume-feature-enabled',
not CONF.volume_feature_enabled.api_v1, update)
if (CONF.volume_feature_enabled.api_v2 !=
contains_version('v2.', versions)):
- print_and_or_update('api_v2', 'volume_feature_enabled',
+ print_and_or_update('api_v2', 'volume-feature-enabled',
not CONF.volume_feature_enabled.api_v2, update)
@@ -348,7 +348,7 @@
CONF_PARSER = moves.configparser.SafeConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
- icreds = credentials.get_isolated_credentials('verify_tempest_config')
+ icreds = credentials.get_credentials_provider('verify_tempest_config')
try:
os = clients.Manager(icreds.get_primary_creds())
services = check_service_availability(os, update)
@@ -370,7 +370,7 @@
CONF_PARSER.write(outfile)
outfile.close()
finally:
- icreds.clear_isolated_creds()
+ icreds.clear_creds()
if __name__ == "__main__":
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index a76696e..41b0529 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -28,19 +28,21 @@
def create_test_server(clients, validatable=False, validation_resources=None,
- tenant_network=None, wait_until=None, **kwargs):
+ tenant_network=None, wait_until=None,
+ volume_backed=False, **kwargs):
"""Common wrapper utility returning a test server.
This method is a common wrapper returning a test server that can be
pingable or sshable.
- :param clients: Client manager which provides Openstack Tempest clients.
+ :param clients: Client manager which provides OpenStack Tempest clients.
:param validatable: Whether the server will be pingable or sshable.
:param validation_resources: Resources created for the connection to the
server. Include a keypair, a security group and an IP.
:param tenant_network: Tenant network to be used for creating a server.
:param wait_until: Server status to wait for the server to reach after
its creation.
+ :param volume_backed: Whether the instance is volume backed or not.
:returns a tuple
"""
@@ -51,8 +53,8 @@
else:
name = data_utils.rand_name(__name__ + "-instance")
- flavor = kwargs.get('flavor', CONF.compute.flavor_ref)
- image_id = kwargs.get('image_id', CONF.compute.image_ref)
+ flavor = kwargs.pop('flavor', CONF.compute.flavor_ref)
+ image_id = kwargs.pop('image_id', CONF.compute.image_ref)
kwargs = fixed_network.set_networks_kwarg(
tenant_network, kwargs) or {}
@@ -85,7 +87,31 @@
if wait_until is None:
wait_until = 'ACTIVE'
- body = clients.servers_client.create_server(name, image_id, flavor,
+ if volume_backed:
+ volume_name = data_utils.rand_name('volume')
+ volumes_client = clients.volumes_v2_client
+ if CONF.volume_feature_enabled.api_v1:
+ volumes_client = clients.volumes_client
+ volume = volumes_client.create_volume(
+ display_name=volume_name,
+ imageRef=image_id)
+ volumes_client.wait_for_volume_status(volume['volume']['id'],
+ 'available')
+
+ bd_map_v2 = [{
+ 'uuid': volume['volume']['id'],
+ 'source_type': 'volume',
+ 'destination_type': 'volume',
+ 'boot_index': 0,
+ 'delete_on_termination': True}]
+ kwargs['block_device_mapping_v2'] = bd_map_v2
+
+ # Since this is boot from volume an image does not need
+ # to be specified.
+ image_id = ''
+
+ body = clients.servers_client.create_server(name=name, imageRef=image_id,
+ flavorRef=flavor,
**kwargs)
# handle the case of multiple servers
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index 7c3a77f..79a502a 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -14,14 +14,11 @@
from oslo_log import log as logging
import six
+from tempest_lib import auth
from tempest_lib import exceptions as lib_exc
-from tempest.common import cred_provider
-from tempest import config
-from tempest import exceptions
from tempest.services.identity.v2.json import identity_client as v2_identity
-CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -36,7 +33,6 @@
def __init__(self, identity_client):
# The client implies version and credentials
self.identity_client = identity_client
- self.credentials = self.identity_client.auth_provider.credentials
def create_user(self, username, password, project, email):
user = self.identity_client.create_user(
@@ -75,13 +71,20 @@
@abc.abstractmethod
def get_credentials(self, user, project, password):
+ """Produces a Credentials object from the details provided
+
+ :param user: a user dict
+ :param project: a project dict
+ :param password: the password as a string
+ :return: a Credentials object with all the available credential details
+ """
pass
def delete_user(self, user_id):
self.identity_client.delete_user(user_id)
def _list_roles(self):
- roles = self.identity_client.list_roles()
+ roles = self.identity_client.list_roles()['roles']
return roles
@@ -89,11 +92,15 @@
def create_project(self, name, description):
tenant = self.identity_client.create_tenant(
- name=name, description=description)
+ name=name, description=description)['tenant']
return tenant
def get_credentials(self, user, project, password):
- return cred_provider.get_credentials(
+ # User and project already include both ID and name here,
+ # so there's no need to use the fill_in mode
+ return auth.get_credentials(
+ auth_url=None,
+ fill_in=False,
identity_version='v2',
username=user['name'], user_id=user['id'],
tenant_name=project['name'], tenant_id=project['id'],
@@ -114,8 +121,8 @@
params={'name': domain_name})['domains'][0]
except lib_exc.NotFound:
# TODO(andrea) we could probably create the domain on the fly
- msg = "Configured domain %s could not be found" % domain_name
- raise exceptions.InvalidConfiguration(msg)
+ msg = "Requested domain %s could not be found" % domain_name
+ raise lib_exc.InvalidCredentials(msg)
def create_project(self, name, description):
project = self.identity_client.create_project(
@@ -124,11 +131,16 @@
return project
def get_credentials(self, user, project, password):
- return cred_provider.get_credentials(
+ # User, project and domain already include both ID and name here,
+ # so there's no need to use the fill_in mode.
+ return auth.get_credentials(
+ auth_url=None,
+ fill_in=False,
identity_version='v3',
username=user['name'], user_id=user['id'],
project_name=project['name'], project_id=project['id'],
password=password,
+ project_domain_id=self.creds_domain['id'],
project_domain_name=self.creds_domain['name'])
def delete_project(self, project_id):
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 783a5fc..3575998 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -26,7 +26,7 @@
# Type of credentials available from configuration
CREDENTIAL_TYPES = {
- 'identity_admin': ('identity', 'admin'),
+ 'identity_admin': ('auth', 'admin'),
'user': ('identity', None),
'alt_user': ('identity', 'alt')
}
@@ -98,19 +98,22 @@
@six.add_metaclass(abc.ABCMeta)
class CredentialProvider(object):
- def __init__(self, identity_version=None, name=None,
- network_resources=None):
+ def __init__(self, identity_version, name=None, network_resources=None,
+ credentials_domain=None, admin_role=None):
"""A CredentialProvider supplies credentials to test classes.
- :param identity_version: If specified it will return credentials of the
- corresponding identity version, otherwise it
- uses auth_version from configuration
+ :param identity_version: Identity version of the credentials provided
:param name: Name of the calling test. Included in provisioned
credentials when credentials are provisioned on the fly
:param network_resources: Network resources required for the
credentials
+ :param credentials_domain: Domain credentials belong to
+ :param admin_role: Name of the role of the admin account
"""
+ self.identity_version = identity_version
self.name = name or "test_creds"
- self.identity_version = identity_version or CONF.identity.auth_version
+ self.network_resources = network_resources
+ self.credentials_domain = credentials_domain or 'Default'
+ self.admin_role = admin_role
if not auth.is_identity_version_supported(self.identity_version):
raise exceptions.InvalidIdentityVersion(
identity_version=self.identity_version)
@@ -128,7 +131,7 @@
return
@abc.abstractmethod
- def clear_isolated_creds(self):
+ def clear_creds(self):
return
@abc.abstractmethod
diff --git a/tempest/common/credentials.py b/tempest/common/credentials.py
index 71d905f..76f8afe 100644
--- a/tempest/common/credentials.py
+++ b/tempest/common/credentials.py
@@ -13,9 +13,9 @@
import os
-from tempest.common import accounts
from tempest.common import cred_provider
-from tempest.common import isolated_creds
+from tempest.common import dynamic_creds
+from tempest.common import preprov_creds
from tempest import config
from tempest import exceptions
@@ -25,47 +25,58 @@
# Return the right implementation of CredentialProvider based on config
# Dropping interface and password, as they are never used anyways
# TODO(andreaf) Drop them from the CredentialsProvider interface completely
-def get_isolated_credentials(name, network_resources=None,
+def get_credentials_provider(name, network_resources=None,
force_tenant_isolation=False,
identity_version=None):
# If a test requires a new account to work, it can have it via forcing
- # tenant isolation. A new account will be produced only for that test.
+ # dynamic credentials. A new account will be produced only for that test.
# In case admin credentials are not available for the account creation,
# the test should be skipped else it would fail.
- if CONF.auth.allow_tenant_isolation or force_tenant_isolation:
- return isolated_creds.IsolatedCreds(
+ identity_version = identity_version or CONF.identity.auth_version
+ if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
+ return dynamic_creds.DynamicCredentialProvider(
name=name,
network_resources=network_resources,
- identity_version=identity_version)
+ identity_version=identity_version,
+ credentials_domain=CONF.auth.default_credentials_domain_name,
+ admin_role=CONF.identity.admin_role)
else:
if (CONF.auth.test_accounts_file and
os.path.isfile(CONF.auth.test_accounts_file)):
# Most params are not relevant for pre-created accounts
- return accounts.Accounts(name=name,
- identity_version=identity_version)
+ return preprov_creds.PreProvisionedCredentialProvider(
+ name=name, identity_version=identity_version,
+ credentials_domain=CONF.auth.default_credentials_domain_name,
+ admin_role=CONF.identity.admin_role)
else:
- return accounts.NotLockingAccounts(
- name=name, identity_version=identity_version)
+ return preprov_creds.NonLockingCredentialProvider(
+ name=name, identity_version=identity_version,
+ admin_role=CONF.identity.admin_role)
# We want a helper function here to check and see if admin credentials
# are available so we can do a single call from skip_checks if admin
-# creds area vailable.
-def is_admin_available():
+# creds area available.
+# This depends on identity_version as there may be admin credentials
+# available for v2 but not for v3.
+def is_admin_available(identity_version):
is_admin = True
- # If tenant isolation is enabled admin will be available
- if CONF.auth.allow_tenant_isolation:
+ # If dynamic credentials is enabled admin will be available
+ if CONF.auth.use_dynamic_credentials:
return is_admin
# Check whether test accounts file has the admin specified or not
elif (CONF.auth.test_accounts_file and
os.path.isfile(CONF.auth.test_accounts_file)):
- check_accounts = accounts.Accounts(name='check_admin')
+ check_accounts = preprov_creds.PreProvisionedCredentialProvider(
+ identity_version=identity_version, name='check_admin',
+ admin_role=CONF.identity.admin_role)
if not check_accounts.admin_available():
is_admin = False
else:
try:
- cred_provider.get_configured_credentials('identity_admin',
- fill_in=False)
+ cred_provider.get_configured_credentials(
+ 'identity_admin', fill_in=False,
+ identity_version=identity_version)
except exceptions.InvalidConfiguration:
is_admin = False
return is_admin
@@ -73,17 +84,23 @@
# We want a helper function here to check and see if alt credentials
# are available so we can do a single call from skip_checks if alt
-# creds area vailable.
-def is_alt_available():
- # If tenant isolation is enabled admin will be available
- if CONF.auth.allow_tenant_isolation:
+# creds area available.
+# This depends on identity_version as there may be alt credentials
+# available for v2 but not for v3.
+def is_alt_available(identity_version):
+ # If dynamic credentials is enabled alt will be available
+ if CONF.auth.use_dynamic_credentials:
return True
# Check whether test accounts file has the admin specified or not
if (CONF.auth.test_accounts_file and
os.path.isfile(CONF.auth.test_accounts_file)):
- check_accounts = accounts.Accounts(name='check_alt')
+ check_accounts = preprov_creds.PreProvisionedCredentialProvider(
+ identity_version=identity_version, name='check_alt',
+ admin_role=CONF.identity.admin_role)
else:
- check_accounts = accounts.NotLockingAccounts(name='check_alt')
+ check_accounts = preprov_creds.NonLockingCredentialProvider(
+ identity_version=identity_version, name='check_alt',
+ admin_role=CONF.identity.admin_role)
try:
if not check_accounts.is_multi_user():
return False
diff --git a/tempest/common/isolated_creds.py b/tempest/common/dynamic_creds.py
similarity index 86%
rename from tempest/common/isolated_creds.py
rename to tempest/common/dynamic_creds.py
index a4081c9..e2df560 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -28,27 +28,29 @@
LOG = logging.getLogger(__name__)
-class IsolatedCreds(cred_provider.CredentialProvider):
+class DynamicCredentialProvider(cred_provider.CredentialProvider):
- def __init__(self, identity_version=None, name=None,
- network_resources=None):
- super(IsolatedCreds, self).__init__(identity_version, name,
- network_resources)
- self.network_resources = network_resources
- self.isolated_creds = {}
+ def __init__(self, identity_version, name=None, network_resources=None,
+ credentials_domain=None, admin_role=None):
+ super(DynamicCredentialProvider, self).__init__(
+ identity_version=identity_version, name=name,
+ network_resources=network_resources,
+ credentials_domain=credentials_domain, admin_role=admin_role)
+ self._creds = {}
self.ports = []
self.default_admin_creds = cred_provider.get_configured_credentials(
'identity_admin', fill_in=True,
identity_version=self.identity_version)
- self.identity_admin_client, self.network_admin_client = (
- self._get_admin_clients())
+ (self.identity_admin_client, self.network_admin_client,
+ self.networks_admin_client,
+ self.subnets_admin_client) = self._get_admin_clients()
# Domain where isolated credentials are provisioned (v3 only).
# Use that of the admin account is None is configured.
self.creds_domain_name = None
if self.identity_version == 'v3':
self.creds_domain_name = (
self.default_admin_creds.project_domain_name or
- CONF.auth.default_credentials_domain_name)
+ self.credentials_domain)
self.creds_client = cred_client.get_creds_client(
self.identity_admin_client, self.creds_domain_name)
@@ -61,9 +63,11 @@
"""
os = clients.Manager(self.default_admin_creds)
if self.identity_version == 'v2':
- return os.identity_client, os.network_client
+ return (os.identity_client, os.network_client, os.networks_client,
+ os.subnets_client)
else:
- return os.identity_v3_client, os.network_client
+ return (os.identity_v3_client, os.network_client,
+ os.networks_client, os.subnets_client)
def _create_creds(self, suffix="", admin=False, roles=None):
"""Create random credentials under the following schema.
@@ -95,7 +99,7 @@
role_assigned = False
if admin:
self.creds_client.assign_user_role(user, project,
- CONF.identity.admin_role)
+ self.admin_role)
role_assigned = True
# Add roles specified in config file
for conf_role in CONF.auth.tempest_roles:
@@ -158,7 +162,7 @@
return network, subnet, router
def _create_network(self, name, tenant_id):
- resp_body = self.network_admin_client.create_network(
+ resp_body = self.networks_admin_client.create_network(
name=name, tenant_id=tenant_id)
return resp_body['network']
@@ -168,7 +172,7 @@
for subnet_cidr in base_cidr.subnet(mask_bits):
try:
if self.network_resources:
- resp_body = self.network_admin_client.\
+ resp_body = self.subnets_admin_client.\
create_subnet(
network_id=network_id, cidr=str(subnet_cidr),
name=subnet_name,
@@ -176,7 +180,7 @@
enable_dhcp=self.network_resources['dhcp'],
ip_version=4)
else:
- resp_body = self.network_admin_client.\
+ resp_body = self.subnets_admin_client.\
create_subnet(network_id=network_id,
cidr=str(subnet_cidr),
name=subnet_name,
@@ -205,17 +209,17 @@
router_id, subnet_id)
def get_credentials(self, credential_type):
- if self.isolated_creds.get(str(credential_type)):
- credentials = self.isolated_creds[str(credential_type)]
+ if self._creds.get(str(credential_type)):
+ credentials = self._creds[str(credential_type)]
else:
if credential_type in ['primary', 'alt', 'admin']:
is_admin = (credential_type == 'admin')
credentials = self._create_creds(admin=is_admin)
else:
credentials = self._create_creds(roles=credential_type)
- self.isolated_creds[str(credential_type)] = credentials
+ self._creds[str(credential_type)] = credentials
# Maintained until tests are ported
- LOG.info("Acquired isolated creds:\n credentials: %s"
+ LOG.info("Acquired dynamic creds:\n credentials: %s"
% credentials)
if (CONF.service_available.neutron and
not CONF.baremetal.driver_enabled and
@@ -240,15 +244,15 @@
def get_creds_by_roles(self, roles, force_new=False):
roles = list(set(roles))
# The roles list as a str will become the index as the dict key for
- # the created credentials set in the isolated_creds dict.
- exist_creds = self.isolated_creds.get(str(roles))
+ # the created credentials set in the dynamic_creds dict.
+ exist_creds = self._creds.get(str(roles))
# If force_new flag is True 2 cred sets with the same roles are needed
# handle this by creating a separate index for old one to store it
# separately for cleanup
if exist_creds and force_new:
- new_index = str(roles) + '-' + str(len(self.isolated_creds))
- self.isolated_creds[new_index] = exist_creds
- del self.isolated_creds[str(roles)]
+ new_index = str(roles) + '-' + str(len(self._creds))
+ self._creds[new_index] = exist_creds
+ del self._creds[str(roles)]
return self.get_credentials(roles)
def _clear_isolated_router(self, router_id, router_name):
@@ -260,15 +264,15 @@
router_name)
def _clear_isolated_subnet(self, subnet_id, subnet_name):
- net_client = self.network_admin_client
+ client = self.subnets_admin_client
try:
- net_client.delete_subnet(subnet_id)
+ client.delete_subnet(subnet_id)
except lib_exc.NotFound:
LOG.warn('subnet with name: %s not found for delete' %
subnet_name)
def _clear_isolated_network(self, network_id, network_name):
- net_client = self.network_admin_client
+ net_client = self.networks_admin_client
try:
net_client.delete_network(network_id)
except lib_exc.NotFound:
@@ -289,8 +293,8 @@
def _clear_isolated_net_resources(self):
net_client = self.network_admin_client
- for cred in self.isolated_creds:
- creds = self.isolated_creds.get(cred)
+ for cred in self._creds:
+ creds = self._creds.get(cred)
if (not creds or not any([creds.router, creds.network,
creds.subnet])):
continue
@@ -317,11 +321,11 @@
self._clear_isolated_network(creds.network['id'],
creds.network['name'])
- def clear_isolated_creds(self):
- if not self.isolated_creds:
+ def clear_creds(self):
+ if not self._creds:
return
self._clear_isolated_net_resources()
- for creds in six.itervalues(self.isolated_creds):
+ for creds in six.itervalues(self._creds):
try:
self.creds_client.delete_user(creds.user_id)
except lib_exc.NotFound:
@@ -334,7 +338,7 @@
except lib_exc.NotFound:
LOG.warn("tenant with name: %s not found for delete" %
creds.tenant_name)
- self.isolated_creds = {}
+ self._creds = {}
def is_multi_user(self):
return True
diff --git a/tempest/common/accounts.py b/tempest/common/preprov_creds.py
similarity index 79%
rename from tempest/common/accounts.py
rename to tempest/common/preprov_creds.py
index 9e6bee3..dd27f08 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/preprov_creds.py
@@ -18,6 +18,7 @@
from oslo_concurrency import lockutils
from oslo_log import log as logging
import six
+from tempest_lib import auth
import yaml
from tempest import clients
@@ -36,11 +37,13 @@
return accounts
-class Accounts(cred_provider.CredentialProvider):
+class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
- def __init__(self, identity_version=None, name=None):
- super(Accounts, self).__init__(identity_version=identity_version,
- name=name)
+ def __init__(self, identity_version, name=None, credentials_domain=None,
+ admin_role=None):
+ super(PreProvisionedCredentialProvider, self).__init__(
+ identity_version=identity_version, name=name,
+ credentials_domain=credentials_domain, admin_role=admin_role)
if (CONF.auth.test_accounts_file and
os.path.isfile(CONF.auth.test_accounts_file)):
accounts = read_accounts_yaml(CONF.auth.test_accounts_file)
@@ -48,10 +51,10 @@
else:
accounts = {}
self.use_default_creds = True
- self.hash_dict = self.get_hash_dict(accounts)
+ self.hash_dict = self.get_hash_dict(accounts, admin_role)
self.accounts_dir = os.path.join(lockutils.get_lock_path(CONF),
'test_accounts')
- self.isolated_creds = {}
+ self._creds = {}
@classmethod
def _append_role(cls, role, account_hash, hash_dict):
@@ -62,7 +65,7 @@
return hash_dict
@classmethod
- def get_hash_dict(cls, accounts):
+ def get_hash_dict(cls, accounts, admin_role):
hash_dict = {'roles': {}, 'creds': {}, 'networks': {}}
# Loop over the accounts read from the yaml file
for account in accounts:
@@ -86,8 +89,8 @@
# subdict with the hash
for type in types:
if type == 'admin':
- hash_dict = cls._append_role(CONF.identity.admin_role,
- temp_hash_key, hash_dict)
+ hash_dict = cls._append_role(admin_role, temp_hash_key,
+ hash_dict)
elif type == 'operator':
hash_dict = cls._append_role(
CONF.object_storage.operator_role, temp_hash_key,
@@ -102,7 +105,7 @@
if resource == 'network':
hash_dict['networks'][temp_hash_key] = resources[resource]
else:
- LOG.warning('Unkown resource type %s, ignoring this field'
+ LOG.warning('Unknown resource type %s, ignoring this field'
% resource)
return hash_dict
@@ -172,9 +175,9 @@
# privlege set which could potentially cause issues on tests where that
# is not expected. So unless the admin role isn't specified do not
# allocate admin.
- admin_hashes = self.hash_dict['roles'].get(CONF.identity.admin_role,
+ admin_hashes = self.hash_dict['roles'].get(self.admin_role,
None)
- if ((not roles or CONF.identity.admin_role not in roles) and
+ if ((not roles or self.admin_role not in roles) and
admin_hashes):
useable_hashes = [x for x in hashes if x not in admin_hashes]
else:
@@ -216,7 +219,7 @@
if ('user_domain_name' in init_attributes and 'user_domain_name'
not in hash_attributes):
# Allow for the case of domain_name populated from config
- domain_name = CONF.auth.default_credentials_domain_name
+ domain_name = self.credentials_domain
hash_attributes['user_domain_name'] = domain_name
if all([getattr(creds, k) == hash_attributes[k] for
k in init_attributes]):
@@ -230,42 +233,42 @@
LOG.info("%s returned allocated creds:\n%s" % (self.name, clean_creds))
def get_primary_creds(self):
- if self.isolated_creds.get('primary'):
- return self.isolated_creds.get('primary')
+ if self._creds.get('primary'):
+ return self._creds.get('primary')
net_creds = self._get_creds()
- self.isolated_creds['primary'] = net_creds
+ self._creds['primary'] = net_creds
return net_creds
def get_alt_creds(self):
- if self.isolated_creds.get('alt'):
- return self.isolated_creds.get('alt')
+ if self._creds.get('alt'):
+ return self._creds.get('alt')
net_creds = self._get_creds()
- self.isolated_creds['alt'] = net_creds
+ self._creds['alt'] = net_creds
return net_creds
def get_creds_by_roles(self, roles, force_new=False):
roles = list(set(roles))
- exist_creds = self.isolated_creds.get(six.text_type(roles).encode(
+ exist_creds = self._creds.get(six.text_type(roles).encode(
'utf-8'), None)
# The force kwarg is used to allocate an additional set of creds with
# the same role list. The index used for the previously allocation
- # in the isolated_creds dict will be moved.
+ # in the _creds dict will be moved.
if exist_creds and not force_new:
return exist_creds
elif exist_creds and force_new:
new_index = six.text_type(roles).encode('utf-8') + '-' + \
- six.text_type(len(self.isolated_creds)).encode('utf-8')
- self.isolated_creds[new_index] = exist_creds
+ six.text_type(len(self._creds)).encode('utf-8')
+ self._creds[new_index] = exist_creds
net_creds = self._get_creds(roles=roles)
- self.isolated_creds[six.text_type(roles).encode('utf-8')] = net_creds
+ self._creds[six.text_type(roles).encode('utf-8')] = net_creds
return net_creds
- def clear_isolated_creds(self):
- for creds in self.isolated_creds.values():
+ def clear_creds(self):
+ for creds in self._creds.values():
self.remove_credentials(creds)
def get_admin_creds(self):
- return self.get_creds_by_roles([CONF.identity.admin_role])
+ return self.get_creds_by_roles([self.admin_role])
def is_role_available(self, role):
if self.use_default_creds:
@@ -276,11 +279,16 @@
return False
def admin_available(self):
- return self.is_role_available(CONF.identity.admin_role)
+ return self.is_role_available(self.admin_role)
def _wrap_creds_with_network(self, hash):
creds_dict = self.hash_dict['creds'][hash]
- credential = cred_provider.get_credentials(
+ # Make sure a domain scope if defined for users in case of V3
+ creds_dict = self._extend_credentials(creds_dict)
+ # This just builds a Credentials object, it does not validate
+ # nor fill with missing fields.
+ credential = auth.get_credentials(
+ auth_url=None, fill_in=False,
identity_version=self.identity_version, **creds_dict)
net_creds = cred_provider.TestResources(credential)
net_clients = clients.Manager(credentials=credential)
@@ -294,8 +302,17 @@
net_creds.set_resources(network=network)
return net_creds
+ def _extend_credentials(self, creds_dict):
+ # In case of v3, adds a user_domain_name field to the creds
+ # dict if not defined
+ if self.identity_version == 'v3':
+ user_domain_fields = set(['user_domain_name', 'user_domain_id'])
+ if not user_domain_fields.intersection(set(creds_dict.keys())):
+ creds_dict['user_domain_name'] = self.credentials_domain
+ return creds_dict
-class NotLockingAccounts(Accounts):
+
+class NonLockingCredentialProvider(PreProvisionedCredentialProvider):
"""Credentials provider which always returns the first and second
configured accounts as primary and alt users.
This credential provider can be used in case of serial test execution
@@ -320,36 +337,37 @@
return self._unique_creds('tenant_id')
def get_primary_creds(self):
- if self.isolated_creds.get('primary'):
- return self.isolated_creds.get('primary')
+ if self._creds.get('primary'):
+ return self._creds.get('primary')
primary_credential = cred_provider.get_configured_credentials(
- credential_type='user', identity_version=self.identity_version)
- self.isolated_creds['primary'] = cred_provider.TestResources(
+ fill_in=False, credential_type='user',
+ identity_version=self.identity_version)
+ self._creds['primary'] = cred_provider.TestResources(
primary_credential)
- return self.isolated_creds['primary']
+ return self._creds['primary']
def get_alt_creds(self):
- if self.isolated_creds.get('alt'):
- return self.isolated_creds.get('alt')
+ if self._creds.get('alt'):
+ return self._creds.get('alt')
alt_credential = cred_provider.get_configured_credentials(
- credential_type='alt_user',
+ fill_in=False, credential_type='alt_user',
identity_version=self.identity_version)
- self.isolated_creds['alt'] = cred_provider.TestResources(
+ self._creds['alt'] = cred_provider.TestResources(
alt_credential)
- return self.isolated_creds['alt']
+ return self._creds['alt']
- def clear_isolated_creds(self):
- self.isolated_creds = {}
+ def clear_creds(self):
+ self._creds = {}
def get_admin_creds(self):
creds = cred_provider.get_configured_credentials(
"identity_admin", fill_in=False)
- self.isolated_creds['admin'] = cred_provider.TestResources(creds)
- return self.isolated_creds['admin']
+ self._creds['admin'] = cred_provider.TestResources(creds)
+ return self._creds['admin']
def get_creds_by_roles(self, roles, force_new=False):
msg = "Credentials being specified through the config file can not be"\
" used with tests that specify using credentials by roles. "\
"Either exclude/skip the tests doing this or use either an "\
- "test_accounts_file or tenant isolation."
+ "test_accounts_file or dynamic credentials."
raise exceptions.InvalidConfiguration(msg)
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index a567c6a..3bead88 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -163,11 +163,22 @@
* dhclient
"""
# TODO(yfried): add support for dhcpcd
- suported_clients = ['udhcpc', 'dhclient']
+ supported_clients = ['udhcpc', 'dhclient']
dhcp_client = CONF.scenario.dhcp_client
- if dhcp_client not in suported_clients:
+ if dhcp_client not in supported_clients:
raise exceptions.InvalidConfiguration('%s DHCP client unsupported'
% dhcp_client)
if dhcp_client == 'udhcpc' and not fixed_ip:
raise ValueError("need to set 'fixed_ip' for udhcpc client")
return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)
+
+ def mount(self, dev_name, mount_path='/mnt'):
+ cmd_mount = 'sudo mount /dev/%s %s' % (dev_name, mount_path)
+ self.exec_command(cmd_mount)
+
+ def umount(self, mount_path='/mnt'):
+ self.exec_command('sudo umount %s' % mount_path)
+
+ def make_fs(self, dev_name, fs='ext4'):
+ cmd_mkfs = 'sudo /usr/sbin/mke2fs -t %s /dev/%s' % (fs, dev_name)
+ self.exec_command(cmd_mkfs)
diff --git a/tempest/config.py b/tempest/config.py
index b867980..0cda018 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -53,7 +53,7 @@
"at least `2 * CONC` distinct accounts configured in "
" the `test_accounts_file`, with CONC == the "
"number of concurrent test processes."),
- cfg.BoolOpt('allow_tenant_isolation',
+ cfg.BoolOpt('use_dynamic_credentials',
default=True,
help="Allows test cases to create/destroy tenants and "
"users. This option requires that OpenStack Identity "
@@ -61,6 +61,8 @@
"test cases and parallel execution, can still be "
"achieved configuring a list of test accounts",
deprecated_opts=[cfg.DeprecatedOpt('allow_tenant_isolation',
+ group='auth'),
+ cfg.DeprecatedOpt('allow_tenant_isolation',
group='compute'),
cfg.DeprecatedOpt('allow_tenant_isolation',
group='orchestration')]),
@@ -76,12 +78,32 @@
group='auth')]),
cfg.BoolOpt('create_isolated_networks',
default=True,
- help="If allow_tenant_isolation is set to True and Neutron is "
- "enabled Tempest will try to create a usable network, "
- "subnet, and router when needed for each tenant it "
+ help="If use_dynamic_credentials is set to True and Neutron "
+ "is enabled Tempest will try to create a usable network, "
+ "subnet, and router when needed for each tenant it "
"creates. However in some neutron configurations, like "
"with VLAN provider networks, this doesn't work. So if "
"set to False the isolated networks will not be created"),
+ cfg.StrOpt('admin_username',
+ help="Username for an administrative user. This is needed for "
+ "authenticating requests made by tenant isolation to "
+ "create users and projects",
+ deprecated_group='identity'),
+ cfg.StrOpt('admin_tenant_name',
+ help="Tenant name to use for an administrative user. This is "
+ "needed for authenticating requests made by tenant "
+ "isolation to create users and projects",
+ deprecated_group='identity'),
+ cfg.StrOpt('admin_password',
+ help="Password to use for an administrative user. This is "
+ "needed for authenticating requests made by tenant "
+ "isolation to create users and projects",
+ secret=True,
+ deprecated_group='identity'),
+ cfg.StrOpt('admin_domain_name',
+ help="Admin domain name for authentication (Keystone V3)."
+ "The same domain applies to user and project",
+ deprecated_group='identity'),
]
identity_group = cfg.OptGroup(name='identity',
@@ -133,42 +155,38 @@
help="The endpoint type to use for OpenStack Identity "
"(Keystone) API v3"),
cfg.StrOpt('username',
- help="Username to use for Nova API requests."),
+ help="Username to use for Nova API requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('tenant_name',
- help="Tenant name to use for Nova API requests."),
+ help="Tenant name to use for Nova API requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('admin_role',
default='admin',
help="Role required to administrate keystone."),
cfg.StrOpt('password',
help="API key to use when authenticating.",
- secret=True),
+ secret=True,
+ deprecated_for_removal=True),
cfg.StrOpt('domain_name',
help="Domain name for authentication (Keystone V3)."
- "The same domain applies to user and project"),
+ "The same domain applies to user and project",
+ deprecated_for_removal=True),
cfg.StrOpt('alt_username',
help="Username of alternate user to use for Nova API "
- "requests."),
+ "requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('alt_tenant_name',
help="Alternate user's Tenant name to use for Nova API "
- "requests."),
+ "requests.",
+ deprecated_for_removal=True),
cfg.StrOpt('alt_password',
help="API key to use when authenticating as alternate user.",
- secret=True),
+ secret=True,
+ deprecated_for_removal=True),
cfg.StrOpt('alt_domain_name',
help="Alternate domain name for authentication (Keystone V3)."
- "The same domain applies to user and project"),
- cfg.StrOpt('admin_username',
- help="Administrative Username to use for "
- "Keystone API requests."),
- cfg.StrOpt('admin_tenant_name',
- help="Administrative Tenant name to use for Keystone API "
- "requests."),
- cfg.StrOpt('admin_password',
- help="API key to use when authenticating as admin.",
- secret=True),
- cfg.StrOpt('admin_domain_name',
- help="Admin domain name for authentication (Keystone V3)."
- "The same domain applies to user and project"),
+ "The same domain applies to user and project",
+ deprecated_for_removal=True),
cfg.StrOpt('default_domain_id',
default='default',
help="ID of the default domain"),
@@ -404,6 +422,12 @@
cfg.BoolOpt('ec2_api',
default=True,
help='Does the test environment have the ec2 api running?'),
+ cfg.BoolOpt('nova_cert',
+ default=True,
+ help='Does the test environment have the nova cert running?'),
+ cfg.BoolOpt('personality',
+ default=True,
+ help='Does the test environment support server personality'),
# TODO(mriedem): Remove preserve_ports once juno-eol happens.
cfg.BoolOpt('preserve_ports',
default=False,
@@ -424,6 +448,9 @@
help='Does the test environment support creating instances '
'with multiple ports on the same network? This is only '
'valid when using Neutron.'),
+ cfg.BoolOpt('config_drive',
+ default=True,
+ help='Enable special configuration drive with metadata.'),
]
@@ -456,7 +483,16 @@
cfg.IntOpt('build_interval',
default=1,
help="Time in seconds between image operation status "
- "checks.")
+ "checks."),
+ cfg.ListOpt('container_formats',
+ default=['ami', 'ari', 'aki', 'bare', 'ovf', 'ova'],
+ help="A list of image's container formats "
+ "users can specify."),
+ cfg.ListOpt('disk_formats',
+ default=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2',
+ 'vdi', 'iso'],
+ help="A list of image's disk formats "
+ "users can specify.")
]
image_feature_group = cfg.OptGroup(name='image-feature-enabled',
@@ -541,6 +577,10 @@
" with pre-configured ports."
" Supported ports are:"
" ['normal','direct','macvtap']"),
+ cfg.ListOpt('default_network',
+ default=["1.0.0.0/16", "2.0.0.0/16"],
+ help="List of ip pools"
+ " for subnetpools creation"),
]
network_feature_group = cfg.OptGroup(name='network-feature-enabled',
@@ -898,29 +938,32 @@
]
-data_processing_group = cfg.OptGroup(name="data_processing",
+data_processing_group = cfg.OptGroup(name="data-processing",
title="Data Processing options")
DataProcessingGroup = [
cfg.StrOpt('catalog_type',
- default='data_processing',
+ default='data-processing',
+ deprecated_group="data_processing",
help="Catalog type of the data processing service."),
cfg.StrOpt('endpoint_type',
default='publicURL',
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
+ deprecated_group="data_processing",
help="The endpoint type to use for the data processing "
"service."),
]
data_processing_feature_group = cfg.OptGroup(
- name="data_processing-feature-enabled",
+ name="data-processing-feature-enabled",
title="Enabled Data Processing features")
DataProcessingFeaturesGroup = [
cfg.ListOpt('plugins',
default=["vanilla", "hdp"],
+ deprecated_group="data_processing-feature-enabled",
help="List of enabled data processing plugins")
]
@@ -1048,7 +1091,7 @@
# TODO(yfried): add support for dhcpcd
cfg.StrOpt('dhcp_client',
default='udhcpc',
- choices=["udhcpc", "dhclient"],
+ choices=["udhcpc", "dhclient", ""],
help='DHCP client used by images to renew DCHP lease. '
'If left empty, update operation will be skipped. '
'Supported clients: "udhcpc", "dhclient"')
@@ -1266,9 +1309,7 @@
class TempestConfigPrivate(object):
"""Provides OpenStack configuration information."""
- DEFAULT_CONFIG_DIR = os.path.join(
- os.path.abspath(os.path.dirname(os.path.dirname(__file__))),
- "etc")
+ DEFAULT_CONFIG_DIR = os.path.join(os.getcwd(), "etc")
DEFAULT_CONFIG_FILE = "tempest.conf"
@@ -1298,9 +1339,9 @@
self.telemetry = _CONF.telemetry
self.telemetry_feature_enabled = _CONF['telemetry-feature-enabled']
self.dashboard = _CONF.dashboard
- self.data_processing = _CONF.data_processing
+ self.data_processing = _CONF['data-processing']
self.data_processing_feature_enabled = _CONF[
- 'data_processing-feature-enabled']
+ 'data-processing-feature-enabled']
self.boto = _CONF.boto
self.stress = _CONF.stress
self.scenario = _CONF.scenario
diff --git a/tempest/manager.py b/tempest/manager.py
index c39d3e5..d7c3128 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -47,14 +47,14 @@
# Check if passed or default credentials are valid
if not self.credentials.is_valid():
raise exceptions.InvalidCredentials()
- # Tenant isolation creates TestResources, but Accounts and some tests
- # creates Credentials
+ # Tenant isolation creates TestResources, but
+ # PreProvisionedCredentialProvider and some tests create Credentials
if isinstance(credentials, cred_provider.TestResources):
creds = self.credentials.credentials
else:
creds = self.credentials
# Creates an auth provider for the credentials
- self.auth_provider = get_auth_provider(creds)
+ self.auth_provider = get_auth_provider(creds, pre_auth=True)
# FIXME(andreaf) unused
self.client_attr_names = []
@@ -66,7 +66,7 @@
return auth.KeystoneV2AuthProvider, CONF.identity.uri
-def get_auth_provider(credentials):
+def get_auth_provider(credentials, pre_auth=False):
default_params = {
'disable_ssl_certificate_validation':
CONF.identity.disable_ssl_certificate_validation,
@@ -78,4 +78,8 @@
'Credentials must be specified')
auth_provider_class, auth_url = get_auth_provider_class(
credentials)
- return auth_provider_class(credentials, auth_url, **default_params)
+ _auth_provider = auth_provider_class(credentials, auth_url,
+ **default_params)
+ if pre_auth:
+ _auth_provider.set_auth()
+ return _auth_provider
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index d70021c..a10dc83 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -61,6 +61,8 @@
cls.interface_client = cls.manager.interfaces_client
# Neutron network client
cls.network_client = cls.manager.network_client
+ cls.networks_client = cls.manager.networks_client
+ cls.subnets_client = cls.manager.subnets_client
# Heat client
cls.orchestration_client = cls.manager.orchestration_client
@@ -178,7 +180,8 @@
LOG.debug("Creating a server (name: %s, image: %s, flavor: %s)",
name, image, flavor)
- server = self.servers_client.create_server(name, image, flavor,
+ server = self.servers_client.create_server(name=name, imageRef=image,
+ flavorRef=flavor,
**create_kwargs)['server']
if wait_on_delete:
self.addCleanup(waiters.wait_for_server_termination,
@@ -447,21 +450,21 @@
image_name, server['name'])
return snapshot_image
- def nova_volume_attach(self):
+ def nova_volume_attach(self, server, volume_to_attach):
volume = self.servers_client.attach_volume(
- self.server['id'], volumeId=self.volume['id'], device='/dev/%s'
+ server['id'], volumeId=volume_to_attach['id'], device='/dev/%s'
% CONF.compute.volume_device_name)['volumeAttachment']
- self.assertEqual(self.volume['id'], volume['id'])
+ self.assertEqual(volume_to_attach['id'], volume['id'])
self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
- # Refresh the volume after the attachment
- self.volume = self.volumes_client.show_volume(volume['id'])['volume']
- def nova_volume_detach(self):
- self.servers_client.detach_volume(self.server['id'], self.volume['id'])
- self.volumes_client.wait_for_volume_status(self.volume['id'],
- 'available')
+ # Return the updated volume after the attachment
+ return self.volumes_client.show_volume(volume['id'])['volume']
- volume = self.volumes_client.show_volume(self.volume['id'])['volume']
+ def nova_volume_detach(self, server, volume):
+ self.servers_client.detach_volume(server['id'], volume['id'])
+ self.volumes_client.wait_for_volume_status(volume['id'], 'available')
+
+ volume = self.volumes_client.show_volume(volume['id'])['volume']
self.assertEqual('available', volume['status'])
def rebuild_server(self, server_id, image=None,
@@ -492,9 +495,23 @@
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.communicate()
+
return (proc.returncode == 0) == should_succeed
- return tempest.test.call_until_true(ping, timeout, 1)
+ caller = misc_utils.find_test_caller()
+ LOG.debug('%(caller)s begins to ping %(ip)s in %(timeout)s sec and the'
+ ' expected result is %(should_succeed)s' % {
+ 'caller': caller, 'ip': ip_address, 'timeout': timeout,
+ 'should_succeed':
+ 'reachable' if should_succeed else 'unreachable'
+ })
+ result = tempest.test.call_until_true(ping, timeout, 1)
+ LOG.debug('%(caller)s finishes ping %(ip)s in %(timeout)s sec and the '
+ 'ping result is %(result)s' % {
+ 'caller': caller, 'ip': ip_address, 'timeout': timeout,
+ 'result': 'expected' if result else 'unexpected'
+ })
+ return result
def check_vm_connectivity(self, ip_address,
username=None,
@@ -556,6 +573,33 @@
floating_ip['ip'], thing['id'])
return floating_ip
+ def create_timestamp(self, server_or_ip, dev_name=None, mount_path='/mnt',
+ private_key=None):
+ ssh_client = self.get_remote_client(server_or_ip,
+ private_key=private_key)
+ if dev_name is not None:
+ ssh_client.make_fs(dev_name)
+ ssh_client.mount(dev_name, mount_path)
+ cmd_timestamp = 'sudo sh -c "date > %s/timestamp; sync"' % mount_path
+ ssh_client.exec_command(cmd_timestamp)
+ timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
+ % mount_path)
+ if dev_name is not None:
+ ssh_client.umount(mount_path)
+ return timestamp
+
+ def get_timestamp(self, server_or_ip, dev_name=None, mount_path='/mnt',
+ private_key=None):
+ ssh_client = self.get_remote_client(server_or_ip,
+ private_key=private_key)
+ if dev_name is not None:
+ ssh_client.mount(dev_name, mount_path)
+ timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
+ % mount_path)
+ if dev_name is not None:
+ ssh_client.umount(mount_path)
+ return timestamp
+
class NetworkScenarioTest(ScenarioTest):
"""Base class for network scenario tests.
@@ -581,29 +625,31 @@
super(NetworkScenarioTest, cls).resource_setup()
cls.tenant_id = cls.manager.identity_client.tenant_id
- def _create_network(self, client=None, tenant_id=None,
- namestart='network-smoke-'):
+ def _create_network(self, client=None, networks_client=None,
+ tenant_id=None, namestart='network-smoke-'):
if not client:
client = self.network_client
+ if not networks_client:
+ networks_client = self.networks_client
if not tenant_id:
tenant_id = client.tenant_id
name = data_utils.rand_name(namestart)
- result = client.create_network(name=name, tenant_id=tenant_id)
- network = net_resources.DeletableNetwork(client=client,
- **result['network'])
+ result = networks_client.create_network(name=name, tenant_id=tenant_id)
+ network = net_resources.DeletableNetwork(
+ networks_client=networks_client, **result['network'])
self.assertEqual(network.name, name)
self.addCleanup(self.delete_wrapper, network.delete)
return network
def _list_networks(self, *args, **kwargs):
"""List networks using admin creds """
- networks_list = self.admin_manager.network_client.list_networks(
+ networks_list = self.admin_manager.networks_client.list_networks(
*args, **kwargs)
return networks_list['networks']
def _list_subnets(self, *args, **kwargs):
"""List subnets using admin creds """
- subnets_list = self.admin_manager.network_client.list_subnets(
+ subnets_list = self.admin_manager.subnets_client.list_subnets(
*args, **kwargs)
return subnets_list['subnets']
@@ -625,14 +671,16 @@
*args, **kwargs)
return agents_list['agents']
- def _create_subnet(self, network, client=None, namestart='subnet-smoke',
- **kwargs):
+ def _create_subnet(self, network, client=None, subnets_client=None,
+ namestart='subnet-smoke', **kwargs):
"""
Create a subnet for the given network within the cidr block
configured for tenant networks.
"""
if not client:
client = self.network_client
+ if not subnets_client:
+ subnets_client = self.subnets_client
def cidr_in_use(cidr, tenant_id):
"""
@@ -670,15 +718,16 @@
**kwargs
)
try:
- result = client.create_subnet(**subnet)
+ result = subnets_client.create_subnet(**subnet)
break
except lib_exc.Conflict as e:
is_overlapping_cidr = 'overlaps with another subnet' in str(e)
if not is_overlapping_cidr:
raise
self.assertIsNotNone(result, 'Unable to allocate tenant network')
- subnet = net_resources.DeletableSubnet(client=client,
- **result['subnet'])
+ subnet = net_resources.DeletableSubnet(
+ network_client=client, subnets_client=subnets_client,
+ **result['subnet'])
self.assertEqual(subnet.cidr, str_cidr)
self.addCleanup(self.delete_wrapper, subnet.delete)
return subnet
@@ -699,7 +748,7 @@
return port
def _get_server_port_id_and_ip4(self, server, ip_addr=None):
- ports = self._list_ports(device_id=server['id'],
+ ports = self._list_ports(device_id=server['id'], status='ACTIVE',
fixed_ip=ip_addr)
# it might happen here that this port has more then one ip address
# as in case of dual stack- when this port is created on 2 subnets
@@ -1034,7 +1083,8 @@
router.update(admin_state_up=admin_state_up)
self.assertEqual(admin_state_up, router.admin_state_up)
- def create_networks(self, client=None, tenant_id=None,
+ def create_networks(self, client=None, networks_client=None,
+ subnets_client=None, tenant_id=None,
dns_nameservers=None):
"""Create a network with a subnet connected to a router.
@@ -1060,10 +1110,13 @@
router = None
subnet = None
else:
- network = self._create_network(client=client, tenant_id=tenant_id)
+ network = self._create_network(
+ client=client, networks_client=networks_client,
+ tenant_id=tenant_id)
router = self._get_router(client=client, tenant_id=tenant_id)
- subnet_kwargs = dict(network=network, client=client)
+ subnet_kwargs = dict(network=network, client=client,
+ subnets_client=subnets_client)
# use explicit check because empty list is a valid option
if dns_nameservers is not None:
subnet_kwargs['dns_nameservers'] = dns_nameservers
@@ -1073,7 +1126,13 @@
def create_server(self, name=None, image=None, flavor=None,
wait_on_boot=True, wait_on_delete=True,
+ network_client=None, networks_client=None,
create_kwargs=None):
+ if network_client is None:
+ network_client = self.network_client
+ if networks_client is None:
+ networks_client = self.networks_client
+
vnic_type = CONF.network.port_vnic_type
# If vnic_type is configured create port for
@@ -1084,19 +1143,16 @@
create_port_body = {'binding:vnic_type': vnic_type,
'namestart': 'port-smoke'}
if create_kwargs:
- net_client = create_kwargs.get("network_client",
- self.network_client)
-
# Convert security group names to security group ids
# to pass to create_port
if create_kwargs.get('security_groups'):
- security_groups = net_client.list_security_groups().get(
- 'security_groups')
+ security_groups = network_client.list_security_groups(
+ ).get('security_groups')
sec_dict = dict([(s['name'], s['id'])
for s in security_groups])
- sec_groups_names = [s['name'] for s in create_kwargs[
- 'security_groups']]
+ sec_groups_names = [s['name'] for s in create_kwargs.get(
+ 'security_groups')]
security_groups_ids = [sec_dict[s]
for s in sec_groups_names]
@@ -1104,15 +1160,14 @@
create_port_body[
'security_groups'] = security_groups_ids
networks = create_kwargs.get('networks')
- else:
- net_client = self.network_client
+
# If there are no networks passed to us we look up
# for the tenant's private networks and create a port
# if there is only one private network. The same behaviour
# as we would expect when passing the call to the clients
# with no networks
if not networks:
- networks = net_client.list_networks(filters={
+ networks = networks_client.list_networks(filters={
'router:external': False})
self.assertEqual(1, len(networks),
"There is more than one"
@@ -1120,7 +1175,7 @@
for net in networks:
net_id = net['uuid']
port = self._create_port(network_id=net_id,
- client=net_client,
+ client=network_client,
**create_port_body)
ports.append({'port': port.id})
if ports:
@@ -1343,9 +1398,9 @@
control_location=control_location)['encryption']
-class SwiftScenarioTest(ScenarioTest):
+class ObjectStorageScenarioTest(ScenarioTest):
"""
- Provide harness to do Swift scenario tests.
+ Provide harness to do Object Storage scenario tests.
Subclasses implement the tests that use the methods provided by this
class.
@@ -1353,7 +1408,7 @@
@classmethod
def skip_checks(cls):
- super(SwiftScenarioTest, cls).skip_checks()
+ super(ObjectStorageScenarioTest, cls).skip_checks()
if not CONF.service_available.swift:
skip_msg = ("%s skipped as swift is not available" %
cls.__name__)
@@ -1362,13 +1417,13 @@
@classmethod
def setup_credentials(cls):
cls.set_network_resources()
- super(SwiftScenarioTest, cls).setup_credentials()
+ super(ObjectStorageScenarioTest, cls).setup_credentials()
operator_role = CONF.object_storage.operator_role
cls.os_operator = cls.get_client_manager(roles=[operator_role])
@classmethod
def setup_clients(cls):
- super(SwiftScenarioTest, cls).setup_clients()
+ super(ObjectStorageScenarioTest, cls).setup_clients()
# Clients for Swift
cls.account_client = cls.os_operator.account_client
cls.container_client = cls.os_operator.container_client
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index d5bad64..f6d9f88 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -90,7 +90,7 @@
# construct login url for dashboard, discovery accommodates non-/ web
# root for dashboard
- login_url = CONF.dashboard.dashboard_url + parser.login[1:]
+ login_url = parse.urljoin(CONF.dashboard.dashboard_url, parser.login)
# Prepare login form request
req = request.Request(login_url)
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index b66eb59..3f0123d 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -54,8 +54,8 @@
self.volume = self.create_volume(volume_type=volume_type['name'])
def attach_detach_volume(self):
- self.nova_volume_attach()
- self.nova_volume_detach()
+ self.volume = self.nova_volume_attach(self.server, self.volume)
+ self.nova_volume_detach(self.server, self.volume)
@test.idempotent_id('79165fb4-5534-4b9d-8429-97ccffb8f86e')
@test.services('compute', 'volume', 'image')
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 2ad5d2d..63dd4f0 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -99,9 +99,9 @@
create_kwargs = fixed_network.set_networks_kwarg(network,
create_kwargs)
self.servers_client.create_server(
- name,
- self.image,
- flavor_id,
+ name=name,
+ imageRef=self.image,
+ flavorRef=flavor_id,
**create_kwargs)
# needed because of bug 1199788
params = {'name': name}
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index eac8311..22aa06c 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -40,66 +40,61 @@
"""
- def _wait_for_server_status(self, status):
- server_id = self.server['id']
+ def _wait_for_server_status(self, server, status):
+ server_id = server['id']
# Raise on error defaults to True, which is consistent with the
# original function from scenario tests here
waiters.wait_for_server_status(self.servers_client,
server_id, status)
- def nova_keypair_add(self):
- self.keypair = self.create_keypair()
-
- def nova_boot(self):
- create_kwargs = {'key_name': self.keypair['name']}
- self.server = self.create_server(image=self.image,
- create_kwargs=create_kwargs)
+ def nova_boot(self, keypair):
+ create_kwargs = {'key_name': keypair['name']}
+ return self.create_server(image=self.image,
+ create_kwargs=create_kwargs)
def nova_list(self):
servers = self.servers_client.list_servers()
# The list servers in the compute client is inconsistent...
- servers = servers['servers']
- self.assertIn(self.server['id'], [x['id'] for x in servers])
+ return servers['servers']
- def nova_show(self):
- got_server = (self.servers_client.show_server(self.server['id'])
+ def nova_show(self, server):
+ got_server = (self.servers_client.show_server(server['id'])
['server'])
excluded_keys = ['OS-EXT-AZ:availability_zone']
# Exclude these keys because of LP:#1486475
excluded_keys.extend(['OS-EXT-STS:power_state', 'updated'])
self.assertThat(
- self.server, custom_matchers.MatchesDictExceptForKeys(
+ server, custom_matchers.MatchesDictExceptForKeys(
got_server, excluded_keys=excluded_keys))
def cinder_create(self):
- self.volume = self.create_volume()
+ return self.create_volume()
def cinder_list(self):
- volumes = self.volumes_client.list_volumes()['volumes']
- self.assertIn(self.volume['id'], [x['id'] for x in volumes])
+ return self.volumes_client.list_volumes()['volumes']
- def cinder_show(self):
- volume = self.volumes_client.show_volume(self.volume['id'])['volume']
- self.assertEqual(self.volume, volume)
+ def cinder_show(self, volume):
+ got_volume = self.volumes_client.show_volume(volume['id'])['volume']
+ self.assertEqual(volume, got_volume)
- def nova_reboot(self):
- self.servers_client.reboot_server(self.server['id'], 'SOFT')
- self._wait_for_server_status('ACTIVE')
+ def nova_reboot(self, server):
+ self.servers_client.reboot_server(server['id'], 'SOFT')
+ self._wait_for_server_status(server, 'ACTIVE')
def check_partitions(self):
# NOTE(andreaf) The device name may be different on different guest OS
partitions = self.linux_client.get_partitions()
self.assertEqual(1, partitions.count(CONF.compute.volume_device_name))
- def create_and_add_security_group(self):
+ def create_and_add_security_group_to_server(self, server):
secgroup = self._create_security_group()
- self.servers_client.add_security_group(self.server['id'],
+ self.servers_client.add_security_group(server['id'],
secgroup['name'])
self.addCleanup(self.servers_client.remove_security_group,
- self.server['id'], secgroup['name'])
+ server['id'], secgroup['name'])
def wait_for_secgroup_add():
- body = (self.servers_client.show_server(self.server['id'])
+ body = (self.servers_client.show_server(server['id'])
['server'])
return {'name': secgroup['name']} in body['security_groups']
@@ -107,29 +102,39 @@
CONF.compute.build_timeout,
CONF.compute.build_interval):
msg = ('Timed out waiting for adding security group %s to server '
- '%s' % (secgroup['id'], self.server['id']))
+ '%s' % (secgroup['id'], server['id']))
raise exceptions.TimeoutException(msg)
@test.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
@test.services('compute', 'volume', 'image', 'network')
def test_minimum_basic_scenario(self):
self.glance_image_create()
- self.nova_keypair_add()
- self.nova_boot()
- self.nova_list()
- self.nova_show()
- self.cinder_create()
- self.cinder_list()
- self.cinder_show()
- self.nova_volume_attach()
- self.addCleanup(self.nova_volume_detach)
- self.cinder_show()
- self.floating_ip = self.create_floating_ip(self.server)
- self.create_and_add_security_group()
+ keypair = self.create_keypair()
- self.linux_client = self.get_remote_client(self.floating_ip['ip'])
- self.nova_reboot()
+ server = self.nova_boot(keypair)
+ servers = self.nova_list()
+ self.assertIn(server['id'], [x['id'] for x in servers])
- self.linux_client = self.get_remote_client(self.floating_ip['ip'])
+ self.nova_show(server)
+
+ volume = self.cinder_create()
+ volumes = self.cinder_list()
+ self.assertIn(volume['id'], [x['id'] for x in volumes])
+
+ self.cinder_show(volume)
+
+ volume = self.nova_volume_attach(server, volume)
+ self.addCleanup(self.nova_volume_detach, server, volume)
+ self.cinder_show(volume)
+
+ floating_ip = self.create_floating_ip(server)
+ self.create_and_add_security_group_to_server(server)
+
+ self.linux_client = self.get_remote_client(
+ floating_ip['ip'], private_key=keypair['private_key'])
+ self.nova_reboot(server)
+
+ self.linux_client = self.get_remote_client(
+ floating_ip['ip'], private_key=keypair['private_key'])
self.check_partitions()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 62b2976..704342f 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -56,7 +56,7 @@
super(TestNetworkAdvancedServerOps, cls).setup_credentials()
def _setup_network_and_servers(self):
- self.keypair = self.create_keypair()
+ keypair = self.create_keypair()
security_group = self._create_security_group()
network, subnet, router = self.create_networks()
public_network_id = CONF.network.public_network_id
@@ -64,91 +64,103 @@
'networks': [
{'uuid': network.id},
],
- 'key_name': self.keypair['name'],
+ 'key_name': keypair['name'],
'security_groups': [{'name': security_group['name']}],
}
server_name = data_utils.rand_name('server-smoke')
- self.server = self.create_server(name=server_name,
- create_kwargs=create_kwargs)
- self.floating_ip = self.create_floating_ip(self.server,
- public_network_id)
+ server = self.create_server(name=server_name,
+ create_kwargs=create_kwargs)
+ floating_ip = self.create_floating_ip(server, public_network_id)
# Verify that we can indeed connect to the server before we mess with
# it's state
- self._wait_server_status_and_check_network_connectivity()
+ self._wait_server_status_and_check_network_connectivity(
+ server, keypair, floating_ip)
- def _check_network_connectivity(self, should_connect=True):
+ return server, keypair, floating_ip
+
+ def _check_network_connectivity(self, server, keypair, floating_ip,
+ should_connect=True):
username = CONF.compute.image_ssh_user
- private_key = self.keypair['private_key']
+ private_key = keypair['private_key']
self._check_tenant_network_connectivity(
- self.server, username, private_key,
+ server, username, private_key,
should_connect=should_connect,
- servers_for_debug=[self.server])
- floating_ip = self.floating_ip.floating_ip_address
+ servers_for_debug=[server])
+ floating_ip_addr = floating_ip.floating_ip_address
# Check FloatingIP status before checking the connectivity
- self.check_floating_ip_status(self.floating_ip, 'ACTIVE')
- self.check_public_network_connectivity(floating_ip, username,
+ self.check_floating_ip_status(floating_ip, 'ACTIVE')
+ self.check_public_network_connectivity(floating_ip_addr, username,
private_key, should_connect,
- servers=[self.server])
+ servers=[server])
- def _wait_server_status_and_check_network_connectivity(self):
- waiters.wait_for_server_status(self.servers_client,
- self.server['id'], 'ACTIVE')
- self._check_network_connectivity()
+ def _wait_server_status_and_check_network_connectivity(self, server,
+ keypair,
+ floating_ip):
+ waiters.wait_for_server_status(self.servers_client, server['id'],
+ 'ACTIVE')
+ self._check_network_connectivity(server, keypair, floating_ip)
@test.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
@test.stresstest(class_setup_per='process')
@test.services('compute', 'network')
def test_server_connectivity_stop_start(self):
- self._setup_network_and_servers()
- self.servers_client.stop_server(self.server['id'])
- waiters.wait_for_server_status(self.servers_client,
- self.server['id'], 'SHUTOFF')
- self._check_network_connectivity(should_connect=False)
- self.servers_client.start_server(self.server['id'])
- self._wait_server_status_and_check_network_connectivity()
+ server, keypair, floating_ip = self._setup_network_and_servers()
+ self.servers_client.stop_server(server['id'])
+ waiters.wait_for_server_status(self.servers_client, server['id'],
+ 'SHUTOFF')
+ self._check_network_connectivity(server, keypair, floating_ip,
+ should_connect=False)
+ self.servers_client.start_server(server['id'])
+ self._wait_server_status_and_check_network_connectivity(
+ server, keypair, floating_ip)
@test.idempotent_id('7b6860c2-afa3-4846-9522-adeb38dfbe08')
@test.services('compute', 'network')
def test_server_connectivity_reboot(self):
- self._setup_network_and_servers()
- self.servers_client.reboot_server(self.server['id'],
- reboot_type='SOFT')
- self._wait_server_status_and_check_network_connectivity()
+ server, keypair, floating_ip = self._setup_network_and_servers()
+ self.servers_client.reboot_server(server['id'], reboot_type='SOFT')
+ self._wait_server_status_and_check_network_connectivity(
+ server, keypair, floating_ip)
@test.idempotent_id('88a529c2-1daa-4c85-9aec-d541ba3eb699')
@test.services('compute', 'network')
def test_server_connectivity_rebuild(self):
- self._setup_network_and_servers()
+ server, keypair, floating_ip = self._setup_network_and_servers()
image_ref_alt = CONF.compute.image_ref_alt
- self.servers_client.rebuild_server(self.server['id'],
+ self.servers_client.rebuild_server(server['id'],
image_ref=image_ref_alt)
- self._wait_server_status_and_check_network_connectivity()
+ self._wait_server_status_and_check_network_connectivity(
+ server, keypair, floating_ip)
@test.idempotent_id('2b2642db-6568-4b35-b812-eceed3fa20ce')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.services('compute', 'network')
def test_server_connectivity_pause_unpause(self):
- self._setup_network_and_servers()
- self.servers_client.pause_server(self.server['id'])
- waiters.wait_for_server_status(self.servers_client,
- self.server['id'], 'PAUSED')
- self._check_network_connectivity(should_connect=False)
- self.servers_client.unpause_server(self.server['id'])
- self._wait_server_status_and_check_network_connectivity()
+ server, keypair, floating_ip = self._setup_network_and_servers()
+ self.servers_client.pause_server(server['id'])
+ waiters.wait_for_server_status(self.servers_client, server['id'],
+ 'PAUSED')
+ self._check_network_connectivity(server, keypair, floating_ip,
+ should_connect=False)
+ self.servers_client.unpause_server(server['id'])
+ self._wait_server_status_and_check_network_connectivity(
+ server, keypair, floating_ip)
@test.idempotent_id('5cdf9499-541d-4923-804e-b9a60620a7f0')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.services('compute', 'network')
def test_server_connectivity_suspend_resume(self):
- self._setup_network_and_servers()
- self.servers_client.suspend_server(self.server['id'])
- waiters.wait_for_server_status(self.servers_client, self.server['id'],
+ server, keypair, floating_ip = self._setup_network_and_servers()
+ self.servers_client.suspend_server(server['id'])
+ waiters.wait_for_server_status(self.servers_client, server['id'],
'SUSPENDED')
- self._check_network_connectivity(should_connect=False)
- self.servers_client.resume_server(self.server['id'])
- self._wait_server_status_and_check_network_connectivity()
+ self._check_network_connectivity(server, keypair, floating_ip,
+ should_connect=False)
+ self.servers_client.resume_server(server['id'])
+ self._wait_server_status_and_check_network_connectivity(
+ server, keypair, floating_ip)
@test.idempotent_id('719eb59d-2f42-4b66-b8b1-bb1254473967')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
@@ -159,10 +171,11 @@
if resize_flavor == CONF.compute.flavor_ref:
msg = "Skipping test - flavor_ref and flavor_ref_alt are identical"
raise self.skipException(msg)
- self._setup_network_and_servers()
- self.servers_client.resize_server(self.server['id'],
+ server, keypair, floating_ip = self._setup_network_and_servers()
+ self.servers_client.resize_server(server['id'],
flavor_ref=resize_flavor)
- waiters.wait_for_server_status(self.servers_client, self.server['id'],
+ waiters.wait_for_server_status(self.servers_client, server['id'],
'VERIFY_RESIZE')
- self.servers_client.confirm_resize_server(self.server['id'])
- self._wait_server_status_and_check_network_connectivity()
+ self.servers_client.confirm_resize_server(server['id'])
+ self._wait_server_status_and_check_network_connectivity(
+ server, keypair, floating_ip)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 8ca5e72..31ccd5b 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -658,6 +658,7 @@
self.assertEqual('', port['device_id'])
self.assertEqual('', port['device_owner'])
+ @test.requires_ext(service='network', extension='l3_agent_scheduler')
@test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
@test.services('compute', 'network')
def test_router_rescheduling(self):
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index a9394cb..3df92cf 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -143,8 +143,9 @@
self._list_ports(device_id=sid,
network_id=self.network_v6.id)]
self.assertEqual(1, len(ports),
- message="Multiple IPv6 ports found on network %s"
- % self.network_v6)
+ message=("Multiple IPv6 ports found on network %s. "
+ "ports: %s")
+ % (self.network_v6, ports))
mac6 = ports[0]
ssh.turn_nic_on(ssh.get_nic_name(mac6))
diff --git a/tempest/scenario/test_swift_basic_ops.py b/tempest/scenario/test_object_storage_basic_ops.py
similarity index 97%
rename from tempest/scenario/test_swift_basic_ops.py
rename to tempest/scenario/test_object_storage_basic_ops.py
index 69e0c4c..49768c5 100644
--- a/tempest/scenario/test_swift_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -24,7 +24,7 @@
LOG = logging.getLogger(__name__)
-class TestSwiftBasicOps(manager.SwiftScenarioTest):
+class TestObjectStorageBasicOps(manager.ObjectStorageScenarioTest):
"""
Test swift basic ops.
* get swift stat.
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_object_storage_telemetry_middleware.py
similarity index 95%
rename from tempest/scenario/test_swift_telemetry_middleware.py
rename to tempest/scenario/test_object_storage_telemetry_middleware.py
index c5a0e7c..3376a7c 100644
--- a/tempest/scenario/test_swift_telemetry_middleware.py
+++ b/tempest/scenario/test_object_storage_telemetry_middleware.py
@@ -34,7 +34,7 @@
NOTIFICATIONS_SLEEP = 1
-class TestSwiftTelemetry(manager.SwiftScenarioTest):
+class TestObjectStorageTelemetry(manager.ObjectStorageScenarioTest):
"""
Test that swift uses the ceilometer middleware.
* create container.
@@ -45,7 +45,7 @@
@classmethod
def skip_checks(cls):
- super(TestSwiftTelemetry, cls).skip_checks()
+ super(TestObjectStorageTelemetry, cls).skip_checks()
if not CONF.service_available.ceilometer:
skip_msg = ("%s skipped as ceilometer is not available" %
cls.__name__)
@@ -53,7 +53,7 @@
@classmethod
def setup_clients(cls):
- super(TestSwiftTelemetry, cls).setup_clients()
+ super(TestObjectStorageTelemetry, cls).setup_clients()
cls.telemetry_client = cls.os_operator.telemetry_client
def _confirm_notifications(self, container_name, obj_name):
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 9afb598..3c11c22 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -244,10 +244,13 @@
{'uuid': tenant.network.id},
],
'key_name': tenant.keypair['name'],
- 'security_groups': security_groups_names,
- 'network_client': tenant.manager.network_client
+ 'security_groups': security_groups_names
}
- server = self.create_server(name=name, create_kwargs=create_kwargs)
+ server = self.create_server(
+ name=name,
+ network_client=tenant.manager.network_client,
+ networks_client=tenant.manager.networks_client,
+ create_kwargs=create_kwargs)
self.assertEqual(
sorted([s['name'] for s in security_groups]),
sorted([s['name'] for s in server['security_groups']]))
@@ -287,7 +290,9 @@
def _create_tenant_network(self, tenant):
network, subnet, router = self.create_networks(
- client=tenant.manager.network_client)
+ client=tenant.manager.network_client,
+ networks_client=tenant.manager.networks_client,
+ subnets_client=tenant.manager.subnets_client)
tenant.set_network(network, subnet, router)
def _set_compute_context(self, tenant):
@@ -552,3 +557,44 @@
username=ssh_login,
private_key=private_key,
should_connect=True)
+
+ @test.requires_ext(service='network', extension='port-security')
+ @test.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
+ @test.services('compute', 'network')
+ def test_port_security_disable_security_group(self):
+ """
+ This test verifies port_security_enabled=False disables
+ the default security group rules.
+ """
+ new_tenant = self.primary_tenant
+
+ # Create server
+ name = 'server-{tenant}-gen-1'.format(
+ tenant=new_tenant.creds.tenant_name
+ )
+ name = data_utils.rand_name(name)
+ server = self._create_server(name, new_tenant)
+
+ access_point_ssh = self._connect_to_access_point(new_tenant)
+ server_id = server['id']
+ port_id = self._list_ports(device_id=server_id)[0]['id']
+
+ # Flip the port's port security and check connectivity
+ try:
+ self.network_client.update_port(port_id,
+ port_security_enabled=True,
+ security_groups=[])
+ self._check_connectivity(access_point=access_point_ssh,
+ ip=self._get_server_ip(server),
+ should_succeed=False)
+
+ self.network_client.update_port(port_id,
+ port_security_enabled=False,
+ security_groups=[])
+ self._check_connectivity(
+ access_point=access_point_ssh,
+ ip=self._get_server_ip(server))
+ except Exception:
+ for tenant in self.tenants.values():
+ self._log_console_output(servers=tenant.servers)
+ raise
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 0f27cd1..e2f8adb 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import json
+
from oslo_log import log as logging
from tempest import config
@@ -39,6 +41,7 @@
* Launch an instance
* Perform ssh to instance
* Verify metadata service
+ * Verify metadata on config_drive
* Terminate the instance
"""
@@ -72,9 +75,12 @@
def boot_instance(self):
# Create server with image and flavor from input scenario
security_groups = [{'name': self.security_group['name']}]
+ self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
create_kwargs = {
'key_name': self.keypair['name'],
- 'security_groups': security_groups
+ 'security_groups': security_groups,
+ 'config_drive': CONF.compute_feature_enabled.config_drive,
+ 'metadata': self.md
}
self.instance = self.create_server(image=self.image_ref,
flavor=self.flavor_ref,
@@ -119,6 +125,22 @@
'verify metadata on server. '
'%s is empty.' % md_url)
+ def verify_metadata_on_config_drive(self):
+ if self.run_ssh and CONF.compute_feature_enabled.config_drive:
+ # Verify metadata on config_drive
+ cmd_blkid = 'blkid -t LABEL=config-2 -o device'
+ dev_name = self.ssh_client.exec_command(cmd_blkid)
+ dev_name = dev_name.rstrip()
+ self.ssh_client.exec_command('sudo mount %s /mnt' % dev_name)
+ cmd_md = 'sudo cat /mnt/openstack/latest/meta_data.json'
+ result = self.ssh_client.exec_command(cmd_md)
+ self.ssh_client.exec_command('sudo umount /mnt')
+ result = json.loads(result)
+ self.assertIn('meta', result)
+ msg = ('Failed while verifying metadata on config_drive on server.'
+ ' Result of command "%s" is NOT "%s".' % (cmd_md, self.md))
+ self.assertEqual(self.md, result['meta'], msg)
+
@test.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
@test.attr(type='smoke')
@test.services('compute', 'network')
@@ -128,4 +150,5 @@
self.boot_instance()
self.verify_ssh()
self.verify_metadata()
+ self.verify_metadata_on_config_drive()
self.servers_client.delete_server(self.instance['id'])
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 022306e..bc80412 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -30,23 +30,13 @@
"""
This test shelves then unshelves a Nova instance
The following is the scenario outline:
- * boot a instance and create a timestamp file in it
+ * boot an instance and create a timestamp file in it
* shelve the instance
* unshelve the instance
* check the existence of the timestamp file in the unshelved instance
"""
- def _write_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- ssh_client.exec_command('date > /tmp/timestamp; sync')
- self.timestamp = ssh_client.exec_command('cat /tmp/timestamp')
-
- def _check_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- got_timestamp = ssh_client.exec_command('cat /tmp/timestamp')
- self.assertEqual(self.timestamp, got_timestamp)
-
def _shelve_then_unshelve_server(self, server):
self.servers_client.shelve_server(server['id'])
offload_time = CONF.compute.shelved_offload_time
@@ -64,22 +54,29 @@
waiters.wait_for_server_status(self.servers_client, server['id'],
'ACTIVE')
- @test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
- @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
- 'Shelve is not available.')
- @test.services('compute', 'network', 'image')
- def test_shelve_instance(self):
- self.keypair = self.create_keypair()
+ def _create_server_then_shelve_and_unshelve(self, boot_from_volume=False):
+ keypair = self.create_keypair()
- self.security_group = self._create_security_group()
- security_groups = [{'name': self.security_group['name']}]
-
+ security_group = self._create_security_group()
+ security_groups = [{'name': security_group['name']}]
create_kwargs = {
- 'key_name': self.keypair['name'],
+ 'key_name': keypair['name'],
'security_groups': security_groups
}
- server = self.create_server(image=CONF.compute.image_ref,
- create_kwargs=create_kwargs)
+
+ if boot_from_volume:
+ volume = self.create_volume(size=CONF.volume.volume_size,
+ imageRef=CONF.compute.image_ref)
+ bd_map = [{
+ 'device_name': 'vda',
+ 'volume_id': volume['id'],
+ 'delete_on_termination': '0'}]
+
+ create_kwargs['block_device_mapping'] = bd_map
+ server = self.create_server(create_kwargs=create_kwargs)
+ else:
+ server = self.create_server(image=CONF.compute.image_ref,
+ create_kwargs=create_kwargs)
if CONF.compute.use_floatingip_for_ssh:
floating_ip = (self.floating_ips_client.create_floating_ip()
@@ -89,15 +86,34 @@
floating_ip['id'])
self.floating_ips_client.associate_floating_ip_to_server(
floating_ip['ip'], server['id'])
- self._write_timestamp(floating_ip['ip'])
+ timestamp = self.create_timestamp(
+ floating_ip['ip'], private_key=keypair['private_key'])
else:
- self._write_timestamp(server)
+ timestamp = self.create_timestamp(
+ server, private_key=keypair['private_key'])
# Prevent bug #1257594 from coming back
# Unshelve used to boot the instance with the original image, not
# with the instance snapshot
self._shelve_then_unshelve_server(server)
if CONF.compute.use_floatingip_for_ssh:
- self._check_timestamp(floating_ip['ip'])
+ timestamp2 = self.get_timestamp(floating_ip['ip'],
+ private_key=keypair['private_key'])
else:
- self._check_timestamp(server)
+ timestamp2 = self.get_timestamp(server,
+ private_key=keypair['private_key'])
+ self.assertEqual(timestamp, timestamp2)
+
+ @test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
+ @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+ 'Shelve is not available.')
+ @test.services('compute', 'network', 'image')
+ def test_shelve_instance(self):
+ self._create_server_then_shelve_and_unshelve()
+
+ @test.idempotent_id('c1b6318c-b9da-490b-9c67-9339b627271f')
+ @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+ 'Shelve is not available.')
+ @test.services('compute', 'volume', 'network', 'image')
+ def test_shelve_volume_backed_instance(self):
+ self._create_server_then_shelve_and_unshelve(boot_from_volume=True)
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 1298faa..5ac3a7e 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -29,60 +29,54 @@
"""
This test is for snapshotting an instance and booting with it.
The following is the scenario outline:
- * boot a instance and create a timestamp file in it
+ * boot an instance and create a timestamp file in it
* snapshot the instance
* boot a second instance from the snapshot
* check the existence of the timestamp file in the second instance
"""
- def _boot_image(self, image_id):
- security_groups = [{'name': self.security_group['name']}]
+ def _boot_image(self, image_id, keypair, security_group):
+ security_groups = [{'name': security_group['name']}]
create_kwargs = {
- 'key_name': self.keypair['name'],
+ 'key_name': keypair['name'],
'security_groups': security_groups
}
return self.create_server(image=image_id, create_kwargs=create_kwargs)
- def _add_keypair(self):
- self.keypair = self.create_keypair()
-
- def _write_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- ssh_client.exec_command('date > /tmp/timestamp; sync')
- self.timestamp = ssh_client.exec_command('cat /tmp/timestamp')
-
- def _check_timestamp(self, server_or_ip):
- ssh_client = self.get_remote_client(server_or_ip)
- got_timestamp = ssh_client.exec_command('cat /tmp/timestamp')
- self.assertEqual(self.timestamp, got_timestamp)
-
@test.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@test.services('compute', 'network', 'image')
def test_snapshot_pattern(self):
- # prepare for booting a instance
- self._add_keypair()
- self.security_group = self._create_security_group()
+ # prepare for booting an instance
+ keypair = self.create_keypair()
+ security_group = self._create_security_group()
- # boot a instance and create a timestamp file in it
- server = self._boot_image(CONF.compute.image_ref)
+ # boot an instance and create a timestamp file in it
+ server = self._boot_image(CONF.compute.image_ref, keypair,
+ security_group)
if CONF.compute.use_floatingip_for_ssh:
fip_for_server = self.create_floating_ip(server)
- self._write_timestamp(fip_for_server['ip'])
+ timestamp = self.create_timestamp(
+ fip_for_server['ip'], private_key=keypair['private_key'])
else:
- self._write_timestamp(server)
+ timestamp = self.create_timestamp(
+ server, private_key=keypair['private_key'])
# snapshot the instance
snapshot_image = self.create_server_snapshot(server=server)
# boot a second instance from the snapshot
- server_from_snapshot = self._boot_image(snapshot_image['id'])
+ server_from_snapshot = self._boot_image(snapshot_image['id'],
+ keypair, security_group)
# check the existence of the timestamp file in the second instance
if CONF.compute.use_floatingip_for_ssh:
fip_for_snapshot = self.create_floating_ip(server_from_snapshot)
- self._check_timestamp(fip_for_snapshot['ip'])
+ timestamp2 = self.get_timestamp(fip_for_snapshot['ip'],
+ private_key=keypair['private_key'])
else:
- self._check_timestamp(server_from_snapshot)
+ timestamp2 = self.get_timestamp(server_from_snapshot,
+ private_key=keypair['private_key'])
+ self.assertEqual(timestamp, timestamp2)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 5f1e7fe..6eceeb2 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -63,23 +63,17 @@
self.snapshots_client.wait_for_snapshot_status(volume_snapshot['id'],
status)
- def _boot_image(self, image_id):
- security_groups = [{'name': self.security_group['name']}]
+ def _boot_image(self, image_id, keypair, security_group):
+ security_groups = [{'name': security_group['name']}]
create_kwargs = {
- 'key_name': self.keypair['name'],
+ 'key_name': keypair['name'],
'security_groups': security_groups
}
return self.create_server(image=image_id, create_kwargs=create_kwargs)
- def _add_keypair(self):
- self.keypair = self.create_keypair()
-
- def _ssh_to_server(self, server_or_ip):
- return self.get_remote_client(server_or_ip)
-
def _create_volume_snapshot(self, volume):
snapshot_name = data_utils.rand_name('scenario-snapshot')
- _, snapshot = self.snapshots_client.create_snapshot(
+ snapshot = self.snapshots_client.create_snapshot(
volume['id'], display_name=snapshot_name)['snapshot']
def cleaner():
@@ -114,8 +108,9 @@
self.servers_client.detach_volume(server['id'], volume['id'])
self._wait_for_volume_status(volume, 'available')
- def _wait_for_volume_available_on_the_system(self, server_or_ip):
- ssh = self.get_remote_client(server_or_ip)
+ def _wait_for_volume_available_on_the_system(self, server_or_ip,
+ private_key):
+ ssh = self.get_remote_client(server_or_ip, private_key=private_key)
def _func():
part = ssh.get_partitions()
@@ -127,36 +122,20 @@
CONF.compute.build_interval):
raise exceptions.TimeoutException
- def _create_timestamp(self, server_or_ip):
- ssh_client = self._ssh_to_server(server_or_ip)
- ssh_client.exec_command('sudo /usr/sbin/mkfs.ext4 /dev/%s'
- % CONF.compute.volume_device_name)
- ssh_client.exec_command('sudo mount /dev/%s /mnt'
- % CONF.compute.volume_device_name)
- ssh_client.exec_command('sudo sh -c "date > /mnt/timestamp;sync"')
- self.timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
- ssh_client.exec_command('sudo umount /mnt')
-
- def _check_timestamp(self, server_or_ip):
- ssh_client = self._ssh_to_server(server_or_ip)
- ssh_client.exec_command('sudo mount /dev/%s /mnt'
- % CONF.compute.volume_device_name)
- got_timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
- self.assertEqual(self.timestamp, got_timestamp)
-
@decorators.skip_because(bug="1205344")
@test.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@tempest.test.services('compute', 'network', 'volume', 'image')
def test_stamp_pattern(self):
- # prepare for booting a instance
- self._add_keypair()
- self.security_group = self._create_security_group()
+ # prepare for booting an instance
+ keypair = self.create_keypair()
+ security_group = self._create_security_group()
# boot an instance and create a timestamp file in it
volume = self._create_volume()
- server = self._boot_image(CONF.compute.image_ref)
+ server = self._boot_image(CONF.compute.image_ref, keypair,
+ security_group)
# create and add floating IP to server1
if CONF.compute.use_floatingip_for_ssh:
@@ -166,8 +145,11 @@
ip_for_server = server
self._attach_volume(server, volume)
- self._wait_for_volume_available_on_the_system(ip_for_server)
- self._create_timestamp(ip_for_server)
+ self._wait_for_volume_available_on_the_system(ip_for_server,
+ keypair['private_key'])
+ timestamp = self.create_timestamp(ip_for_server,
+ CONF.compute.volume_device_name,
+ private_key=keypair['private_key'])
self._detach_volume(server, volume)
# snapshot the volume
@@ -181,7 +163,8 @@
snapshot_id=volume_snapshot['id'])
# boot second instance from the snapshot(instance2)
- server_from_snapshot = self._boot_image(snapshot_image['id'])
+ server_from_snapshot = self._boot_image(snapshot_image['id'],
+ keypair, security_group)
# create and add floating IP to server_from_snapshot
if CONF.compute.use_floatingip_for_ssh:
@@ -193,7 +176,11 @@
# attach volume2 to instance2
self._attach_volume(server_from_snapshot, volume_from_snapshot)
- self._wait_for_volume_available_on_the_system(ip_for_snapshot)
+ self._wait_for_volume_available_on_the_system(ip_for_snapshot,
+ keypair['private_key'])
# check the existence of the timestamp file in the volume2
- self._check_timestamp(ip_for_snapshot)
+ timestamp2 = self.get_timestamp(ip_for_snapshot,
+ CONF.compute.volume_device_name,
+ private_key=keypair['private_key'])
+ self.assertEqual(timestamp, timestamp2)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index ba419a6..d4bddc0 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -96,14 +96,6 @@
vol_name = data_utils.rand_name('volume')
return self.create_volume(name=vol_name, snapshot_id=snap_id)
- def _stop_instances(self, instances):
- # NOTE(gfidente): two loops so we do not wait for the status twice
- for i in instances:
- self.servers_client.stop_server(i['id'])
- for i in instances:
- waiters.wait_for_server_status(self.servers_client,
- i['id'], 'SHUTOFF')
-
def _ssh_to_server(self, server, keypair):
if CONF.compute.use_floatingip_for_ssh:
ip = self.create_floating_ip(server)['ip']
@@ -172,10 +164,6 @@
ssh_client = self._ssh_to_server(instance_from_snapshot, keypair)
self._check_content_of_written_file(ssh_client, text)
- # NOTE(gfidente): ensure resources are in clean state for
- # deletion operations to succeed
- self._stop_instances([instance_2nd, instance_from_snapshot])
-
@decorators.skip_because(bug='1489581')
@test.idempotent_id('36c34c67-7b54-4b59-b188-02a2f458a63b')
@test.services('compute', 'volume', 'image')
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 0a7d492..12509f7 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -19,13 +19,13 @@
from oslo_serialization import jsonutils as json
from tempest_lib.common.utils import misc
+from tempest_lib import exceptions as exc_lib
import testscenarios
import testtools
from tempest import clients
from tempest.common import credentials
from tempest import config
-from tempest import exceptions
CONF = config.CONF
@@ -91,8 +91,8 @@
def test_create_server_metadata(self):
name = rand_name('instance')
self.servers_client.create_server(name=name,
- flavor_ref=self.flavor_ref,
- image_ref=self.image_ref)
+ flavorRef=self.flavor_ref,
+ imageRef=self.image_ref)
"""
validchars = "-_.{ascii}{digit}".format(ascii=string.ascii_letters,
digit=string.digits)
@@ -104,11 +104,11 @@
'subnet': False,
'dhcp': False,
}
- self.isolated_creds = credentials.get_isolated_credentials(
+ self.cred_provider = credentials.get_credentials_provider(
name='InputScenarioUtils',
identity_version=CONF.identity.auth_version,
network_resources=network_resources)
- os = clients.Manager(self.isolated_creds.get_primary_creds())
+ os = clients.Manager(self.cred_provider.get_primary_creds())
self.images_client = os.images_client
self.flavors_client = os.flavors_client
self.image_pattern = CONF.input_scenario.image_regex
@@ -120,7 +120,7 @@
return nname
def clear_creds(self):
- self.isolated_creds.clear_isolated_creds()
+ self.cred_provider.clear_creds()
@property
def scenario_images(self):
@@ -174,7 +174,7 @@
scenario_utils = InputScenarioUtils()
scenario_flavor = scenario_utils.scenario_flavors
scenario_image = scenario_utils.scenario_images
- except (exceptions.InvalidConfiguration, TypeError):
+ except (exc_lib.InvalidCredentials, TypeError):
output = standard_tests
finally:
if scenario_utils:
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index ede464f..bedb9ec 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -94,14 +94,15 @@
:return: EC2 credentials
"""
ec2_cred_list = identity_client.list_user_ec2_credentials(
- identity_client.user_id)
+ identity_client.user_id)['credentials']
for cred in ec2_cred_list:
if cred['tenant_id'] == identity_client.tenant_id:
ec2_cred = cred
break
else:
- ec2_cred = identity_client.create_user_ec2_credentials(
+ ec2_cred = (identity_client.create_user_ec2_credentials(
identity_client.user_id, identity_client.tenant_id)
+ ['credential'])
if not all((ec2_cred, ec2_cred['access'], ec2_cred['secret'])):
raise lib_exc.NotFound("Unable to get access and secret keys")
else:
diff --git a/tempest/services/compute/json/agents_client.py b/tempest/services/compute/json/agents_client.py
deleted file mode 100644
index d38c8cd..0000000
--- a/tempest/services/compute/json/agents_client.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2014 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 oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.api_schema.response.compute.v2_1 import agents as schema
-from tempest.common import service_client
-
-
-class AgentsClient(service_client.ServiceClient):
- """
- Tests Agents API
- """
-
- def list_agents(self, **params):
- """List all agent builds."""
- url = 'os-agents'
- if params:
- url += '?%s' % urllib.urlencode(params)
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_agents, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def create_agent(self, **kwargs):
- """Create an agent build."""
- post_body = json.dumps({'agent': kwargs})
- resp, body = self.post('os-agents', post_body)
- body = json.loads(body)
- self.validate_response(schema.create_agent, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_agent(self, agent_id):
- """Delete an existing agent build."""
- resp, body = self.delete("os-agents/%s" % agent_id)
- self.validate_response(schema.delete_agent, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_agent(self, agent_id, **kwargs):
- """Update an agent build."""
- put_body = json.dumps({'para': kwargs})
- resp, body = self.put('os-agents/%s' % agent_id, put_body)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/aggregates_client.py b/tempest/services/compute/json/aggregates_client.py
deleted file mode 100644
index c9895db..0000000
--- a/tempest/services/compute/json/aggregates_client.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2013 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 oslo_serialization import jsonutils as json
-from tempest_lib import exceptions as lib_exc
-
-from tempest.api_schema.response.compute.v2_1 import aggregates as schema
-from tempest.common import service_client
-
-
-class AggregatesClient(service_client.ServiceClient):
-
- def list_aggregates(self):
- """Get aggregate list."""
- resp, body = self.get("os-aggregates")
- body = json.loads(body)
- self.validate_response(schema.list_aggregates, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_aggregate(self, aggregate_id):
- """Get details of the given aggregate."""
- resp, body = self.get("os-aggregates/%s" % aggregate_id)
- body = json.loads(body)
- self.validate_response(schema.get_aggregate, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def create_aggregate(self, **kwargs):
- """Creates a new aggregate."""
- post_body = json.dumps({'aggregate': kwargs})
- resp, body = self.post('os-aggregates', post_body)
-
- body = json.loads(body)
- self.validate_response(schema.create_aggregate, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_aggregate(self, aggregate_id, **kwargs):
- """Update a aggregate."""
- put_body = json.dumps({'aggregate': kwargs})
- resp, body = self.put('os-aggregates/%s' % aggregate_id, put_body)
-
- body = json.loads(body)
- self.validate_response(schema.update_aggregate, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_aggregate(self, aggregate_id):
- """Deletes the given aggregate."""
- resp, body = self.delete("os-aggregates/%s" % aggregate_id)
- self.validate_response(schema.delete_aggregate, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def is_resource_deleted(self, id):
- try:
- self.show_aggregate(id)
- except lib_exc.NotFound:
- return True
- return False
-
- @property
- def resource_type(self):
- """Returns the primary type of resource this client works with."""
- return 'aggregate'
-
- def add_host(self, aggregate_id, **kwargs):
- """Adds a host to the given aggregate."""
- post_body = json.dumps({'add_host': kwargs})
- resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
- post_body)
- body = json.loads(body)
- self.validate_response(schema.aggregate_add_remove_host, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def remove_host(self, aggregate_id, **kwargs):
- """Removes a host from the given aggregate."""
- post_body = json.dumps({'remove_host': kwargs})
- resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
- post_body)
- body = json.loads(body)
- self.validate_response(schema.aggregate_add_remove_host, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def set_metadata(self, aggregate_id, **kwargs):
- """Replaces the aggregate's existing metadata with new metadata."""
- post_body = json.dumps({'set_metadata': kwargs})
- resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
- post_body)
- body = json.loads(body)
- self.validate_response(schema.aggregate_set_metadata, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/availability_zone_client.py b/tempest/services/compute/json/availability_zone_client.py
deleted file mode 100644
index 0012637..0000000
--- a/tempest/services/compute/json/availability_zone_client.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2013 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 oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import availability_zone \
- as schema
-from tempest.common import service_client
-
-
-class AvailabilityZoneClient(service_client.ServiceClient):
-
- def list_availability_zones(self, detail=False):
- url = 'os-availability-zone'
- schema_list = schema.list_availability_zone_list
- if detail:
- url += '/detail'
- schema_list = schema.list_availability_zone_list_detail
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema_list, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/baremetal_nodes_client.py b/tempest/services/compute/json/baremetal_nodes_client.py
deleted file mode 100644
index 15f883a..0000000
--- a/tempest/services/compute/json/baremetal_nodes_client.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# 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 oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.api_schema.response.compute.v2_1 import baremetal_nodes \
- as schema
-from tempest.common import service_client
-
-
-class BaremetalNodesClient(service_client.ServiceClient):
- """
- Tests Baremetal API
- """
-
- def list_baremetal_nodes(self, **params):
- """List all baremetal nodes."""
- url = 'os-baremetal-nodes'
- if params:
- url += '?%s' % urllib.urlencode(params)
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_baremetal_nodes, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_baremetal_node(self, baremetal_node_id):
- """Returns the details of a single baremetal node."""
- url = 'os-baremetal-nodes/%s' % baremetal_node_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_baremetal_node, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
deleted file mode 100644
index d6c72f4..0000000
--- a/tempest/services/compute/json/certificates_client.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2013 IBM Corp
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import certificates as schema
-from tempest.common import service_client
-
-
-class CertificatesClient(service_client.ServiceClient):
-
- def show_certificate(self, certificate_id):
- url = "os-certificates/%s" % certificate_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_certificate, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def create_certificate(self):
- """create certificates."""
- url = "os-certificates"
- resp, body = self.post(url, None)
- body = json.loads(body)
- self.validate_response(schema.create_certificate, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/extensions_client.py b/tempest/services/compute/json/extensions_client.py
deleted file mode 100644
index 4741812..0000000
--- a/tempest/services/compute/json/extensions_client.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# 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 oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import extensions as schema
-from tempest.common import service_client
-
-
-class ExtensionsClient(service_client.ServiceClient):
-
- def list_extensions(self):
- url = 'extensions'
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_extensions, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_extension(self, extension_alias):
- resp, body = self.get('extensions/%s' % extension_alias)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
deleted file mode 100644
index 23401c3..0000000
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2013 IBM Corp
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import fixed_ips as schema
-from tempest.common import service_client
-
-
-class FixedIPsClient(service_client.ServiceClient):
-
- def show_fixed_ip(self, fixed_ip):
- url = "os-fixed-ips/%s" % fixed_ip
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_fixed_ip, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def reserve_fixed_ip(self, fixed_ip, **kwargs):
- """This reserves and unreserves fixed ips."""
- url = "os-fixed-ips/%s/action" % fixed_ip
- resp, body = self.post(url, json.dumps(kwargs))
- self.validate_response(schema.reserve_fixed_ip, resp, body)
- return service_client.ResponseBody(resp)
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
deleted file mode 100644
index 2c32d30..0000000
--- a/tempest/services/compute/json/flavors_client.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# 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 oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.api_schema.response.compute.v2_1 import flavors as schema
-from tempest.api_schema.response.compute.v2_1 import flavors_access \
- as schema_access
-from tempest.api_schema.response.compute.v2_1 import flavors_extra_specs \
- as schema_extra_specs
-from tempest.common import service_client
-
-
-class FlavorsClient(service_client.ServiceClient):
-
- def list_flavors(self, detail=False, **params):
- url = 'flavors'
- _schema = schema.list_flavors
-
- if detail:
- url += '/detail'
- _schema = schema.list_flavors_details
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(_schema, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_flavor(self, flavor_id):
- resp, body = self.get("flavors/%s" % flavor_id)
- body = json.loads(body)
- self.validate_response(schema.create_get_flavor_details, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def create_flavor(self, **kwargs):
- """Creates a new flavor or instance type.
- Most parameters except the following are passed to the API without
- any changes.
- :param ephemeral: The name is changed to OS-FLV-EXT-DATA:ephemeral
- :param is_public: The name is changed to os-flavor-access:is_public
- """
- if kwargs.get('ephemeral'):
- kwargs['OS-FLV-EXT-DATA:ephemeral'] = kwargs.pop('ephemeral')
- if kwargs.get('is_public'):
- kwargs['os-flavor-access:is_public'] = kwargs.pop('is_public')
-
- post_body = json.dumps({'flavor': kwargs})
- resp, body = self.post('flavors', post_body)
-
- body = json.loads(body)
- self.validate_response(schema.create_get_flavor_details, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_flavor(self, flavor_id):
- """Deletes the given flavor."""
- resp, body = self.delete("flavors/{0}".format(flavor_id))
- self.validate_response(schema.delete_flavor, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def is_resource_deleted(self, id):
- # Did not use show_flavor(id) for verification as it gives
- # 200 ok even for deleted id. LP #981263
- # we can remove the loop here and use get by ID when bug gets sortedout
- flavors = self.list_flavors(detail=True)['flavors']
- for flavor in flavors:
- if flavor['id'] == id:
- return False
- return True
-
- @property
- def resource_type(self):
- """Returns the primary type of resource this client works with."""
- return 'flavor'
-
- def set_flavor_extra_spec(self, flavor_id, **kwargs):
- """Sets extra Specs to the mentioned flavor."""
- post_body = json.dumps({'extra_specs': kwargs})
- resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
- post_body)
- body = json.loads(body)
- self.validate_response(schema_extra_specs.set_get_flavor_extra_specs,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_flavor_extra_specs(self, flavor_id):
- """Gets extra Specs details of the mentioned flavor."""
- resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id)
- body = json.loads(body)
- self.validate_response(schema_extra_specs.set_get_flavor_extra_specs,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_flavor_extra_spec(self, flavor_id, key):
- """Gets extra Specs key-value of the mentioned flavor and key."""
- resp, body = self.get('flavors/%s/os-extra_specs/%s' % (flavor_id,
- key))
- body = json.loads(body)
- self.validate_response(
- schema_extra_specs.set_get_flavor_extra_specs_key,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
- """Update specified extra Specs of the mentioned flavor and key."""
- resp, body = self.put('flavors/%s/os-extra_specs/%s' %
- (flavor_id, key), json.dumps(kwargs))
- body = json.loads(body)
- self.validate_response(
- schema_extra_specs.set_get_flavor_extra_specs_key,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def unset_flavor_extra_spec(self, flavor_id, key):
- """Unsets extra Specs from the mentioned flavor."""
- resp, body = self.delete('flavors/%s/os-extra_specs/%s' %
- (flavor_id, key))
- self.validate_response(schema.unset_flavor_extra_specs, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_flavor_access(self, flavor_id):
- """Gets flavor access information given the flavor id."""
- resp, body = self.get('flavors/%s/os-flavor-access' % flavor_id)
- body = json.loads(body)
- self.validate_response(schema_access.add_remove_list_flavor_access,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def add_flavor_access(self, flavor_id, tenant_id):
- """Add flavor access for the specified tenant."""
- post_body = {
- 'addTenantAccess': {
- 'tenant': tenant_id
- }
- }
- post_body = json.dumps(post_body)
- resp, body = self.post('flavors/%s/action' % flavor_id, post_body)
- body = json.loads(body)
- self.validate_response(schema_access.add_remove_list_flavor_access,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def remove_flavor_access(self, flavor_id, tenant_id):
- """Remove flavor access from the specified tenant."""
- post_body = {
- 'removeTenantAccess': {
- 'tenant': tenant_id
- }
- }
- post_body = json.dumps(post_body)
- resp, body = self.post('flavors/%s/action' % flavor_id, post_body)
- body = json.loads(body)
- self.validate_response(schema_access.add_remove_list_flavor_access,
- resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/floating_ip_pools_client.py b/tempest/services/compute/json/floating_ip_pools_client.py
deleted file mode 100644
index c83537a..0000000
--- a/tempest/services/compute/json/floating_ip_pools_client.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# 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 oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.api_schema.response.compute.v2_1 import floating_ips as schema
-from tempest.common import service_client
-
-
-class FloatingIPPoolsClient(service_client.ServiceClient):
-
- def list_floating_ip_pools(self, params=None):
- """Gets all floating IP Pools list."""
- url = 'os-floating-ip-pools'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_floating_ip_pools, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/floating_ips_bulk_client.py b/tempest/services/compute/json/floating_ips_bulk_client.py
deleted file mode 100644
index dfe69f0..0000000
--- a/tempest/services/compute/json/floating_ips_bulk_client.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# 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 oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import floating_ips as schema
-from tempest.common import service_client
-
-
-class FloatingIPsBulkClient(service_client.ServiceClient):
-
- def create_floating_ips_bulk(self, ip_range, pool, interface):
- """Allocate floating IPs in bulk."""
- post_body = {
- 'ip_range': ip_range,
- 'pool': pool,
- 'interface': interface
- }
- post_body = json.dumps({'floating_ips_bulk_create': post_body})
- resp, body = self.post('os-floating-ips-bulk', post_body)
- body = json.loads(body)
- self.validate_response(schema.create_floating_ips_bulk, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_floating_ips_bulk(self):
- """Gets all floating IPs in bulk."""
- resp, body = self.get('os-floating-ips-bulk')
- body = json.loads(body)
- self.validate_response(schema.list_floating_ips_bulk, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_floating_ips_bulk(self, ip_range):
- """Deletes the provided floating IPs in bulk."""
- post_body = json.dumps({'ip_range': ip_range})
- resp, body = self.put('os-floating-ips-bulk/delete', post_body)
- body = json.loads(body)
- self.validate_response(schema.delete_floating_ips_bulk, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/hosts_client.py b/tempest/services/compute/json/hosts_client.py
deleted file mode 100644
index 3d3cb18..0000000
--- a/tempest/services/compute/json/hosts_client.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright 2013 IBM Corp.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.api_schema.response.compute.v2_1 import hosts as schema
-from tempest.common import service_client
-
-
-class HostsClient(service_client.ServiceClient):
-
- def list_hosts(self, **params):
- """Lists all hosts."""
-
- url = 'os-hosts'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_hosts, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_host(self, hostname):
- """Show detail information for the host."""
-
- resp, body = self.get("os-hosts/%s" % hostname)
- body = json.loads(body)
- self.validate_response(schema.get_host_detail, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_host(self, hostname, **kwargs):
- """Update a host."""
-
- request_body = {
- 'status': None,
- 'maintenance_mode': None,
- }
- request_body.update(**kwargs)
- request_body = json.dumps(request_body)
-
- resp, body = self.put("os-hosts/%s" % hostname, request_body)
- body = json.loads(body)
- self.validate_response(schema.update_host, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def startup_host(self, hostname):
- """Startup a host."""
-
- resp, body = self.get("os-hosts/%s/startup" % hostname)
- body = json.loads(body)
- self.validate_response(schema.startup_host, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def shutdown_host(self, hostname):
- """Shutdown a host."""
-
- resp, body = self.get("os-hosts/%s/shutdown" % hostname)
- body = json.loads(body)
- self.validate_response(schema.shutdown_host, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def reboot_host(self, hostname):
- """reboot a host."""
-
- resp, body = self.get("os-hosts/%s/reboot" % hostname)
- body = json.loads(body)
- self.validate_response(schema.reboot_host, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/hypervisor_client.py b/tempest/services/compute/json/hypervisor_client.py
deleted file mode 100644
index ba06f23..0000000
--- a/tempest/services/compute/json/hypervisor_client.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright 2013 IBM 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 oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import hypervisors as schema
-from tempest.common import service_client
-
-
-class HypervisorClient(service_client.ServiceClient):
-
- def list_hypervisors(self, detail=False):
- """List hypervisors information."""
- url = 'os-hypervisors'
- _schema = schema.list_search_hypervisors
- if detail:
- url += '/detail'
- _schema = schema.list_hypervisors_detail
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(_schema, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_hypervisor(self, hypervisor_id):
- """Display the details of the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s' % hypervisor_id)
- body = json.loads(body)
- self.validate_response(schema.get_hypervisor, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_servers_on_hypervisor(self, hypervisor_name):
- """List instances belonging to the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/servers' % hypervisor_name)
- body = json.loads(body)
- self.validate_response(schema.get_hypervisors_servers, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_hypervisor_statistics(self):
- """Get hypervisor statistics over all compute nodes."""
- resp, body = self.get('os-hypervisors/statistics')
- body = json.loads(body)
- self.validate_response(schema.get_hypervisor_statistics, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_hypervisor_uptime(self, hypervisor_id):
- """Display the uptime of the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/uptime' % hypervisor_id)
- body = json.loads(body)
- self.validate_response(schema.get_hypervisor_uptime, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def search_hypervisor(self, hypervisor_name):
- """Search specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/search' % hypervisor_name)
- body = json.loads(body)
- self.validate_response(schema.list_search_hypervisors, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 2e66082..fe076d8 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -16,7 +16,6 @@
from oslo_serialization import jsonutils as json
from tempest.api_schema.response.compute.v2_1 import interfaces as schema
-from tempest.api_schema.response.compute.v2_1 import servers as servers_schema
from tempest.common import service_client
@@ -49,21 +48,3 @@
port_id))
self.validate_response(schema.delete_interface, resp, body)
return service_client.ResponseBody(resp, body)
-
- def add_fixed_ip(self, server_id, **kwargs):
- """Add a fixed IP to input server instance."""
- post_body = json.dumps({'addFixedIp': kwargs})
- resp, body = self.post('servers/%s/action' % server_id,
- post_body)
- self.validate_response(servers_schema.server_actions_common_schema,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def remove_fixed_ip(self, server_id, **kwargs):
- """Remove input fixed IP from input server instance."""
- post_body = json.dumps({'removeFixedIp': kwargs})
- resp, body = self.post('servers/%s/action' % server_id,
- post_body)
- self.validate_response(servers_schema.server_actions_common_schema,
- resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/server_groups_client.py b/tempest/services/compute/json/server_groups_client.py
index 33501fb..62258d3 100644
--- a/tempest/services/compute/json/server_groups_client.py
+++ b/tempest/services/compute/json/server_groups_client.py
@@ -22,18 +22,13 @@
class ServerGroupsClient(service_client.ServiceClient):
- def create_server_group(self, name, policies):
+ def create_server_group(self, **kwargs):
"""
Create the server group
name : Name of the server-group
policies : List of the policies - affinity/anti-affinity)
"""
- post_body = {
- 'name': name,
- 'policies': policies,
- }
-
- post_body = json.dumps({'server_group': post_body})
+ post_body = json.dumps({'server_group': kwargs})
resp, body = self.post('os-server-groups', post_body)
body = json.loads(body)
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index a36603f..e54cfe4 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
@@ -29,59 +31,28 @@
auth_provider, service, region, **kwargs)
self.enable_instance_password = enable_instance_password
- def create_server(self, name, image_ref, flavor_ref, **kwargs):
+ def create_server(self, **kwargs):
+ """Create server
+
+ Most parameters except the following are passed to the API without
+ any changes.
+ :param disk_config: The name is changed to OS-DCF:diskConfig
+ :param scheduler_hints: The name is changed to os:scheduler_hints and
+ the parameter is set in the same level as the parameter 'server'.
"""
- Creates an instance of a server.
- name (Required): The name of the server.
- image_ref (Required): Reference to the image used to build the server.
- flavor_ref (Required): The flavor used to build the server.
- Following optional keyword arguments are accepted:
- adminPass: Sets the initial root password.
- key_name: Key name of keypair that was created earlier.
- meta: A dictionary of values to be used as metadata.
- personality: A list of dictionaries for files to be injected into
- the server.
- security_groups: A list of security group dicts.
- networks: A list of network dicts with UUID and fixed_ip.
- user_data: User data for instance.
- availability_zone: Availability zone in which to launch instance.
- accessIPv4: The IPv4 access address for the server.
- accessIPv6: The IPv6 access address for the server.
- min_count: Count of minimum number of instances to launch.
- max_count: Count of maximum number of instances to launch.
- disk_config: Determines if user or admin controls disk configuration.
- return_reservation_id: Enable/Disable the return of reservation id
- block_device_mapping: Block device mapping for the server.
- block_device_mapping_v2: Block device mapping V2 for the server.
- """
- post_body = {
- 'name': name,
- 'imageRef': image_ref,
- 'flavorRef': flavor_ref
- }
+ body = copy.deepcopy(kwargs)
+ if body.get('disk_config'):
+ body['OS-DCF:diskConfig'] = body.pop('disk_config')
- for option in ['personality', 'adminPass', 'key_name',
- 'security_groups', 'networks', 'user_data',
- 'availability_zone', 'accessIPv4', 'accessIPv6',
- 'min_count', 'max_count', ('metadata', 'meta'),
- ('OS-DCF:diskConfig', 'disk_config'),
- 'return_reservation_id', 'block_device_mapping',
- 'block_device_mapping_v2']:
- if isinstance(option, tuple):
- post_param = option[0]
- key = option[1]
- else:
- post_param = option
- key = option
- value = kwargs.get(key)
- if value is not None:
- post_body[post_param] = value
+ hints = None
+ if body.get('scheduler_hints'):
+ hints = {'os:scheduler_hints': body.pop('scheduler_hints')}
- post_body = {'server': post_body}
+ post_body = {'server': body}
- if 'sched_hints' in kwargs:
- hints = {'os:scheduler_hints': kwargs.get('sched_hints')}
+ if hints:
post_body = dict(post_body.items() + hints.items())
+
post_body = json.dumps(post_body)
resp, body = self.post('servers', post_body)
@@ -98,7 +69,8 @@
return service_client.ResponseBody(resp, body)
def update_server(self, server_id, **kwargs):
- """Updates the properties of an existing server.
+ """Update server
+
Most parameters except the following are passed to the API without
any changes.
:param disk_config: The name is changed to OS-DCF:diskConfig
@@ -113,20 +85,20 @@
return service_client.ResponseBody(resp, body)
def show_server(self, server_id):
- """Returns the details of an existing server."""
+ """Get server details"""
resp, body = self.get("servers/%s" % server_id)
body = json.loads(body)
self.validate_response(schema.get_server, resp, body)
return service_client.ResponseBody(resp, body)
def delete_server(self, server_id):
- """Deletes the given server."""
+ """Delete server"""
resp, body = self.delete("servers/%s" % server_id)
self.validate_response(schema.delete_server, resp, body)
return service_client.ResponseBody(resp, body)
def list_servers(self, detail=False, **params):
- """Lists all servers for a user."""
+ """List servers"""
url = 'servers'
_schema = schema.list_servers
@@ -457,3 +429,11 @@
return self.action(server_id, "os-getVNCConsole",
schema.get_vnc_console,
type=console_type)
+
+ def add_fixed_ip(self, server_id, **kwargs):
+ """Add a fixed IP to input server instance."""
+ return self.action(server_id, 'addFixedIp', **kwargs)
+
+ def remove_fixed_ip(self, server_id, **kwargs):
+ """Remove input fixed IP from input server instance."""
+ return self.action(server_id, 'removeFixedIp', **kwargs)
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
index 232b301..6e2f320 100644
--- a/tempest/services/compute/json/services_client.py
+++ b/tempest/services/compute/json/services_client.py
@@ -33,25 +33,26 @@
self.validate_response(schema.list_services, resp, body)
return service_client.ResponseBody(resp, body)
- def enable_service(self, host_name, binary):
+ def enable_service(self, **kwargs):
"""
Enable service on a host
host_name: Name of host
binary: Service binary
"""
- post_body = json.dumps({'binary': binary, 'host': host_name})
+ post_body = json.dumps(kwargs)
resp, body = self.put('os-services/enable', post_body)
body = json.loads(body)
- self.validate_response(schema.enable_service, resp, body)
+ self.validate_response(schema.enable_disable_service, resp, body)
return service_client.ResponseBody(resp, body)
- def disable_service(self, host_name, binary):
+ def disable_service(self, **kwargs):
"""
Disable service on a host
host_name: Name of host
binary: Service binary
"""
- post_body = json.dumps({'binary': binary, 'host': host_name})
+ post_body = json.dumps(kwargs)
resp, body = self.put('os-services/disable', post_body)
body = json.loads(body)
+ self.validate_response(schema.enable_disable_service, resp, body)
return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/snapshots_extensions_client.py b/tempest/services/compute/json/snapshots_client.py
similarity index 97%
rename from tempest/services/compute/json/snapshots_extensions_client.py
rename to tempest/services/compute/json/snapshots_client.py
index 6902a39..e3f92db 100644
--- a/tempest/services/compute/json/snapshots_extensions_client.py
+++ b/tempest/services/compute/json/snapshots_client.py
@@ -21,7 +21,7 @@
from tempest.common import service_client
-class SnapshotsExtensionsClient(service_client.ServiceClient):
+class SnapshotsClient(service_client.ServiceClient):
def create_snapshot(self, volume_id, **kwargs):
post_body = {
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_client.py
similarity index 97%
rename from tempest/services/compute/json/volumes_extensions_client.py
rename to tempest/services/compute/json/volumes_client.py
index db92351..e799c29 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_client.py
@@ -21,7 +21,7 @@
from tempest.common import service_client
-class VolumesExtensionsClient(service_client.ServiceClient):
+class VolumesClient(service_client.ServiceClient):
def list_volumes(self, detail=False, **params):
"""List all the volumes created."""
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index 81e967d..f37bc08 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -24,7 +24,8 @@
url = ''
resp, body = self.get(url)
self.expected_success([200, 203], resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def has_admin_extensions(self):
"""
@@ -49,7 +50,8 @@
post_body = json.dumps({'role': post_body})
resp, body = self.post('OS-KSADM/roles', post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def get_role(self, role_id):
"""Get a role by its id."""
@@ -73,7 +75,8 @@
post_body = json.dumps({'tenant': post_body})
resp, body = self.post('tenants', post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def delete_role(self, role_id):
"""Delete a role."""
@@ -86,14 +89,16 @@
url = '/tenants/%s/users/%s/roles' % (tenant_id, user_id)
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def assign_user_role(self, tenant_id, user_id, role_id):
"""Add roles to a user on a tenant."""
resp, body = self.put('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
(tenant_id, user_id, role_id), "")
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def remove_user_role(self, tenant_id, user_id, role_id):
"""Removes a role assignment for a user on a tenant."""
@@ -112,13 +117,15 @@
"""Get tenant details."""
resp, body = self.get('tenants/%s' % str(tenant_id))
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def list_roles(self):
"""Returns roles."""
resp, body = self.get('OS-KSADM/roles')
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def list_tenants(self):
"""Returns tenants."""
@@ -136,7 +143,7 @@
def update_tenant(self, tenant_id, **kwargs):
"""Updates a tenant."""
- body = self.get_tenant(tenant_id)
+ body = self.get_tenant(tenant_id)['tenant']
name = kwargs.get('name', body['name'])
desc = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
@@ -149,7 +156,8 @@
post_body = json.dumps({'tenant': post_body})
resp, body = self.post('tenants/%s' % tenant_id, post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def create_user(self, name, password, tenant_id, email, **kwargs):
"""Create a user."""
@@ -165,20 +173,23 @@
post_body = json.dumps({'user': post_body})
resp, body = self.post('users', post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def update_user(self, user_id, **kwargs):
"""Updates a user."""
put_body = json.dumps({'user': kwargs})
resp, body = self.put('users/%s' % user_id, put_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def get_user(self, user_id):
"""GET a user."""
resp, body = self.get("users/%s" % user_id)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def delete_user(self, user_id):
"""Delete a user."""
@@ -190,7 +201,8 @@
"""Get the list of users."""
resp, body = self.get("users")
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def enable_disable_user(self, user_id, enabled):
"""Enables or disables a user."""
@@ -200,13 +212,15 @@
put_body = json.dumps({'user': put_body})
resp, body = self.put('users/%s/enabled' % user_id, put_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def get_token(self, token_id):
"""Get token details."""
resp, body = self.get("tokens/%s" % token_id)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def delete_token(self, token_id):
"""Delete a token."""
@@ -218,10 +232,11 @@
"""List users for a Tenant."""
resp, body = self.get('/tenants/%s/users' % tenant_id)
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def get_user_by_username(self, tenant_id, username):
- users = self.list_users_for_tenant(tenant_id)
+ users = self.list_users_for_tenant(tenant_id)['users']
for user in users:
if user['name'] == username:
return user
@@ -237,20 +252,23 @@
post_body = json.dumps({'OS-KSADM:service': post_body})
resp, body = self.post('/OS-KSADM/services', post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def get_service(self, service_id):
"""Get Service."""
url = '/OS-KSADM/services/%s' % service_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def list_services(self):
"""List Service - Returns Services."""
resp, body = self.get('/OS-KSADM/services')
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def delete_service(self, service_id):
"""Delete Service."""
@@ -271,13 +289,15 @@
post_body = json.dumps({'endpoint': post_body})
resp, body = self.post('/endpoints', post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def list_endpoints(self):
"""List Endpoints - Returns Endpoints."""
resp, body = self.get('/endpoints')
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def delete_endpoint(self, endpoint_id):
"""Delete an endpoint."""
@@ -295,7 +315,8 @@
put_body = json.dumps({'user': put_body})
resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def update_user_own_password(self, user_id, new_pass, old_pass):
"""User updates own password"""
@@ -306,22 +327,23 @@
patch_body = json.dumps({'user': patch_body})
resp, body = self.patch('OS-KSCRUD/users/%s' % user_id, patch_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def list_extensions(self):
"""List all the extensions."""
resp, body = self.get('/extensions')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBodyList(resp,
- body['extensions']['values'])
+ return service_client.ResponseBody(resp, body)
def create_user_ec2_credentials(self, user_id, tenant_id):
post_body = json.dumps({'tenant_id': tenant_id})
resp, body = self.post('/users/%s/credentials/OS-EC2' % user_id,
post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def delete_user_ec2_credentials(self, user_id, access):
resp, body = self.delete('/users/%s/credentials/OS-EC2/%s' %
@@ -332,10 +354,12 @@
def list_user_ec2_credentials(self, user_id):
resp, body = self.get('/users/%s/credentials/OS-EC2' % user_id)
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def show_user_ec2_credentials(self, user_id, access):
resp, body = self.get('/users/%s/credentials/OS-EC2/%s' %
(user_id, access))
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 6cad746..eea179d 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -212,3 +212,63 @@
self.expected_success(200, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
+
+ def list_resource_types(self):
+ url = '/v2/metadefs/resource_types'
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def create_namespaces(self, namespace, **kwargs):
+ params = {
+ "namespace": namespace,
+ }
+
+ for option in kwargs:
+ value = kwargs.get(option)
+ if isinstance(value, dict) or isinstance(value, tuple):
+ params.update(value)
+ else:
+ params[option] = value
+
+ data = json.dumps(params)
+ self._validate_schema(data)
+
+ resp, body = self.post('/v2/metadefs/namespaces', data)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def show_namespaces(self, namespace):
+ url = '/v2/metadefs/namespaces/%s' % namespace
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def update_namespaces(self, namespace, visibility, **kwargs):
+ params = {
+ "namespace": namespace,
+ "visibility": visibility
+ }
+ for option in kwargs:
+ value = kwargs.get(option)
+ if isinstance(value, dict) or isinstance(value, tuple):
+ params.update(value)
+ else:
+ params[option] = value
+
+ data = json.dumps(params)
+ self._validate_schema(data)
+ url = '/v2/metadefs/namespaces/%s' % namespace
+ resp, body = self.put(url, body=data)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_namespaces(self, namespace):
+ url = '/v2/metadefs/namespaces/%s' % namespace
+ resp, _ = self.delete(url)
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index a345d56..7821f37 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -34,50 +34,6 @@
quotas
"""
- def create_network(self, **kwargs):
- uri = '/networks'
- post_data = {'network': kwargs}
- return self.create_resource(uri, post_data)
-
- def update_network(self, network_id, **kwargs):
- uri = '/networks/%s' % network_id
- post_data = {'network': kwargs}
- return self.update_resource(uri, post_data)
-
- def show_network(self, network_id, **fields):
- uri = '/networks/%s' % network_id
- return self.show_resource(uri, **fields)
-
- def delete_network(self, network_id):
- uri = '/networks/%s' % network_id
- return self.delete_resource(uri)
-
- def list_networks(self, **filters):
- uri = '/networks'
- return self.list_resources(uri, **filters)
-
- def create_subnet(self, **kwargs):
- uri = '/subnets'
- post_data = {'subnet': kwargs}
- return self.create_resource(uri, post_data)
-
- def update_subnet(self, subnet_id, **kwargs):
- uri = '/subnets/%s' % subnet_id
- post_data = {'subnet': kwargs}
- return self.update_resource(uri, post_data)
-
- def show_subnet(self, subnet_id, **fields):
- uri = '/subnets/%s' % subnet_id
- return self.show_resource(uri, **fields)
-
- def delete_subnet(self, subnet_id):
- uri = '/subnets/%s' % subnet_id
- return self.delete_resource(uri)
-
- def list_subnets(self, **filters):
- uri = '/subnets'
- return self.list_resources(uri, **filters)
-
def create_port(self, **kwargs):
uri = '/ports'
post_data = {'port': kwargs}
@@ -445,3 +401,25 @@
post_body = {'network_id': network_id}
uri = '/agents/%s/dhcp-networks' % agent_id
return self.create_resource(uri, post_body)
+
+ 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/networks_client.py b/tempest/services/network/json/networks_client.py
new file mode 100644
index 0000000..2907d44
--- /dev/null
+++ b/tempest/services/network/json/networks_client.py
@@ -0,0 +1,38 @@
+# 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 NetworksClient(base.BaseNetworkClient):
+
+ def create_network(self, **kwargs):
+ uri = '/networks'
+ post_data = {'network': kwargs}
+ return self.create_resource(uri, post_data)
+
+ def update_network(self, network_id, **kwargs):
+ uri = '/networks/%s' % network_id
+ post_data = {'network': kwargs}
+ return self.update_resource(uri, post_data)
+
+ def show_network(self, network_id, **fields):
+ uri = '/networks/%s' % network_id
+ return self.show_resource(uri, **fields)
+
+ def delete_network(self, network_id):
+ uri = '/networks/%s' % network_id
+ return self.delete_resource(uri)
+
+ def list_networks(self, **filters):
+ uri = '/networks'
+ return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/subnets_client.py b/tempest/services/network/json/subnets_client.py
new file mode 100644
index 0000000..957b606
--- /dev/null
+++ b/tempest/services/network/json/subnets_client.py
@@ -0,0 +1,38 @@
+# 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 SubnetsClient(base.BaseNetworkClient):
+
+ def create_subnet(self, **kwargs):
+ uri = '/subnets'
+ post_data = {'subnet': kwargs}
+ return self.create_resource(uri, post_data)
+
+ def update_subnet(self, subnet_id, **kwargs):
+ uri = '/subnets/%s' % subnet_id
+ post_data = {'subnet': kwargs}
+ return self.update_resource(uri, post_data)
+
+ def show_subnet(self, subnet_id, **fields):
+ uri = '/subnets/%s' % subnet_id
+ return self.show_resource(uri, **fields)
+
+ def delete_subnet(self, subnet_id):
+ uri = '/subnets/%s' % subnet_id
+ return self.delete_resource(uri)
+
+ def list_subnets(self, **filters):
+ uri = '/subnets'
+ return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/resources.py b/tempest/services/network/resources.py
index 4d45515..16d9823 100644
--- a/tempest/services/network/resources.py
+++ b/tempest/services/network/resources.py
@@ -41,6 +41,9 @@
def __init__(self, *args, **kwargs):
self.client = kwargs.pop('client', None)
+ self.network_client = kwargs.pop('network_client', None)
+ self.networks_client = kwargs.pop('networks_client', None)
+ self.subnets_client = kwargs.pop('subnets_client', None)
super(DeletableResource, self).__init__(*args, **kwargs)
def __str__(self):
@@ -72,7 +75,7 @@
class DeletableNetwork(DeletableResource):
def delete(self):
- self.client.delete_network(self.id)
+ self.networks_client.delete_network(self.id)
class DeletableSubnet(DeletableResource):
@@ -82,23 +85,23 @@
self._router_ids = set()
def update(self, *args, **kwargs):
- result = self.client.update_subnet(self.id,
- *args,
- **kwargs)
+ result = self.subnets_client.update_subnet(self.id,
+ *args,
+ **kwargs)
return super(DeletableSubnet, self).update(**result['subnet'])
def add_to_router(self, router_id):
self._router_ids.add(router_id)
- self.client.add_router_interface_with_subnet_id(router_id,
- subnet_id=self.id)
+ self.network_client.add_router_interface_with_subnet_id(
+ router_id, subnet_id=self.id)
def delete(self):
for router_id in self._router_ids.copy():
- self.client.remove_router_interface_with_subnet_id(
+ self.network_client.remove_router_interface_with_subnet_id(
router_id,
subnet_id=self.id)
self._router_ids.remove(router_id)
- self.client.delete_subnet(self.id)
+ self.subnets_client.delete_subnet(self.id)
class DeletableRouter(DeletableResource):
diff --git a/tempest/stress/actions/server_create_destroy.py b/tempest/stress/actions/server_create_destroy.py
index 37664de..44b6f62 100644
--- a/tempest/stress/actions/server_create_destroy.py
+++ b/tempest/stress/actions/server_create_destroy.py
@@ -30,7 +30,7 @@
name = data_utils.rand_name("instance")
self.logger.info("creating %s" % name)
server = self.manager.servers_client.create_server(
- name, self.image, self.flavor)['server']
+ name=name, imageRef=self.image, flavorRef=self.flavor)['server']
server_id = server['id']
waiters.wait_for_server_status(self.manager.servers_client, server_id,
'ACTIVE')
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 81bb071..d912b25 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -75,8 +75,8 @@
self.logger.info("creating %s" % name)
vm_args = self.vm_extra_args.copy()
vm_args['security_groups'] = [self.sec_grp]
- server = servers_client.create_server(name, self.image,
- self.flavor,
+ server = servers_client.create_server(name=name, imageRef=self.image,
+ flavorRef=self.flavor,
**vm_args)['server']
self.server_id = server['id']
if self.wait_after_vm_create:
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index b3753a5..847f342 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -39,7 +39,7 @@
vm_name = data_utils.rand_name("instance")
self.logger.info("creating vm: %s" % vm_name)
server = self.manager.servers_client.create_server(
- vm_name, self.image, self.flavor)['server']
+ name=vm_name, imageRef=self.image, flavorRef=self.flavor)['server']
server_id = server['id']
waiters.wait_for_server_status(self.manager.servers_client, server_id,
'ACTIVE')
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index 8105626..95841a9 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -39,8 +39,8 @@
vm_args = self.vm_extra_args.copy()
vm_args['security_groups'] = [self.sec_grp]
vm_args['key_name'] = self.key['name']
- server = servers_client.create_server(name, self.image,
- self.flavor,
+ server = servers_client.create_server(name=name, imageRef=self.image,
+ flavorRef=self.flavor,
**vm_args)['server']
self.server_id = server['id']
waiters.wait_for_server_status(self.manager.servers_client,
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index 9456590..1350d95 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -68,7 +68,7 @@
except Exception:
pass
- users = admin_manager.identity_client.get_users()
+ users = admin_manager.identity_client.get_users()['users']
LOG.info("Cleanup::remove %s users" % len(users))
for user in users:
if user['name'].startswith("stress_user"):
diff --git a/tempest/test.py b/tempest/test.py
index 142488c..b8ba5f4 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -224,7 +224,7 @@
Tear-down is also split in a series of steps (teardown stages), which are
stacked for execution only if the corresponding setup stage had been
reached during the setup phase. Tear-down stages are:
- - clear_isolated_creds (defined in the base test class)
+ - clear_credentials (defined in the base test class)
- resource_cleanup
"""
@@ -258,7 +258,7 @@
cls.skip_checks()
try:
# Allocation of all required credentials and client managers
- cls.teardowns.append(('credentials', cls.clear_isolated_creds))
+ cls.teardowns.append(('credentials', cls.clear_credentials))
cls.setup_credentials()
# Shortcuts to clients
cls.setup_clients()
@@ -323,10 +323,13 @@
If one is really needed it may be implemented either in the
resource_setup or at test level.
"""
- if 'admin' in cls.credentials and not credentials.is_admin_available():
+ identity_version = cls.get_identity_version()
+ if 'admin' in cls.credentials and not credentials.is_admin_available(
+ identity_version=identity_version):
msg = "Missing Identity Admin API credentials in configuration."
raise cls.skipException(msg)
- if 'alt' in cls.credentials and not credentials.is_alt_available():
+ if 'alt' in cls.credentials and not credentials.is_alt_available(
+ identity_version=identity_version):
msg = "Missing a 2nd set of API credentials in configuration."
raise cls.skipException(msg)
if hasattr(cls, 'identity_version'):
@@ -454,6 +457,12 @@
return cred_client.get_creds_client(client, domain)
@classmethod
+ def get_identity_version(cls):
+ """Returns the identity version used by the test class"""
+ identity_version = getattr(cls, 'identity_version', None)
+ return identity_version or CONF.identity.auth_version
+
+ @classmethod
def _get_credentials_provider(cls):
"""Returns a credentials provider
@@ -464,13 +473,11 @@
not cls._creds_provider.name == cls.__name__):
force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
False)
- identity_version = getattr(cls, 'identity_version', None)
- identity_version = identity_version or CONF.identity.auth_version
- cls._creds_provider = credentials.get_isolated_credentials(
+ cls._creds_provider = credentials.get_credentials_provider(
name=cls.__name__, network_resources=cls.network_resources,
force_tenant_isolation=force_tenant_isolation,
- identity_version=identity_version)
+ identity_version=cls.get_identity_version())
return cls._creds_provider
@classmethod
@@ -515,12 +522,12 @@
return clients.Manager(credentials=creds, service=cls._service)
@classmethod
- def clear_isolated_creds(cls):
+ def clear_credentials(cls):
"""
- Clears isolated creds if set
+ Clears creds if set
"""
if hasattr(cls, '_creds_provider'):
- cls._creds_provider.clear_isolated_creds()
+ cls._creds_provider.clear_creds()
@classmethod
def set_validation_resources(cls, keypair=None, floating_ip=None,
@@ -589,7 +596,7 @@
:return: network dict including 'id' and 'name'
"""
- # Make sure isolated_creds exists and get a network client
+ # Make sure cred_provider exists and get a network client
networks_client = cls.get_client_manager().compute_networks_client
cred_provider = cls._get_credentials_provider()
# In case of nova network, isolated tenants are not able to list the
@@ -597,7 +604,8 @@
# for their servers, so using an admin network client to validate
# the network name
if (not CONF.service_available.neutron and
- credentials.is_admin_available()):
+ credentials.is_admin_available(
+ identity_version=cls.get_identity_version())):
admin_creds = cred_provider.get_admin_creds()
admin_manager = clients.Manager(admin_creds)
networks_client = admin_manager.compute_networks_client
@@ -747,7 +755,8 @@
"mechanism")
if "admin_client" in description and description["admin_client"]:
- if not credentials.is_admin_available():
+ if not credentials.is_admin_available(
+ identity_version=self.get_identity_version()):
msg = ("Missing Identity Admin API credentials in"
"configuration.")
raise self.skipException(msg)
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index 640b004..58a9905 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -88,7 +88,11 @@
def register_plugin_opts(self, conf):
for plug in self.ext_plugins:
- plug.obj.register_opts(conf)
+ try:
+ plug.obj.register_opts(conf)
+ except Exception:
+ LOG.exception('Plugin %s raised an exception trying to run '
+ 'register_opts' % plug.name)
def get_plugin_options_list(self):
plugin_options = []
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index 4a8f729..fc3d984 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -380,7 +380,7 @@
javelin.destroy_subnets([self.fake_object])
- mocked_function = self.fake_client.networks.delete_subnet
+ mocked_function = self.fake_client.subnets.delete_subnet
mocked_function.assert_called_once_with(fake_subnet_id)
def test_destroy_routers(self):
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
index 6b5af7e..1d60c67 100644
--- a/tempest/tests/cmd/test_tempest_init.py
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -13,6 +13,7 @@
# under the License.
import os
+import shutil
import fixtures
@@ -39,9 +40,37 @@
self.addCleanup(conf_file.close)
self.assertEqual(conf_file.read(), testr_conf_file)
+ def test_generate_sample_config(self):
+ local_dir = self.useFixture(fixtures.TempDir())
+ etc_dir_path = os.path.join(local_dir.path, 'etc/')
+ os.mkdir(etc_dir_path)
+ tmp_dir = self.useFixture(fixtures.TempDir())
+ config_dir = os.path.join(tmp_dir.path, 'config/')
+ shutil.copytree('etc/', config_dir)
+ init_cmd = init.TempestInit(None, None)
+ local_sample_conf_file = os.path.join(etc_dir_path,
+ 'tempest.conf.sample')
+ # Verify no sample config file exist
+ self.assertFalse(os.path.isfile(local_sample_conf_file))
+ init_cmd.generate_sample_config(local_dir.path, config_dir)
+
+ # Verify sample config file exist with some content
+ self.assertTrue(os.path.isfile(local_sample_conf_file))
+ self.assertGreater(os.path.getsize(local_sample_conf_file), 0)
+
+ def test_create_working_dir_with_existing_local_dir(self):
+ fake_local_dir = self.useFixture(fixtures.TempDir())
+ fake_local_conf_dir = self.useFixture(fixtures.TempDir())
+ _init = init.TempestInit(None, None)
+ self.assertRaises(OSError,
+ _init.create_working_dir,
+ fake_local_dir.path,
+ fake_local_conf_dir.path)
+
def test_create_working_dir(self):
fake_local_dir = self.useFixture(fixtures.TempDir())
fake_local_conf_dir = self.useFixture(fixtures.TempDir())
+ os.rmdir(fake_local_dir.path)
# Create a fake conf file
fake_file = fake_local_conf_dir.join('conf_file.conf')
open(fake_file, 'w').close()
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 2de5802..a5dea54 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -113,7 +113,7 @@
'print_and_or_update') as print_mock:
verify_tempest_config.verify_keystone_api_versions(fake_os, True)
print_mock.assert_called_once_with('api_v3',
- 'identity_feature_enabled',
+ 'identity-feature-enabled',
False, True)
def test_verify_keystone_api_versions_no_v2(self):
@@ -129,7 +129,7 @@
'print_and_or_update') as print_mock:
verify_tempest_config.verify_keystone_api_versions(fake_os, True)
print_mock.assert_called_once_with('api_v2',
- 'identity_feature_enabled',
+ 'identity-feature-enabled',
False, True)
def test_verify_cinder_api_versions_no_v2(self):
@@ -144,7 +144,7 @@
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
verify_tempest_config.verify_cinder_api_versions(fake_os, True)
- print_mock.assert_called_once_with('api_v2', 'volume_feature_enabled',
+ print_mock.assert_called_once_with('api_v2', 'volume-feature-enabled',
False, True)
def test_verify_cinder_api_versions_no_v1(self):
@@ -159,7 +159,7 @@
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
verify_tempest_config.verify_cinder_api_versions(fake_os, True)
- print_mock.assert_called_once_with('api_v1', 'volume_feature_enabled',
+ print_mock.assert_called_once_with('api_v1', 'volume-feature-enabled',
False, True)
def test_verify_glance_version_no_v2_with_v1_1(self):
@@ -170,7 +170,7 @@
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
verify_tempest_config.verify_glance_api_versions(fake_os, True)
- print_mock.assert_called_once_with('api_v2', 'image_feature_enabled',
+ print_mock.assert_called_once_with('api_v2', 'image-feature-enabled',
False, True)
def test_verify_glance_version_no_v2_with_v1_0(self):
@@ -181,7 +181,7 @@
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
verify_tempest_config.verify_glance_api_versions(fake_os, True)
- print_mock.assert_called_once_with('api_v2', 'image_feature_enabled',
+ print_mock.assert_called_once_with('api_v2', 'image-feature-enabled',
False, True)
def test_verify_glance_version_no_v1(self):
@@ -192,7 +192,7 @@
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
verify_tempest_config.verify_glance_api_versions(fake_os, True)
- print_mock.assert_called_once_with('api_v1', 'image_feature_enabled',
+ print_mock.assert_called_once_with('api_v1', 'image-feature-enabled',
False, True)
def test_verify_extensions_neutron(self):
diff --git a/tempest/tests/common/test_admin_available.py b/tempest/tests/common/test_admin_available.py
index 5c69c5e..a53ed5f 100644
--- a/tempest/tests/common/test_admin_available.py
+++ b/tempest/tests/common/test_admin_available.py
@@ -23,15 +23,17 @@
class TestAdminAvailable(base.TestCase):
+ identity_version = 'v2'
+
def setUp(self):
super(TestAdminAvailable, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
- def run_test(self, tenant_isolation, use_accounts_file, admin_creds):
+ def run_test(self, dynamic_creds, use_accounts_file, admin_creds):
- cfg.CONF.set_default('allow_tenant_isolation',
- tenant_isolation, group='auth')
+ cfg.CONF.set_default('use_dynamic_credentials',
+ dynamic_creds, group='auth')
if use_accounts_file:
accounts = [{'username': 'u1',
'tenant_name': 't1',
@@ -50,7 +52,7 @@
'password': 'p',
'types': ['admin']})
self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=accounts))
cfg.CONF.set_default('test_accounts_file',
use_accounts_file, group='auth')
@@ -60,45 +62,58 @@
self.useFixture(mockpatch.Patch('os.path.isfile',
return_value=False))
if admin_creds:
- (u, t, p) = ('u', 't', 'p')
+ username = 'u'
+ tenant = 't'
+ password = 'p'
+ domain = 'd'
else:
- (u, t, p) = (None, None, None)
+ username = None
+ tenant = None
+ password = None
+ domain = None
- cfg.CONF.set_default('admin_username', u, group='identity')
- cfg.CONF.set_default('admin_tenant_name', t, group='identity')
- cfg.CONF.set_default('admin_password', p, group='identity')
+ cfg.CONF.set_default('admin_username', username, group='auth')
+ cfg.CONF.set_default('admin_tenant_name', tenant, group='auth')
+ cfg.CONF.set_default('admin_password', password, group='auth')
+ cfg.CONF.set_default('admin_domain_name', domain, group='auth')
- expected = admin_creds is not None or tenant_isolation
- observed = credentials.is_admin_available()
+ expected = admin_creds is not None or dynamic_creds
+ observed = credentials.is_admin_available(
+ identity_version=self.identity_version)
self.assertEqual(expected, observed)
- # Tenant isolation implies admin so only one test case for True
- def test__tenant_isolation__accounts_file__no_admin(self):
- self.run_test(tenant_isolation=True,
+ # Dynamic credentials implies admin so only one test case for True
+ def test__dynamic_creds__accounts_file__no_admin(self):
+ self.run_test(dynamic_creds=True,
use_accounts_file=True,
admin_creds=None)
- def test__no_tenant_isolation__accounts_file__no_admin(self):
- self.run_test(tenant_isolation=False,
+ def test__no_dynamic_creds__accounts_file__no_admin(self):
+ self.run_test(dynamic_creds=False,
use_accounts_file=True,
admin_creds=None)
- def test__no_tenant_isolation__accounts_file__admin_role(self):
- self.run_test(tenant_isolation=False,
+ def test__no_dynamic_creds__accounts_file__admin_role(self):
+ self.run_test(dynamic_creds=False,
use_accounts_file=True,
admin_creds='role')
- def test__no_tenant_isolation__accounts_file__admin_type(self):
- self.run_test(tenant_isolation=False,
+ def test__no_dynamic_creds__accounts_file__admin_type(self):
+ self.run_test(dynamic_creds=False,
use_accounts_file=True,
admin_creds='type')
- def test__no_tenant_isolation__no_accounts_file__no_admin(self):
- self.run_test(tenant_isolation=False,
+ def test__no_dynamic_creds__no_accounts_file__no_admin(self):
+ self.run_test(dynamic_creds=False,
use_accounts_file=False,
admin_creds=None)
- def test__no_tenant_isolation__no_accounts_file__admin(self):
- self.run_test(tenant_isolation=False,
+ def test__no_dynamic_creds__no_accounts_file__admin(self):
+ self.run_test(dynamic_creds=False,
use_accounts_file=False,
admin_creds='role')
+
+
+class TestAdminAvailableV3(TestAdminAvailable):
+
+ identity_version = 'v3'
diff --git a/tempest/tests/common/test_alt_available.py b/tempest/tests/common/test_alt_available.py
new file mode 100644
index 0000000..6a86f73
--- /dev/null
+++ b/tempest/tests/common/test_alt_available.py
@@ -0,0 +1,117 @@
+# Copyright 2015 Red Hat, Inc.
+#
+# 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 oslo_config import cfg
+from oslotest import mockpatch
+
+from tempest.common import credentials
+from tempest import config
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class TestAltAvailable(base.TestCase):
+
+ identity_version = 'v2'
+
+ def setUp(self):
+ super(TestAltAvailable, self).setUp()
+ self.useFixture(fake_config.ConfigFixture())
+ self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+
+ def run_test(self, dynamic_creds, use_accounts_file, creds):
+
+ cfg.CONF.set_default('use_dynamic_credentials',
+ dynamic_creds, group='auth')
+ if use_accounts_file:
+ accounts = [dict(username="u%s" % ii,
+ tenant_name="t%s" % ii,
+ password="p") for ii in creds]
+ self.useFixture(mockpatch.Patch(
+ 'tempest.common.preprov_creds.read_accounts_yaml',
+ return_value=accounts))
+ cfg.CONF.set_default('test_accounts_file',
+ use_accounts_file, group='auth')
+ self.useFixture(mockpatch.Patch('os.path.isfile',
+ return_value=True))
+ else:
+ self.useFixture(mockpatch.Patch('os.path.isfile',
+ return_value=False))
+ cred_prefix = ['', 'alt_']
+ for ii in range(0, 2):
+ if len(creds) > ii:
+ username = 'u%s' % creds[ii]
+ tenant = 't%s' % creds[ii]
+ password = 'p'
+ domain = 'd'
+ else:
+ username = None
+ tenant = None
+ password = None
+ domain = None
+
+ cfg.CONF.set_default('%susername' % cred_prefix[ii], username,
+ group='identity')
+ cfg.CONF.set_default('%stenant_name' % cred_prefix[ii], tenant,
+ group='identity')
+ cfg.CONF.set_default('%spassword' % cred_prefix[ii], password,
+ group='identity')
+ cfg.CONF.set_default('%sdomain_name' % cred_prefix[ii], domain,
+ group='identity')
+
+ expected = len(set(creds)) > 1 or dynamic_creds
+ observed = credentials.is_alt_available(
+ identity_version=self.identity_version)
+ self.assertEqual(expected, observed)
+
+ # Dynamic credentials implies alt so only one test case for True
+ def test__dynamic_creds__accounts_file__one_user(self):
+ self.run_test(dynamic_creds=True,
+ use_accounts_file=False,
+ creds=['1', '2'])
+
+ def test__no_dynamic_creds__accounts_file__one_user(self):
+ self.run_test(dynamic_creds=False,
+ use_accounts_file=True,
+ creds=['1'])
+
+ def test__no_dynamic_creds__accounts_file__two_users(self):
+ self.run_test(dynamic_creds=False,
+ use_accounts_file=True,
+ creds=['1', '2'])
+
+ def test__no_dynamic_creds__accounts_file__two_users_identical(self):
+ self.run_test(dynamic_creds=False,
+ use_accounts_file=True,
+ creds=['1', '1'])
+
+ def test__no_dynamic_creds__no_accounts_file__one_user(self):
+ self.run_test(dynamic_creds=False,
+ use_accounts_file=False,
+ creds=['1'])
+
+ def test__no_dynamic_creds__no_accounts_file__two_users(self):
+ self.run_test(dynamic_creds=False,
+ use_accounts_file=False,
+ creds=['1', '2'])
+
+ def test__no_dynamic_creds__no_accounts_file__two_users_identical(self):
+ self.run_test(dynamic_creds=False,
+ use_accounts_file=False,
+ creds=['1', '1'])
+
+
+class TestAltAvailableV3(TestAltAvailable):
+
+ identity_version = 'v3'
diff --git a/tempest/tests/common/test_cred_provider.py b/tempest/tests/common/test_cred_provider.py
index 1bc7147..d404660 100644
--- a/tempest/tests/common/test_cred_provider.py
+++ b/tempest/tests/common/test_cred_provider.py
@@ -123,5 +123,9 @@
cfg.CONF.set_default('auth_version', 'v3', group='identity')
# Identity group items
for prefix in ['', 'alt_', 'admin_']:
+ if prefix == 'admin_':
+ group = 'auth'
+ else:
+ group = 'identity'
cfg.CONF.set_default(prefix + 'domain_name', 'fake_domain_name',
- group='identity')
+ group=group)
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/common/test_dynamic_creds.py
similarity index 78%
rename from tempest/tests/test_tenant_isolation.py
rename to tempest/tests/common/test_dynamic_creds.py
index 7bdc1d7..59a5523 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -17,7 +17,7 @@
from oslotest import mockpatch
from tempest_lib.services.identity.v2 import token_client as json_token_client
-from tempest.common import isolated_creds
+from tempest.common import dynamic_creds
from tempest.common import service_client
from tempest import config
from tempest import exceptions
@@ -30,10 +30,14 @@
from tempest.tests import fake_identity
-class TestTenantIsolation(base.TestCase):
+class TestDynamicCredentialProvider(base.TestCase):
+
+ fixed_params = {'name': 'test class',
+ 'identity_version': 'v2',
+ 'admin_role': 'admin'}
def setUp(self):
- super(TestTenantIsolation, self).setUp()
+ super(TestDynamicCredentialProvider, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.fake_http = fake_http.fake_httplib2(return_type=200)
@@ -44,10 +48,10 @@
self._mock_list_ec2_credentials('fake_user_id', 'fake_tenant_id')
def test_tempest_client(self):
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
- self.assertTrue(isinstance(iso_creds.identity_admin_client,
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
+ self.assertTrue(isinstance(creds.identity_admin_client,
json_iden_client.IdentityClient))
- self.assertTrue(isinstance(iso_creds.network_admin_client,
+ self.assertTrue(isinstance(creds.network_admin_client,
json_network_client.NetworkClient))
def _mock_user_create(self, id, name):
@@ -55,7 +59,7 @@
json_iden_client.IdentityClient,
'create_user',
return_value=(service_client.ResponseBody
- (200, {'id': id, 'name': name}))))
+ (200, {'user': {'id': id, 'name': name}}))))
return user_fix
def _mock_tenant_create(self, id, name):
@@ -63,28 +67,29 @@
json_iden_client.IdentityClient,
'create_tenant',
return_value=(service_client.ResponseBody
- (200, {'id': id, 'name': name}))))
+ (200, {'tenant': {'id': id, 'name': name}}))))
return tenant_fix
def _mock_list_roles(self, id, name):
roles_fix = self.useFixture(mockpatch.PatchObject(
json_iden_client.IdentityClient,
'list_roles',
- return_value=(service_client.ResponseBodyList
+ return_value=(service_client.ResponseBody
(200,
- [{'id': id, 'name': name},
- {'id': '1', 'name': 'FakeRole'}]))))
+ {'roles': [{'id': id, 'name': name},
+ {'id': '1', 'name': 'FakeRole'},
+ {'id': '2', 'name': 'Member'}]}))))
return roles_fix
def _mock_list_2_roles(self):
roles_fix = self.useFixture(mockpatch.PatchObject(
json_iden_client.IdentityClient,
'list_roles',
- return_value=(service_client.ResponseBodyList
+ return_value=(service_client.ResponseBody
(200,
- [{'id': '1234', 'name': 'role1'},
+ {'roles': [{'id': '1234', 'name': 'role1'},
{'id': '1', 'name': 'FakeRole'},
- {'id': '12345', 'name': 'role2'}]))))
+ {'id': '12345', 'name': 'role2'}]}))))
return roles_fix
def _mock_assign_user_role(self):
@@ -99,32 +104,34 @@
roles_fix = self.useFixture(mockpatch.PatchObject(
json_iden_client.IdentityClient,
'list_roles',
- return_value=(service_client.ResponseBodyList
- (200, [{'id': '1', 'name': 'FakeRole'}]))))
+ return_value=(service_client.ResponseBody
+ (200, {'roles': [{'id': '1',
+ 'name': 'FakeRole'}]}))))
return roles_fix
def _mock_list_ec2_credentials(self, user_id, tenant_id):
ec2_creds_fix = self.useFixture(mockpatch.PatchObject(
json_iden_client.IdentityClient,
'list_user_ec2_credentials',
- return_value=(service_client.ResponseBodyList
- (200, [{'access': 'fake_access',
- 'secret': 'fake_secret',
- 'tenant_id': tenant_id,
- 'user_id': user_id,
- 'trust_id': None}]))))
+ return_value=(service_client.ResponseBody
+ (200, {'credentials': [{
+ 'access': 'fake_access',
+ 'secret': 'fake_secret',
+ 'tenant_id': tenant_id,
+ 'user_id': user_id,
+ 'trust_id': None}]}))))
return ec2_creds_fix
def _mock_network_create(self, iso_creds, id, name):
net_fix = self.useFixture(mockpatch.PatchObject(
- iso_creds.network_admin_client,
+ iso_creds.networks_admin_client,
'create_network',
return_value={'network': {'id': id, 'name': name}}))
return net_fix
def _mock_subnet_create(self, iso_creds, id, name):
subnet_fix = self.useFixture(mockpatch.PatchObject(
- iso_creds.network_admin_client,
+ iso_creds.subnets_admin_client,
'create_subnet',
return_value={'subnet': {'id': id, 'name': name}}))
return subnet_fix
@@ -139,12 +146,12 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_primary_creds(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_tenant_create('1234', 'fake_prim_tenant')
self._mock_user_create('1234', 'fake_prim_user')
- primary_creds = iso_creds.get_primary_creds()
+ primary_creds = creds.get_primary_creds()
self.assertEqual(primary_creds.username, 'fake_prim_user')
self.assertEqual(primary_creds.tenant_name, 'fake_prim_tenant')
# Verify IDs
@@ -154,7 +161,7 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_admin_creds(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_list_roles('1234', 'admin')
self._mock_user_create('1234', 'fake_admin_user')
self._mock_tenant_create('1234', 'fake_admin_tenant')
@@ -165,7 +172,7 @@
self.addCleanup(user_mock.stop)
with mock.patch.object(json_iden_client.IdentityClient,
'assign_user_role') as user_mock:
- admin_creds = iso_creds.get_admin_creds()
+ admin_creds = creds.get_admin_creds()
user_mock.assert_has_calls([
mock.call('1234', '1234', '1234')])
self.assertEqual(admin_creds.username, 'fake_admin_user')
@@ -177,7 +184,7 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_role_creds(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
- iso_creds = isolated_creds.IsolatedCreds('v2', 'test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_list_2_roles()
self._mock_user_create('1234', 'fake_role_user')
self._mock_tenant_create('1234', 'fake_role_tenant')
@@ -188,7 +195,8 @@
self.addCleanup(user_mock.stop)
with mock.patch.object(json_iden_client.IdentityClient,
'assign_user_role') as user_mock:
- role_creds = iso_creds.get_creds_by_roles(roles=['role1', 'role2'])
+ role_creds = creds.get_creds_by_roles(
+ roles=['role1', 'role2'])
calls = user_mock.mock_calls
# Assert that the role creation is called with the 2 specified roles
self.assertEqual(len(calls), 2)
@@ -205,26 +213,26 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_all_cred_cleanup(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_tenant_create('1234', 'fake_prim_tenant')
self._mock_user_create('1234', 'fake_prim_user')
- iso_creds.get_primary_creds()
+ creds.get_primary_creds()
self._mock_tenant_create('12345', 'fake_alt_tenant')
self._mock_user_create('12345', 'fake_alt_user')
- iso_creds.get_alt_creds()
+ creds.get_alt_creds()
self._mock_tenant_create('123456', 'fake_admin_tenant')
self._mock_user_create('123456', 'fake_admin_user')
self._mock_list_roles('123456', 'admin')
- iso_creds.get_admin_creds()
+ creds.get_admin_creds()
user_mock = self.patch(
'tempest.services.identity.v2.json.identity_client.'
'IdentityClient.delete_user')
tenant_mock = self.patch(
'tempest.services.identity.v2.json.identity_client.'
'IdentityClient.delete_tenant')
- iso_creds.clear_isolated_creds()
+ creds.clear_creds()
# Verify user delete calls
calls = user_mock.mock_calls
self.assertEqual(len(calls), 3)
@@ -245,12 +253,12 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_alt_creds(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_alt_user')
self._mock_tenant_create('1234', 'fake_alt_tenant')
- alt_creds = iso_creds.get_alt_creds()
+ alt_creds = creds.get_alt_creds()
self.assertEqual(alt_creds.username, 'fake_alt_user')
self.assertEqual(alt_creds.tenant_name, 'fake_alt_tenant')
# Verify IDs
@@ -260,22 +268,22 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_no_network_creation_with_config_set(self, MockRestClient):
cfg.CONF.set_default('create_isolated_networks', False, group='auth')
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
- net = mock.patch.object(iso_creds.network_admin_client,
+ net = mock.patch.object(creds.networks_admin_client,
'delete_network')
net_mock = net.start()
- subnet = mock.patch.object(iso_creds.network_admin_client,
+ subnet = mock.patch.object(creds.subnets_admin_client,
'delete_subnet')
subnet_mock = subnet.start()
- router = mock.patch.object(iso_creds.network_admin_client,
+ router = mock.patch.object(creds.network_admin_client,
'delete_router')
router_mock = router.start()
- primary_creds = iso_creds.get_primary_creds()
+ primary_creds = creds.get_primary_creds()
self.assertEqual(net_mock.mock_calls, [])
self.assertEqual(subnet_mock.mock_calls, [])
self.assertEqual(router_mock.mock_calls, [])
@@ -288,18 +296,18 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_network_creation(self, MockRestClient):
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
- self._mock_network_create(iso_creds, '1234', 'fake_net')
- self._mock_subnet_create(iso_creds, '1234', 'fake_subnet')
+ self._mock_network_create(creds, '1234', 'fake_net')
+ self._mock_subnet_create(creds, '1234', 'fake_subnet')
self._mock_router_create('1234', 'fake_router')
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClient.'
'add_router_interface_with_subnet_id')
- primary_creds = iso_creds.get_primary_creds()
+ primary_creds = creds.get_primary_creds()
router_interface_mock.called_once_with('1234', '1234')
network = primary_creds.network
subnet = primary_creds.subnet
@@ -319,73 +327,71 @@
"description": args['name'],
"security_group_rules": [],
"id": "sg-%s" % args['tenant_id']}]}
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
# Create primary tenant and network
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
- self._mock_network_create(iso_creds, '1234', 'fake_net')
- self._mock_subnet_create(iso_creds, '1234', 'fake_subnet')
+ self._mock_network_create(creds, '1234', 'fake_net')
+ self._mock_subnet_create(creds, '1234', 'fake_subnet')
self._mock_router_create('1234', 'fake_router')
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClient.'
'add_router_interface_with_subnet_id')
- iso_creds.get_primary_creds()
+ creds.get_primary_creds()
router_interface_mock.called_once_with('1234', '1234')
router_interface_mock.reset_mock()
# Create alternate tenant and network
self._mock_user_create('12345', 'fake_alt_user')
self._mock_tenant_create('12345', 'fake_alt_tenant')
- self._mock_network_create(iso_creds, '12345', 'fake_alt_net')
- self._mock_subnet_create(iso_creds, '12345',
- 'fake_alt_subnet')
+ self._mock_network_create(creds, '12345', 'fake_alt_net')
+ self._mock_subnet_create(creds, '12345', 'fake_alt_subnet')
self._mock_router_create('12345', 'fake_alt_router')
- iso_creds.get_alt_creds()
+ creds.get_alt_creds()
router_interface_mock.called_once_with('12345', '12345')
router_interface_mock.reset_mock()
# Create admin tenant and networks
self._mock_user_create('123456', 'fake_admin_user')
self._mock_tenant_create('123456', 'fake_admin_tenant')
- self._mock_network_create(iso_creds, '123456',
- 'fake_admin_net')
- self._mock_subnet_create(iso_creds, '123456',
- 'fake_admin_subnet')
+ self._mock_network_create(creds, '123456', 'fake_admin_net')
+ self._mock_subnet_create(creds, '123456', 'fake_admin_subnet')
self._mock_router_create('123456', 'fake_admin_router')
self._mock_list_roles('123456', 'admin')
- iso_creds.get_admin_creds()
+ creds.get_admin_creds()
self.patch('tempest.services.identity.v2.json.identity_client.'
'IdentityClient.delete_user')
self.patch('tempest.services.identity.v2.json.identity_client.'
'IdentityClient.delete_tenant')
- net = mock.patch.object(iso_creds.network_admin_client,
+ net = mock.patch.object(creds.networks_admin_client,
'delete_network')
net_mock = net.start()
- subnet = mock.patch.object(iso_creds.network_admin_client,
+ subnet = mock.patch.object(creds.subnets_admin_client,
'delete_subnet')
subnet_mock = subnet.start()
- router = mock.patch.object(iso_creds.network_admin_client,
+ router = mock.patch.object(creds.network_admin_client,
'delete_router')
router_mock = router.start()
remove_router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClient.'
'remove_router_interface_with_subnet_id')
return_values = ({'status': 200}, {'ports': []})
- port_list_mock = mock.patch.object(iso_creds.network_admin_client,
+ port_list_mock = mock.patch.object(creds.network_admin_client,
'list_ports',
return_value=return_values)
port_list_mock.start()
- secgroup_list_mock = mock.patch.object(iso_creds.network_admin_client,
- 'list_security_groups',
- side_effect=side_effect)
+ secgroup_list_mock = mock.patch.object(
+ creds.network_admin_client,
+ 'list_security_groups',
+ side_effect=side_effect)
secgroup_list_mock.start()
return_values = (fake_http.fake_httplib({}, status=204), {})
remove_secgroup_mock = self.patch(
'tempest.services.network.json.network_client.'
'NetworkClient.delete', return_value=return_values)
- iso_creds.clear_isolated_creds()
+ creds.clear_creds()
# Verify default security group delete
calls = remove_secgroup_mock.mock_calls
self.assertEqual(len(calls), 3)
@@ -429,18 +435,18 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_network_alt_creation(self, MockRestClient):
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_alt_user')
self._mock_tenant_create('1234', 'fake_alt_tenant')
- self._mock_network_create(iso_creds, '1234', 'fake_alt_net')
- self._mock_subnet_create(iso_creds, '1234', 'fake_alt_subnet')
+ self._mock_network_create(creds, '1234', 'fake_alt_net')
+ self._mock_subnet_create(creds, '1234', 'fake_alt_subnet')
self._mock_router_create('1234', 'fake_alt_router')
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClient.'
'add_router_interface_with_subnet_id')
- alt_creds = iso_creds.get_alt_creds()
+ alt_creds = creds.get_alt_creds()
router_interface_mock.called_once_with('1234', '1234')
network = alt_creds.network
subnet = alt_creds.subnet
@@ -454,18 +460,18 @@
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_network_admin_creation(self, MockRestClient):
- iso_creds = isolated_creds.IsolatedCreds(name='test class')
+ creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
self._mock_assign_user_role()
self._mock_user_create('1234', 'fake_admin_user')
self._mock_tenant_create('1234', 'fake_admin_tenant')
- self._mock_network_create(iso_creds, '1234', 'fake_admin_net')
- self._mock_subnet_create(iso_creds, '1234', 'fake_admin_subnet')
+ self._mock_network_create(creds, '1234', 'fake_admin_net')
+ self._mock_subnet_create(creds, '1234', 'fake_admin_subnet')
self._mock_router_create('1234', 'fake_admin_router')
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClient.'
'add_router_interface_with_subnet_id')
self._mock_list_roles('123456', 'admin')
- admin_creds = iso_creds.get_admin_creds()
+ admin_creds = creds.get_admin_creds()
router_interface_mock.called_once_with('1234', '1234')
network = admin_creds.network
subnet = admin_creds.subnet
@@ -485,23 +491,24 @@
'subnet': False,
'dhcp': False,
}
- iso_creds = isolated_creds.IsolatedCreds(name='test class',
- network_resources=net_dict)
+ creds = dynamic_creds.DynamicCredentialProvider(
+ network_resources=net_dict,
+ **self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
- net = mock.patch.object(iso_creds.network_admin_client,
+ net = mock.patch.object(creds.networks_admin_client,
'delete_network')
net_mock = net.start()
- subnet = mock.patch.object(iso_creds.network_admin_client,
+ subnet = mock.patch.object(creds.subnets_admin_client,
'delete_subnet')
subnet_mock = subnet.start()
- router = mock.patch.object(iso_creds.network_admin_client,
+ router = mock.patch.object(creds.network_admin_client,
'delete_router')
router_mock = router.start()
- primary_creds = iso_creds.get_primary_creds()
+ primary_creds = creds.get_primary_creds()
self.assertEqual(net_mock.mock_calls, [])
self.assertEqual(subnet_mock.mock_calls, [])
self.assertEqual(router_mock.mock_calls, [])
@@ -520,14 +527,15 @@
'subnet': False,
'dhcp': False,
}
- iso_creds = isolated_creds.IsolatedCreds(name='test class',
- network_resources=net_dict)
+ creds = dynamic_creds.DynamicCredentialProvider(
+ network_resources=net_dict,
+ **self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
self.assertRaises(exceptions.InvalidConfiguration,
- iso_creds.get_primary_creds)
+ creds.get_primary_creds)
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_subnet_without_network(self, MockRestClient):
@@ -537,14 +545,15 @@
'subnet': True,
'dhcp': False,
}
- iso_creds = isolated_creds.IsolatedCreds(name='test class',
- network_resources=net_dict)
+ creds = dynamic_creds.DynamicCredentialProvider(
+ network_resources=net_dict,
+ **self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
self.assertRaises(exceptions.InvalidConfiguration,
- iso_creds.get_primary_creds)
+ creds.get_primary_creds)
@mock.patch('tempest_lib.common.rest_client.RestClient')
def test_dhcp_without_subnet(self, MockRestClient):
@@ -554,11 +563,12 @@
'subnet': False,
'dhcp': True,
}
- iso_creds = isolated_creds.IsolatedCreds(name='test class',
- network_resources=net_dict)
+ creds = dynamic_creds.DynamicCredentialProvider(
+ network_resources=net_dict,
+ **self.fixed_params)
self._mock_assign_user_role()
self._mock_list_role()
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
self.assertRaises(exceptions.InvalidConfiguration,
- iso_creds.get_primary_creds)
+ creds.get_primary_creds)
diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_preprov_creds.py
similarity index 80%
rename from tempest/tests/common/test_accounts.py
rename to tempest/tests/common/test_preprov_creds.py
index 9bf8059..8a014af 100644
--- a/tempest/tests/common/test_accounts.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -24,8 +24,8 @@
from tempest_lib import auth
from tempest_lib.services.identity.v2 import token_client
-from tempest.common import accounts
from tempest.common import cred_provider
+from tempest.common import preprov_creds
from tempest import config
from tempest import exceptions
from tempest.tests import base
@@ -34,10 +34,14 @@
from tempest.tests import fake_identity
-class TestAccount(base.TestCase):
+class TestPreProvisionedCredentials(base.TestCase):
+
+ fixed_params = {'name': 'test class',
+ 'identity_version': 'v2',
+ 'admin_role': 'admin'}
def setUp(self):
- super(TestAccount, self).setUp()
+ super(TestPreProvisionedCredentials, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.fake_http = fake_http.fake_httplib2(return_type=200)
@@ -71,7 +75,7 @@
'password': 'p', 'roles': [cfg.CONF.identity.admin_role]},
]
self.accounts_mock = self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=self.test_accounts))
cfg.CONF.set_default('test_accounts_file', 'fake_path', group='auth')
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
@@ -88,7 +92,8 @@
def test_get_hash(self):
self.stubs.Set(token_client.TokenClient, 'raw_request',
fake_identity._fake_v2_response)
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
hash_list = self._get_hash_list(self.test_accounts)
test_cred_dict = self.test_accounts[3]
test_creds = auth.get_credentials(fake_identity.FAKE_AUTH_URL,
@@ -97,8 +102,10 @@
self.assertEqual(hash_list[3], results)
def test_get_hash_dict(self):
- test_account_class = accounts.Accounts('v2', 'test_name')
- hash_dict = test_account_class.get_hash_dict(self.test_accounts)
+ test_account_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
+ hash_dict = test_account_class.get_hash_dict(
+ self.test_accounts, self.fixed_params['admin_role'])
hash_list = self._get_hash_list(self.test_accounts)
for hash in hash_list:
self.assertIn(hash, hash_dict['creds'].keys())
@@ -109,7 +116,9 @@
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True):
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = (
+ preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params))
res = test_account_class._create_hash_file('12345')
self.assertFalse(res, "_create_hash_file should return False if the "
"pseudo-lock file already exists")
@@ -119,7 +128,9 @@
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=False))
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True):
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = (
+ preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params))
res = test_account_class._create_hash_file('12345')
self.assertTrue(res, "_create_hash_file should return True if the "
"pseudo-lock doesn't already exist")
@@ -131,16 +142,16 @@
hash_list = self._get_hash_list(self.test_accounts)
mkdir_mock = self.useFixture(mockpatch.Patch('os.mkdir'))
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=False))
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True) as open_mock:
test_account_class._get_free_hash(hash_list)
- lock_path = os.path.join(lockutils.get_lock_path(accounts.CONF),
- 'test_accounts',
- hash_list[0])
+ lock_path = os.path.join(lockutils.get_lock_path(
+ preprov_creds.CONF), 'test_accounts', hash_list[0])
open_mock.assert_called_once_with(lock_path, 'w')
- mkdir_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path,
- 'test_accounts')
+ mkdir_path = os.path.join(
+ preprov_creds.CONF.oslo_concurrency.lock_path, 'test_accounts')
mkdir_mock.mock.assert_called_once_with(mkdir_path)
@mock.patch('oslo_concurrency.lockutils.lock')
@@ -150,7 +161,8 @@
self.useFixture(mockpatch.Patch('os.path.isdir', return_value=True))
# Emulate all lcoks in list are in use
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True):
self.assertRaises(exceptions.InvalidConfiguration,
@@ -161,7 +173,8 @@
# Emulate no pre-existing lock
self.useFixture(mockpatch.Patch('os.path.isdir', return_value=True))
hash_list = self._get_hash_list(self.test_accounts)
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
def _fake_is_file(path):
# Fake isfile() to return that the path exists unless a specific
@@ -174,9 +187,9 @@
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True) as open_mock:
test_account_class._get_free_hash(hash_list)
- lock_path = os.path.join(lockutils.get_lock_path(accounts.CONF),
- 'test_accounts',
- hash_list[3])
+ lock_path = os.path.join(
+ lockutils.get_lock_path(preprov_creds.CONF),
+ 'test_accounts', hash_list[3])
open_mock.assert_has_calls([mock.call(lock_path, 'w')])
@mock.patch('oslo_concurrency.lockutils.lock')
@@ -186,14 +199,15 @@
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
# Pretend the lock dir is empty
self.useFixture(mockpatch.Patch('os.listdir', return_value=[]))
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
remove_mock = self.useFixture(mockpatch.Patch('os.remove'))
rmdir_mock = self.useFixture(mockpatch.Patch('os.rmdir'))
test_account_class.remove_hash(hash_list[2])
- hash_path = os.path.join(lockutils.get_lock_path(accounts.CONF),
+ hash_path = os.path.join(lockutils.get_lock_path(preprov_creds.CONF),
'test_accounts',
hash_list[2])
- lock_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path,
+ lock_path = os.path.join(preprov_creds.CONF.oslo_concurrency.lock_path,
'test_accounts')
remove_mock.mock.assert_called_once_with(hash_path)
rmdir_mock.mock.assert_called_once_with(lock_path)
@@ -206,33 +220,37 @@
# Pretend the lock dir is empty
self.useFixture(mockpatch.Patch('os.listdir', return_value=[
hash_list[1], hash_list[4]]))
- test_account_class = accounts.Accounts('v2', 'test_name')
+ test_account_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
remove_mock = self.useFixture(mockpatch.Patch('os.remove'))
rmdir_mock = self.useFixture(mockpatch.Patch('os.rmdir'))
test_account_class.remove_hash(hash_list[2])
- hash_path = os.path.join(lockutils.get_lock_path(accounts.CONF),
+ hash_path = os.path.join(lockutils.get_lock_path(preprov_creds.CONF),
'test_accounts',
hash_list[2])
remove_mock.mock.assert_called_once_with(hash_path)
rmdir_mock.mock.assert_not_called()
def test_is_multi_user(self):
- test_accounts_class = accounts.Accounts('v2', 'test_name')
+ test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
self.assertTrue(test_accounts_class.is_multi_user())
def test_is_not_multi_user(self):
self.test_accounts = [self.test_accounts[0]]
self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=self.test_accounts))
- test_accounts_class = accounts.Accounts('v2', 'test_name')
+ test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
self.assertFalse(test_accounts_class.is_multi_user())
def test__get_creds_by_roles_one_role(self):
self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=self.test_accounts))
- test_accounts_class = accounts.Accounts('v2', 'test_name')
+ test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
hashes = test_accounts_class.hash_dict['roles']['role4']
temp_hash = hashes[0]
get_free_hash_mock = self.useFixture(mockpatch.PatchObject(
@@ -247,9 +265,10 @@
def test__get_creds_by_roles_list_role(self):
self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=self.test_accounts))
- test_accounts_class = accounts.Accounts('v2', 'test_name')
+ test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
hashes = test_accounts_class.hash_dict['roles']['role4']
hashes2 = test_accounts_class.hash_dict['roles']['role2']
hashes = list(set(hashes) & set(hashes2))
@@ -266,9 +285,10 @@
def test__get_creds_by_roles_no_admin(self):
self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=self.test_accounts))
- test_accounts_class = accounts.Accounts('v2', 'test_name')
+ test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
hashes = list(test_accounts_class.hash_dict['creds'].keys())
admin_hashes = test_accounts_class.hash_dict['roles'][
cfg.CONF.identity.admin_role]
@@ -292,9 +312,10 @@
'password': 'p', 'roles': ['role-7', 'role-11'],
'resources': {'network': 'network-2'}}]
self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=test_accounts))
- test_accounts_class = accounts.Accounts('v2', 'test_name')
+ test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
+ **self.fixed_params)
with mock.patch('tempest.services.compute.json.networks_client.'
'NetworksClient.list_networks',
return_value={'networks': [{'name': 'network-2',
@@ -312,6 +333,10 @@
class TestNotLockingAccount(base.TestCase):
+ fixed_params = {'name': 'test class',
+ 'identity_version': 'v2',
+ 'admin_role': 'admin'}
+
def setUp(self):
super(TestNotLockingAccount, self).setUp()
self.useFixture(fake_config.ConfigFixture())
@@ -326,13 +351,14 @@
'password': 'p'},
]
self.useFixture(mockpatch.Patch(
- 'tempest.common.accounts.read_accounts_yaml',
+ 'tempest.common.preprov_creds.read_accounts_yaml',
return_value=self.test_accounts))
cfg.CONF.set_default('test_accounts_file', '', group='auth')
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
def test_get_creds_roles_nonlocking_invalid(self):
- test_accounts_class = accounts.NotLockingAccounts('v2', 'test_name')
+ test_accounts_class = preprov_creds.NonLockingCredentialProvider(
+ **self.fixed_params)
self.assertRaises(exceptions.InvalidConfiguration,
test_accounts_class.get_creds_by_roles,
['fake_role'])
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index 00b8470..4225da8 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -17,37 +17,15 @@
import six
from tempest.services.baremetal.v1.json import baremetal_client
-from tempest.services.compute.json import agents_client
-from tempest.services.compute.json import aggregates_client
-from tempest.services.compute.json import availability_zone_client
-from tempest.services.compute.json import certificates_client
-from tempest.services.compute.json import extensions_client
-from tempest.services.compute.json import fixed_ips_client
-from tempest.services.compute.json import flavors_client
-from tempest.services.compute.json import floating_ip_pools_client
-from tempest.services.compute.json import floating_ips_bulk_client
from tempest.services.compute.json import floating_ips_client
-from tempest.services.compute.json import hosts_client
-from tempest.services.compute.json import hypervisor_client
-from tempest.services.compute.json import images_client
-from tempest.services.compute.json import instance_usage_audit_log_client
from tempest.services.compute.json import interfaces_client
-from tempest.services.compute.json import keypairs_client
-from tempest.services.compute.json import limits_client
-from tempest.services.compute.json import migrations_client
-from tempest.services.compute.json import networks_client as nova_net_client
from tempest.services.compute.json import quota_classes_client
-from tempest.services.compute.json import quotas_client
-from tempest.services.compute.json import security_group_default_rules_client \
- as nova_secgrop_default_client
from tempest.services.compute.json import security_group_rules_client
-from tempest.services.compute.json import security_groups_client
from tempest.services.compute.json import server_groups_client
from tempest.services.compute.json import servers_client
from tempest.services.compute.json import services_client
-from tempest.services.compute.json import tenant_usages_client
-from tempest.services.compute.json import volumes_extensions_client \
- as compute_volumes_extensions_client
+from tempest.services.compute.json import volumes_client \
+ as compute_volumes_client
from tempest.services.data_processing.v1_1 import data_processing_client
from tempest.services.database.json import flavors_client as db_flavor_client
from tempest.services.database.json import versions_client as db_version_client
@@ -109,35 +87,14 @@
def test_service_client_creations_with_specified_args(self, mock_init):
test_clients = [
baremetal_client.BaremetalClient,
- agents_client.AgentsClient,
- aggregates_client.AggregatesClient,
- availability_zone_client.AvailabilityZoneClient,
- certificates_client.CertificatesClient,
- extensions_client.ExtensionsClient,
- fixed_ips_client.FixedIPsClient,
- flavors_client.FlavorsClient,
- floating_ip_pools_client.FloatingIPPoolsClient,
- floating_ips_bulk_client.FloatingIPsBulkClient,
floating_ips_client.FloatingIPsClient,
- hosts_client.HostsClient,
- hypervisor_client.HypervisorClient,
- images_client.ImagesClient,
- instance_usage_audit_log_client.InstanceUsagesAuditLogClient,
interfaces_client.InterfacesClient,
- keypairs_client.KeyPairsClient,
- limits_client.LimitsClient,
- migrations_client.MigrationsClient,
- nova_net_client.NetworksClient,
- quotas_client.QuotasClient,
quota_classes_client.QuotaClassesClient,
- nova_secgrop_default_client.SecurityGroupDefaultRulesClient,
security_group_rules_client.SecurityGroupRulesClient,
- security_groups_client.SecurityGroupsClient,
server_groups_client.ServerGroupsClient,
servers_client.ServersClient,
services_client.ServicesClient,
- tenant_usages_client.TenantUsagesClient,
- compute_volumes_extensions_client.VolumesExtensionsClient,
+ compute_volumes_client.VolumesClient,
data_processing_client.DataProcessingClient,
db_flavor_client.DatabaseFlavorsClient,
db_version_client.DatabaseVersionsClient,
diff --git a/tempest/tests/fake_config.py b/tempest/tests/fake_config.py
index 4898c9c..ca8bc3e 100644
--- a/tempest/tests/fake_config.py
+++ b/tempest/tests/fake_config.py
@@ -48,9 +48,13 @@
for config_option in ['username', 'password', 'tenant_name']:
# Identity group items
for prefix in ['', 'alt_', 'admin_']:
+ if prefix == 'admin_':
+ group = 'auth'
+ else:
+ group = 'identity'
self.conf.set_default(prefix + config_option,
'fake_' + config_option,
- group='identity')
+ group=group)
class FakePrivate(config.TempestConfigPrivate):
diff --git a/tempest/tests/services/compute/test_agents_client.py b/tempest/tests/services/compute/test_agents_client.py
deleted file mode 100644
index 31e576e..0000000
--- a/tempest/tests/services/compute/test_agents_client.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# 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_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import agents_client
-from tempest.tests.services.compute import base
-
-
-class TestAgentsClient(base.BaseComputeServiceTest):
- FAKE_CREATE_AGENT = {
- "agent":
- {
- "url": "http://foo.com",
- "hypervisor": "kvm",
- "md5hash": "md5",
- "version": "2",
- "architecture": "x86_64",
- "os": "linux",
- "agent_id": 1
- }
- }
-
- FAKE_UPDATE_AGENT = {
- "agent":
- {
- "url": "http://foo.com",
- "hypervisor": "kvm",
- "md5hash": "md5",
- "version": "2",
- "architecture": "x86_64",
- "os": "linux",
- "agent_id": 1
- }
- }
-
- def setUp(self):
- super(TestAgentsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = agents_client.AgentsClient(fake_auth,
- 'compute', 'regionOne')
-
- def _test_list_agents(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_agents,
- 'tempest.common.service_client.ServiceClient.get',
- {"agents": []},
- bytes_body)
- self.check_service_client_function(
- self.client.list_agents,
- 'tempest.common.service_client.ServiceClient.get',
- {"agents": []},
- bytes_body,
- hypervisor="kvm")
-
- def _test_create_agent(self, bytes_body=False):
- self.check_service_client_function(
- self.client.create_agent,
- 'tempest.common.service_client.ServiceClient.post',
- self.FAKE_CREATE_AGENT,
- bytes_body,
- url="http://foo.com", hypervisor="kvm", md5hash="md5",
- version="2", architecture="x86_64", os="linux")
-
- def _test_delete_agent(self):
- self.check_service_client_function(
- self.client.delete_agent,
- 'tempest.common.service_client.ServiceClient.delete',
- {}, agent_id="1")
-
- def _test_update_agent(self, bytes_body=False):
- self.check_service_client_function(
- self.client.update_agent,
- 'tempest.common.service_client.ServiceClient.put',
- self.FAKE_UPDATE_AGENT,
- bytes_body,
- agent_id="1", url="http://foo.com", md5hash="md5", version="2")
-
- def test_list_agents_with_str_body(self):
- self._test_list_agents()
-
- def test_list_agents_with_bytes_body(self):
- self._test_list_agents(bytes_body=True)
-
- def test_create_agent_with_str_body(self):
- self._test_create_agent()
-
- def test_create_agent_with_bytes_body(self):
- self._test_create_agent(bytes_body=True)
-
- def test_delete_agent(self):
- self._test_delete_agent()
-
- def test_update_agent_with_str_body(self):
- self._test_update_agent()
-
- def test_update_agent_with_bytes_body(self):
- self._test_update_agent(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_aggregates_client.py b/tempest/tests/services/compute/test_aggregates_client.py
deleted file mode 100644
index e92b76b..0000000
--- a/tempest/tests/services/compute/test_aggregates_client.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# 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_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import aggregates_client
-from tempest.tests.services.compute import base
-
-
-class TestAggregatesClient(base.BaseComputeServiceTest):
- FAKE_SHOW_AGGREGATE = {
- "aggregate":
- {
- "name": "hoge",
- "availability_zone": None,
- "deleted": False,
- "created_at":
- "2015-07-16T03:07:32.000000",
- "updated_at": None,
- "hosts": [],
- "deleted_at": None,
- "id": 1,
- "metadata": {}
- }
- }
-
- FAKE_CREATE_AGGREGATE = {
- "aggregate":
- {
- "name": u'\xf4',
- "availability_zone": None,
- "deleted": False,
- "created_at": "2015-07-21T04:11:18.000000",
- "updated_at": None,
- "deleted_at": None,
- "id": 1
- }
- }
-
- FAKE_UPDATE_AGGREGATE = {
- "aggregate":
- {
- "name": u'\xe9',
- "availability_zone": None,
- "deleted": False,
- "created_at": "2015-07-16T03:07:32.000000",
- "updated_at": "2015-07-23T05:16:29.000000",
- "hosts": [],
- "deleted_at": None,
- "id": 1,
- "metadata": {}
- }
- }
-
- def setUp(self):
- super(TestAggregatesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = aggregates_client.AggregatesClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_aggregates(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_aggregates,
- 'tempest.common.service_client.ServiceClient.get',
- {"aggregates": []},
- bytes_body)
-
- def test_list_aggregates_with_str_body(self):
- self._test_list_aggregates()
-
- def test_list_aggregates_with_bytes_body(self):
- self._test_list_aggregates(bytes_body=True)
-
- def _test_show_aggregate(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_aggregate,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_SHOW_AGGREGATE,
- bytes_body,
- aggregate_id=1)
-
- def test_show_aggregate_with_str_body(self):
- self._test_show_aggregate()
-
- def test_show_aggregate_with_bytes_body(self):
- self._test_show_aggregate(bytes_body=True)
-
- def _test_create_aggregate(self, bytes_body=False):
- self.check_service_client_function(
- self.client.create_aggregate,
- 'tempest.common.service_client.ServiceClient.post',
- self.FAKE_CREATE_AGGREGATE,
- bytes_body,
- name='hoge')
-
- def test_create_aggregate_with_str_body(self):
- self._test_create_aggregate()
-
- def test_create_aggregate_with_bytes_body(self):
- self._test_create_aggregate(bytes_body=True)
-
- def test_delete_aggregate(self):
- self.check_service_client_function(
- self.client.delete_aggregate,
- 'tempest.common.service_client.ServiceClient.delete',
- {}, aggregate_id="1")
-
- def _test_update_aggregate(self, bytes_body=False):
- self.check_service_client_function(
- self.client.update_aggregate,
- 'tempest.common.service_client.ServiceClient.put',
- self.FAKE_UPDATE_AGGREGATE,
- bytes_body,
- aggregate_id=1)
-
- def test_update_aggregate_with_str_body(self):
- self._test_update_aggregate()
-
- def test_update_aggregate_with_bytes_body(self):
- self._test_update_aggregate(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_availability_zone_client.py b/tempest/tests/services/compute/test_availability_zone_client.py
deleted file mode 100644
index 6100f44..0000000
--- a/tempest/tests/services/compute/test_availability_zone_client.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import availability_zone_client
-from tempest.tests.services.compute import base
-
-
-class TestAvailabilityZoneClient(base.BaseComputeServiceTest):
-
- FAKE_AVAILABIRITY_ZONE_INFO = {
- "availabilityZoneInfo":
- [
- {
- "zoneState": {
- "available": True
- },
- "hosts": None,
- "zoneName": u'\xf4'
- }
- ]
- }
-
- def setUp(self):
- super(TestAvailabilityZoneClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = availability_zone_client.AvailabilityZoneClient(
- fake_auth, 'compute', 'regionOne')
-
- def test_list_availability_zones_with_str_body(self):
- self.check_service_client_function(
- self.client.list_availability_zones,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_AVAILABIRITY_ZONE_INFO)
-
- def test_list_availability_zones_with_bytes_body(self):
- self.check_service_client_function(
- self.client.list_availability_zones,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_AVAILABIRITY_ZONE_INFO, to_utf=True)
diff --git a/tempest/tests/services/compute/test_baremetal_nodes_client.py b/tempest/tests/services/compute/test_baremetal_nodes_client.py
deleted file mode 100644
index 86c035c..0000000
--- a/tempest/tests/services/compute/test_baremetal_nodes_client.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# 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.
-
-import copy
-
-from tempest_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import baremetal_nodes_client
-from tempest.tests.services.compute import base
-
-
-class TestBareMetalNodesClient(base.BaseComputeServiceTest):
-
- FAKE_NODE_INFO = {'cpus': '8',
- 'disk_gb': '64',
- 'host': '10.0.2.15',
- 'id': 'Identifier',
- 'instance_uuid': "null",
- 'interfaces': [
- {
- "address": "20::01",
- "datapath_id": "null",
- "id": 1,
- "port_no": None
- }
- ],
- 'memory_mb': '8192',
- 'task_state': None}
-
- def setUp(self):
- super(TestBareMetalNodesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.baremetal_nodes_client = (baremetal_nodes_client.
- BaremetalNodesClient
- (fake_auth, 'compute',
- 'regionOne'))
-
- def _test_bareMetal_nodes(self, operation='list', bytes_body=False):
- if operation != 'list':
- expected = {"node": self.FAKE_NODE_INFO}
- function = self.baremetal_nodes_client.show_baremetal_node
- else:
- node_info = copy.deepcopy(self.FAKE_NODE_INFO)
- del node_info['instance_uuid']
- expected = {"nodes": [node_info]}
- function = self.baremetal_nodes_client.list_baremetal_nodes
-
- self.check_service_client_function(
- function,
- 'tempest.common.service_client.ServiceClient.get',
- expected, bytes_body, 200,
- baremetal_node_id='Identifier')
-
- def test_list_bareMetal_nodes_with_str_body(self):
- self._test_bareMetal_nodes()
-
- def test_list_bareMetal_nodes_with_bytes_body(self):
- self._test_bareMetal_nodes(bytes_body=True)
-
- def test_show_bareMetal_node_with_str_body(self):
- self._test_bareMetal_nodes('show')
-
- def test_show_bareMetal_node_with_bytes_body(self):
- self._test_bareMetal_nodes('show', True)
diff --git a/tempest/tests/services/compute/test_certificates_client.py b/tempest/tests/services/compute/test_certificates_client.py
deleted file mode 100644
index 2ba90d0..0000000
--- a/tempest/tests/services/compute/test_certificates_client.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# 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.
-
-import copy
-
-from tempest_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import certificates_client
-from tempest.tests.services.compute import base
-
-
-class TestCertificatesClient(base.BaseComputeServiceTest):
-
- FAKE_CERTIFICATE = {
- "certificate": {
- "data": "-----BEGIN----MIICyzCCAjSgAwI----END CERTIFICATE-----\n",
- "private_key": None
- }
- }
-
- def setUp(self):
- super(TestCertificatesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = certificates_client.CertificatesClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_show_certificate(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_certificate,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_CERTIFICATE,
- bytes_body,
- certificate_id="fake-id")
-
- def test_show_certificate_with_str_body(self):
- self._test_show_certificate()
-
- def test_show_certificate_with_bytes_body(self):
- self._test_show_certificate(bytes_body=True)
-
- def _test_create_certificate(self, bytes_body=False):
- cert = copy.deepcopy(self.FAKE_CERTIFICATE)
- cert['certificate']['private_key'] = "my_private_key"
- self.check_service_client_function(
- self.client.create_certificate,
- 'tempest.common.service_client.ServiceClient.post',
- cert,
- bytes_body)
-
- def test_create_certificate_with_str_body(self):
- self._test_create_certificate()
-
- def test_create_certificate_with_bytes_body(self):
- self._test_create_certificate(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_extensions_client.py b/tempest/tests/services/compute/test_extensions_client.py
deleted file mode 100644
index 21efc52..0000000
--- a/tempest/tests/services/compute/test_extensions_client.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# 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_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import extensions_client
-from tempest.tests.services.compute import base
-
-
-class TestExtensionsClient(base.BaseComputeServiceTest):
-
- FAKE_SHOW_EXTENSION = {
- "extension": {
- "updated": "2011-06-09T00:00:00Z",
- "name": "Multinic",
- "links": [],
- "namespace":
- "http://docs.openstack.org/compute/ext/multinic/api/v1.1",
- "alias": "NMN",
- "description": u'\u2740(*\xb4\u25e1`*)\u2740'
- }
- }
-
- def setUp(self):
- super(TestExtensionsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = extensions_client.ExtensionsClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_extensions(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_extensions,
- 'tempest.common.service_client.ServiceClient.get',
- {"extensions": []},
- bytes_body)
-
- def test_list_extensions_with_str_body(self):
- self._test_list_extensions()
-
- def test_list_extensions_with_bytes_body(self):
- self._test_list_extensions(bytes_body=True)
-
- def _test_show_extension(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_extension,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_SHOW_EXTENSION,
- bytes_body,
- extension_alias="NMN")
-
- def test_show_extension_with_str_body(self):
- self._test_show_extension()
-
- def test_show_extension_with_bytes_body(self):
- self._test_show_extension(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_fixedIPs_client.py b/tempest/tests/services/compute/test_fixedIPs_client.py
deleted file mode 100644
index 5acb422..0000000
--- a/tempest/tests/services/compute/test_fixedIPs_client.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# 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_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import fixed_ips_client
-from tempest.tests.services.compute import base
-
-
-class TestFixedIPsClient(base.BaseComputeServiceTest):
- FIXED_IP_INFO = {"fixed_ip": {"address": "10.0.0.1",
- "cidr": "10.11.12.0/24",
- "host": "localhost",
- "hostname": "OpenStack"}}
-
- def setUp(self):
- super(TestFixedIPsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.fixedIPsClient = (fixed_ips_client.
- FixedIPsClient
- (fake_auth, 'compute',
- 'regionOne'))
-
- def _test_show_fixed_ip(self, bytes_body=False):
- self.check_service_client_function(
- self.fixedIPsClient.show_fixed_ip,
- 'tempest.common.service_client.ServiceClient.get',
- self.FIXED_IP_INFO, bytes_body,
- status=200, fixed_ip='Identifier')
-
- def test_show_fixed_ip_with_str_body(self):
- self._test_show_fixed_ip()
-
- def test_show_fixed_ip_with_bytes_body(self):
- self._test_show_fixed_ip(True)
diff --git a/tempest/tests/services/compute/test_floating_ip_pools_client.py b/tempest/tests/services/compute/test_floating_ip_pools_client.py
deleted file mode 100644
index 1cb4bf3..0000000
--- a/tempest/tests/services/compute/test_floating_ip_pools_client.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import floating_ip_pools_client
-from tempest.tests.services.compute import base
-
-
-class TestFloatingIPPoolsClient(base.BaseComputeServiceTest):
-
- FAKE_FLOATING_IP_POOLS = {
- "floating_ip_pools":
- [
- {"name": u'\u3042'},
- {"name": u'\u3044'}
- ]
- }
-
- def setUp(self):
- super(TestFloatingIPPoolsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = floating_ip_pools_client.FloatingIPPoolsClient(
- fake_auth, 'compute', 'regionOne')
-
- def test_list_floating_ip_pools_with_str_body(self):
- self.check_service_client_function(
- self.client.list_floating_ip_pools,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_FLOATING_IP_POOLS)
-
- def test_list_floating_ip_pools_with_bytes_body(self):
- self.check_service_client_function(
- self.client.list_floating_ip_pools,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_FLOATING_IP_POOLS, to_utf=True)
diff --git a/tempest/tests/services/compute/test_floating_ips_bulk_client.py b/tempest/tests/services/compute/test_floating_ips_bulk_client.py
deleted file mode 100644
index 600985b..0000000
--- a/tempest/tests/services/compute/test_floating_ips_bulk_client.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# 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_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import floating_ips_bulk_client
-from tempest.tests.services.compute import base
-
-
-class TestFloatingIPsBulkClient(base.BaseComputeServiceTest):
-
- FAKE_FIP_BULK_LIST = {"floating_ip_info": [{
- "address": "10.10.10.1",
- "instance_uuid": None,
- "fixed_ip": None,
- "interface": "eth0",
- "pool": "nova",
- "project_id": None
- },
- {
- "address": "10.10.10.2",
- "instance_uuid": None,
- "fixed_ip": None,
- "interface": "eth0",
- "pool": "nova",
- "project_id": None
- }]}
-
- def setUp(self):
- super(TestFloatingIPsBulkClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = floating_ips_bulk_client.FloatingIPsBulkClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_floating_ips_bulk(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_floating_ips_bulk,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_FIP_BULK_LIST,
- to_utf=bytes_body)
-
- def _test_create_floating_ips_bulk(self, bytes_body=False):
- fake_fip_create_data = {"floating_ips_bulk_create": {
- "ip_range": "192.168.1.0/24", "pool": "nova", "interface": "eth0"}}
- self.check_service_client_function(
- self.client.create_floating_ips_bulk,
- 'tempest.common.service_client.ServiceClient.post',
- fake_fip_create_data,
- to_utf=bytes_body,
- ip_range="192.168.1.0/24", pool="nova", interface="eth0")
-
- def _test_delete_floating_ips_bulk(self, bytes_body=False):
- fake_fip_delete_data = {"floating_ips_bulk_delete": "192.168.1.0/24"}
- self.check_service_client_function(
- self.client.delete_floating_ips_bulk,
- 'tempest.common.service_client.ServiceClient.put',
- fake_fip_delete_data,
- to_utf=bytes_body,
- ip_range="192.168.1.0/24")
-
- def test_list_floating_ips_bulk_with_str_body(self):
- self._test_list_floating_ips_bulk()
-
- def test_list_floating_ips_bulk_with_bytes_body(self):
- self._test_list_floating_ips_bulk(True)
-
- def test_create_floating_ips_bulk_with_str_body(self):
- self._test_create_floating_ips_bulk()
-
- def test_create_floating_ips_bulk_with_bytes_body(self):
- self._test_create_floating_ips_bulk(True)
-
- def test_delete_floating_ips_bulk_with_str_body(self):
- self._test_delete_floating_ips_bulk()
-
- def test_delete_floating_ips_bulk_with_bytes_body(self):
- self._test_delete_floating_ips_bulk(True)
diff --git a/tempest/tests/services/compute/test_floating_ips_client.py b/tempest/tests/services/compute/test_floating_ips_client.py
new file mode 100644
index 0000000..ee22004
--- /dev/null
+++ b/tempest/tests/services/compute/test_floating_ips_client.py
@@ -0,0 +1,113 @@
+# Copyright 2015 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslotest import mockpatch
+from tempest_lib import exceptions as lib_exc
+
+from tempest.services.compute.json import floating_ips_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestFloatingIpsClient(base.BaseComputeServiceTest):
+
+ floating_ip = {"fixed_ip": None,
+ "id": "46d61064-13ba-4bf0-9557-69de824c3d6f",
+ "instance_id": "a1daa443-a6bb-463e-aea2-104b7d912eb8",
+ "ip": "10.10.10.1",
+ "pool": "nova"}
+
+ def setUp(self):
+ super(TestFloatingIpsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = floating_ips_client.FloatingIPsClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def _test_list_floating_ips(self, bytes_body=False):
+ expected = {'floating_ips': [TestFloatingIpsClient.floating_ip]}
+ self.check_service_client_function(
+ self.client.list_floating_ips,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected,
+ bytes_body)
+
+ def test_list_floating_ips_str_body(self):
+ self._test_list_floating_ips(bytes_body=False)
+
+ def test_list_floating_ips_byte_body(self):
+ self._test_list_floating_ips(bytes_body=True)
+
+ def _test_show_floating_ip(self, bytes_body=False):
+ expected = {"floating_ip": TestFloatingIpsClient.floating_ip}
+ self.check_service_client_function(
+ self.client.show_floating_ip,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected,
+ bytes_body,
+ floating_ip_id='a1daa443-a6bb-463e-aea2-104b7d912eb8')
+
+ def test_show_floating_ip_str_body(self):
+ self._test_show_floating_ip(bytes_body=False)
+
+ def test_show_floating_ip_byte_body(self):
+ self._test_show_floating_ip(bytes_body=True)
+
+ def _test_create_floating_ip(self, bytes_body=False):
+ expected = {"floating_ip": TestFloatingIpsClient.floating_ip}
+ self.check_service_client_function(
+ self.client.create_floating_ip,
+ 'tempest.common.service_client.ServiceClient.post',
+ expected,
+ bytes_body,
+ pool_name='nova')
+
+ def test_create_floating_ip_str_body(self):
+ self._test_create_floating_ip(bytes_body=False)
+
+ def test_create_floating_ip_byte_body(self):
+ self._test_create_floating_ip(bytes_body=True)
+
+ def test_delete_floating_ip(self):
+ self.check_service_client_function(
+ self.client.delete_floating_ip,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {}, status=202, floating_ip_id='fake-id')
+
+ def test_associate_floating_ip_to_server(self):
+ self.check_service_client_function(
+ self.client.associate_floating_ip_to_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {}, status=202, floating_ip='10.10.10.1',
+ server_id='c782b7a9-33cd-45f0-b795-7f87f456408b')
+
+ def test_disassociate_floating_ip_from_server(self):
+ self.check_service_client_function(
+ self.client.disassociate_floating_ip_from_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {}, status=202, floating_ip='10.10.10.1',
+ server_id='c782b7a9-33cd-45f0-b795-7f87f456408b')
+
+ def test_is_resource_deleted_true(self):
+ self.useFixture(mockpatch.Patch(
+ 'tempest.services.compute.json.floating_ips_client.'
+ 'FloatingIPsClient.show_floating_ip',
+ side_effect=lib_exc.NotFound()))
+ self.assertTrue(self.client.is_resource_deleted('fake-id'))
+
+ def test_is_resource_deleted_false(self):
+ self.useFixture(mockpatch.Patch(
+ 'tempest.services.compute.json.floating_ips_client.'
+ 'FloatingIPsClient.show_floating_ip',
+ return_value={"floating_ip": TestFloatingIpsClient.floating_ip}))
+ self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/services/compute/test_images_client.py b/tempest/tests/services/compute/test_images_client.py
new file mode 100644
index 0000000..1d532b7
--- /dev/null
+++ b/tempest/tests/services/compute/test_images_client.py
@@ -0,0 +1,240 @@
+# 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.
+
+import copy
+
+from oslotest import mockpatch
+from tempest_lib import exceptions as lib_exc
+
+from tempest.services.compute.json import images_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestImagesClient(base.BaseComputeServiceTest):
+ # Data Dictionaries used for testing #
+ FAKE_IMAGE_METADATA = {
+ "list":
+ {"metadata": {
+ "auto_disk_config": "True",
+ "Label": "Changed"
+ }},
+ "set_item":
+ {"meta": {
+ "auto_disk_config": "True"
+ }},
+ "show_item":
+ {"meta": {
+ "kernel_id": "nokernel",
+ }},
+ "update":
+ {"metadata": {
+ "kernel_id": "False",
+ "Label": "UpdatedImage"
+ }},
+ "set":
+ {"metadata": {
+ "Label": "Changed",
+ "auto_disk_config": "True"
+ }},
+ "delete_item": {}
+ }
+
+ FAKE_IMAGE_DATA = {
+ "list":
+ {"images": [
+ {"id": "70a599e0-31e7-49b7-b260-868f441e862b",
+ "links": [
+ {"href": "http://openstack.example.com/v2/openstack" +
+ "/images/70a599e0-31e7-49b7-b260-868f441e862b",
+ "rel": "self"
+ }
+ ],
+ "name": "fakeimage7"
+ }]},
+ "show": {"image": {
+ "created": "2011-01-01T01:02:03Z",
+ "id": "70a599e0-31e7-49b7-b260-868f441e862b",
+ "links": [
+ {
+ "href": "http://openstack.example.com/v2/openstack" +
+ "/images/70a599e0-31e7-49b7-b260-868f441e862b",
+ "rel": "self"
+ },
+ ],
+ "metadata": {
+ "architecture": "x86_64",
+ "auto_disk_config": "True",
+ "kernel_id": "nokernel",
+ "ramdisk_id": "nokernel"
+ },
+ "minDisk": 0,
+ "minRam": 0,
+ "name": "fakeimage7",
+ "progress": 100,
+ "status": "ACTIVE",
+ "updated": "2011-01-01T01:02:03Z"}},
+ "delete": {}
+ }
+ func2mock = {
+ 'get': 'tempest.common.service_client.ServiceClient.get',
+ 'post': 'tempest.common.service_client.ServiceClient.post',
+ 'put': 'tempest.common.service_client.ServiceClient.put',
+ 'delete': 'tempest.common.service_client.ServiceClient.delete'}
+ # Variable definition
+ FAKE_IMAGE_ID = FAKE_IMAGE_DATA['show']['image']['id']
+ FAKE_CREATE_INFO = {'location': 'None'}
+ FAKE_METADATA = FAKE_IMAGE_METADATA['show_item']['meta']
+
+ def setUp(self):
+ super(TestImagesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = images_client.ImagesClient(fake_auth,
+ "compute", "regionOne")
+
+ def _test_image_operation(self, operation="delete", bytes_body=False):
+ response_code = 200
+ mock_operation = self.func2mock['get']
+ expected_op = self.FAKE_IMAGE_DATA[operation]
+ params = {"image_id": self.FAKE_IMAGE_ID}
+ if operation == 'list':
+ function = self.client.list_images
+ elif operation == 'show':
+ function = self.client.show_image
+ else:
+ function = self.client.delete_image
+ mock_operation = self.func2mock['delete']
+ response_code = 204
+
+ self.check_service_client_function(
+ function, mock_operation, expected_op,
+ bytes_body, response_code, **params)
+
+ def _test_image_metadata(self, operation="set_item", bytes_body=False):
+ response_code = 200
+ expected_op = self.FAKE_IMAGE_METADATA[operation]
+ if operation == 'list':
+ function = self.client.list_image_metadata
+ mock_operation = self.func2mock['get']
+ params = {"image_id": self.FAKE_IMAGE_ID}
+
+ elif operation == 'set':
+ function = self.client.set_image_metadata
+ mock_operation = self.func2mock['put']
+ params = {"image_id": "_dummy_data",
+ "meta": self.FAKE_METADATA}
+
+ elif operation == 'update':
+ function = self.client.update_image_metadata
+ mock_operation = self.func2mock['post']
+ params = {"image_id": self.FAKE_IMAGE_ID,
+ "meta": self.FAKE_METADATA}
+
+ elif operation == 'show_item':
+ mock_operation = self.func2mock['get']
+ function = self.client.show_image_metadata_item
+ params = {"image_id": self.FAKE_IMAGE_ID,
+ "key": "123"}
+
+ elif operation == 'delete_item':
+ function = self.client.delete_image_metadata_item
+ mock_operation = self.func2mock['delete']
+ response_code = 204
+ params = {"image_id": self.FAKE_IMAGE_ID,
+ "key": "123"}
+
+ else:
+ function = self.client.set_image_metadata_item
+ mock_operation = self.func2mock['put']
+ params = {"image_id": self.FAKE_IMAGE_ID,
+ "key": "123",
+ "meta": self.FAKE_METADATA}
+
+ self.check_service_client_function(
+ function, mock_operation, expected_op,
+ bytes_body, response_code, **params)
+
+ def _test_resource_deleted(self, bytes_body=False):
+ params = {"id": self.FAKE_IMAGE_ID}
+ expected_op = self.FAKE_IMAGE_DATA['show']['image']
+ self.useFixture(mockpatch.Patch('tempest.services.compute.json'
+ '.images_client.ImagesClient.show_image',
+ side_effect=lib_exc.NotFound))
+ self.assertEqual(True, self.client.is_resource_deleted(**params))
+ tempdata = copy.deepcopy(self.FAKE_IMAGE_DATA['show'])
+ tempdata['image']['id'] = None
+ self.useFixture(mockpatch.Patch('tempest.services.compute.json'
+ '.images_client.ImagesClient.show_image',
+ return_value=expected_op))
+ self.assertEqual(False, self.client.is_resource_deleted(**params))
+
+ def test_list_images_with_str_body(self):
+ self._test_image_operation('list')
+
+ def test_list_images_with_bytes_body(self):
+ self._test_image_operation('list', True)
+
+ def test_show_image_with_str_body(self):
+ self._test_image_operation('show')
+
+ def test_show_image_with_bytes_body(self):
+ self._test_image_operation('show', True)
+
+ def test_delete_image_with_str_body(self):
+ self._test_image_operation('delete')
+
+ def test_delete_image_with_bytes_body(self):
+ self._test_image_operation('delete', True)
+
+ def test_list_image_metadata_with_str_body(self):
+ self._test_image_metadata('list')
+
+ def test_list_image_metadata_with_bytes_body(self):
+ self._test_image_metadata('list', True)
+
+ def test_set_image_metadata_with_str_body(self):
+ self._test_image_metadata('set')
+
+ def test_set_image_metadata_with_bytes_body(self):
+ self._test_image_metadata('set', True)
+
+ def test_update_image_metadata_with_str_body(self):
+ self._test_image_metadata('update')
+
+ def test_update_image_metadata_with_bytes_body(self):
+ self._test_image_metadata('update', True)
+
+ def test_set_image_metadata_item_with_str_body(self):
+ self._test_image_metadata()
+
+ def test_set_image_metadata_item_with_bytes_body(self):
+ self._test_image_metadata(bytes_body=True)
+
+ def test_show_image_metadata_item_with_str_body(self):
+ self._test_image_metadata('show_item')
+
+ def test_show_image_metadata_item_with_bytes_body(self):
+ self._test_image_metadata('show_item', True)
+
+ def test_delete_image_metadata_item_with_str_body(self):
+ self._test_image_metadata('delete_item')
+
+ def test_delete_image_metadata_item_with_bytes_body(self):
+ self._test_image_metadata('delete_item', True)
+
+ def test_resource_delete_with_str_body(self):
+ self._test_resource_deleted()
+
+ def test_resource_delete_with_bytes_body(self):
+ self._test_resource_deleted(True)
diff --git a/tempest/tests/services/compute/test_interfaces_client.py b/tempest/tests/services/compute/test_interfaces_client.py
new file mode 100644
index 0000000..235585a
--- /dev/null
+++ b/tempest/tests/services/compute/test_interfaces_client.py
@@ -0,0 +1,98 @@
+# 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.compute.json import interfaces_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestInterfacesClient(base.BaseComputeServiceTest):
+ # Data Values to be used for testing #
+ FAKE_INTERFACE_DATA = {
+ "fixed_ips": [{
+ "ip_address": "192.168.1.1",
+ "subnet_id": "f8a6e8f8-c2ec-497c-9f23-da9616de54ef"
+ }],
+ "mac_addr": "fa:16:3e:4c:2c:30",
+ "net_id": "3cb9bc59-5699-4588-a4b1-b87f96708bc6",
+ "port_id": "ce531f90-199f-48c0-816c-13e38010b442",
+ "port_state": "ACTIVE"}
+
+ FAKE_SHOW_DATA = {
+ "interfaceAttachment": FAKE_INTERFACE_DATA}
+ FAKE_LIST_DATA = {
+ "interfaceAttachments": [FAKE_INTERFACE_DATA]}
+
+ FAKE_SERVER_ID = "ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5"
+ FAKE_PORT_ID = FAKE_SHOW_DATA['interfaceAttachment']['port_id']
+ func2mock = {
+ 'delete': 'tempest.common.service_client.ServiceClient.delete',
+ 'get': 'tempest.common.service_client.ServiceClient.get',
+ 'post': 'tempest.common.service_client.ServiceClient.post'}
+
+ def setUp(self):
+ super(TestInterfacesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = interfaces_client.InterfacesClient(fake_auth,
+ "compute",
+ "regionOne")
+
+ def _test_interface_operation(self, operation="create", bytes_body=False):
+ response_code = 200
+ expected_op = self.FAKE_SHOW_DATA
+ mock_operation = self.func2mock['get']
+ params = {'server_id': self.FAKE_SERVER_ID,
+ 'port_id': self.FAKE_PORT_ID}
+ if operation == 'list':
+ expected_op = self.FAKE_LIST_DATA
+ function = self.client.list_interfaces
+ params = {'server_id': self.FAKE_SERVER_ID}
+ elif operation == 'show':
+ function = self.client.show_interface
+ elif operation == 'delete':
+ expected_op = {}
+ mock_operation = self.func2mock['delete']
+ function = self.client.delete_interface
+ response_code = 202
+ else:
+ function = self.client.create_interface
+ mock_operation = self.func2mock['post']
+
+ self.check_service_client_function(
+ function, mock_operation, expected_op,
+ bytes_body, response_code, **params)
+
+ def test_list_interfaces_with_str_body(self):
+ self._test_interface_operation('list')
+
+ def test_list_interfaces_with_bytes_body(self):
+ self._test_interface_operation('list', True)
+
+ def test_show_interface_with_str_body(self):
+ self._test_interface_operation('show')
+
+ def test_show_interface_with_bytes_body(self):
+ self._test_interface_operation('show', True)
+
+ def test_delete_interface_with_str_body(self):
+ self._test_interface_operation('delete')
+
+ def test_delete_interface_with_bytes_body(self):
+ self._test_interface_operation('delete', True)
+
+ def test_create_interface_with_str_body(self):
+ self._test_interface_operation()
+
+ def test_create_interface_with_bytes_body(self):
+ self._test_interface_operation(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_servers_client.py b/tempest/tests/services/compute/test_servers_client.py
new file mode 100644
index 0000000..e347cf1
--- /dev/null
+++ b/tempest/tests/services/compute/test_servers_client.py
@@ -0,0 +1,212 @@
+# Copyright 2015 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.services.compute.json import servers_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestServersClient(base.BaseComputeServiceTest):
+
+ FAKE_SERVERS = {'servers': [{
+ "id": "616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "links": [
+ {
+ "href": "http://os.co/v2/616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "rel": "self"
+ },
+ {
+ "href": "http://os.co/616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "rel": "bookmark"
+ }
+ ],
+ "name": u"new\u1234-server-test"}]
+ }
+
+ FAKE_SERVER_GET = {'server': {
+ "accessIPv4": "",
+ "accessIPv6": "",
+ "addresses": {
+ "private": [
+ {
+ "addr": "192.168.0.3",
+ "version": 4
+ }
+ ]
+ },
+ "created": "2012-08-20T21:11:09Z",
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "href": "http://os.com/openstack/flavors/1",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "hostId": "65201c14a29663e06d0748e561207d998b343e1d164bfa0aafa9c45d",
+ "id": "893c7791-f1df-4c3d-8383-3caae9656c62",
+ "image": {
+ "id": "70a599e0-31e7-49b7-b260-868f441e862b",
+ "links": [
+ {
+ "href": "http://imgs/70a599e0-31e7-49b7-b260-868f441e862b",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "links": [
+ {
+ "href": "http://v2/srvs/893c7791-f1df-4c3d-8383-3caae9656c62",
+ "rel": "self"
+ },
+ {
+ "href": "http://srvs/893c7791-f1df-4c3d-8383-3caae9656c62",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {
+ u"My Server N\u1234me": u"Apa\u1234che1"
+ },
+ "name": u"new\u1234-server-test",
+ "progress": 0,
+ "status": "ACTIVE",
+ "tenant_id": "openstack",
+ "updated": "2012-08-20T21:11:09Z",
+ "user_id": "fake"}
+ }
+
+ FAKE_SERVER_POST = {"server": {
+ "id": "616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "adminPass": "fake-admin-pass",
+ "security_groups": [
+ 'fake-security-group-1',
+ 'fake-security-group-2'
+ ],
+ "links": [
+ {
+ "href": "http://os.co/v2/616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "rel": "self"
+ },
+ {
+ "href": "http://os.co/616fb98f-46ca-475e-917e-2563e5a8cd19",
+ "rel": "bookmark"
+ }
+ ],
+ "OS-DCF:diskConfig": "fake-disk-config"}
+ }
+
+ FAKE_ADDRESS = {"addresses": {
+ "private": [
+ {
+ "addr": "192.168.0.3",
+ "version": 4
+ }
+ ]}
+ }
+
+ server_id = FAKE_SERVER_GET['server']['id']
+ network_id = 'a6b0875b-6b5d-4a5a-81eb-0c3aa62e5fdb'
+
+ def setUp(self):
+ super(TestServersClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = servers_client.ServersClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def test_list_servers_with_str_body(self):
+ self._test_list_servers()
+
+ def test_list_servers_with_bytes_body(self):
+ self._test_list_servers(bytes_body=True)
+
+ def _test_list_servers(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_servers,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_SERVERS,
+ bytes_body)
+
+ def test_show_server_with_str_body(self):
+ self._test_show_server()
+
+ def test_show_server_with_bytes_body(self):
+ self._test_show_server(bytes_body=True)
+
+ def _test_show_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_server,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_SERVER_GET,
+ bytes_body,
+ server_id=self.server_id
+ )
+
+ def test_delete_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_server,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {},
+ status=204,
+ server_id=self.server_id
+ )
+
+ def test_create_server_with_str_body(self):
+ self._test_create_server()
+
+ def test_create_server_with_bytes_body(self):
+ self._test_create_server(True)
+
+ def _test_create_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ self.FAKE_SERVER_POST,
+ bytes_body,
+ status=202,
+ name='fake-name',
+ imageRef='fake-image-ref',
+ flavorRef='fake-flavor-ref'
+ )
+
+ def test_list_addresses_with_str_body(self):
+ self._test_list_addresses()
+
+ def test_list_addresses_with_bytes_body(self):
+ self._test_list_addresses(True)
+
+ def _test_list_addresses(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_addresses,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_ADDRESS,
+ bytes_body,
+ server_id=self.server_id
+ )
+
+ def test_list_addresses_by_network_with_str_body(self):
+ self._test_list_addresses_by_network()
+
+ def test_list_addresses_by_network_with_bytes_body(self):
+ self._test_list_addresses_by_network(True)
+
+ def _test_list_addresses_by_network(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_addresses_by_network,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_ADDRESS['addresses'],
+ bytes_body,
+ server_id=self.server_id,
+ network_id=self.network_id
+ )
diff --git a/tempest/tests/services/compute/test_snapshots_client.py b/tempest/tests/services/compute/test_snapshots_client.py
new file mode 100644
index 0000000..c24c6ae
--- /dev/null
+++ b/tempest/tests/services/compute/test_snapshots_client.py
@@ -0,0 +1,103 @@
+# 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 oslotest import mockpatch
+from tempest_lib import exceptions as lib_exc
+
+from tempest.services.compute.json import snapshots_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestSnapshotsClient(base.BaseComputeServiceTest):
+
+ FAKE_SNAPSHOT = {
+ "createdAt": "2015-10-02T16:27:54.724209",
+ "displayDescription": u"Another \u1234.",
+ "displayName": u"v\u1234-001",
+ "id": "100",
+ "size": 100,
+ "status": "available",
+ "volumeId": "12"
+ }
+
+ FAKE_SNAPSHOTS = {"snapshots": [FAKE_SNAPSHOT]}
+
+ def setUp(self):
+ super(TestSnapshotsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = snapshots_client.SnapshotsClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def _test_create_snapshot(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_snapshot,
+ 'tempest.common.service_client.ServiceClient.post',
+ {"snapshot": self.FAKE_SNAPSHOT},
+ to_utf=bytes_body, status=200,
+ volume_id=self.FAKE_SNAPSHOT["volumeId"])
+
+ def test_create_snapshot_with_str_body(self):
+ self._test_create_snapshot()
+
+ def test_create_shapshot_with_bytes_body(self):
+ self._test_create_snapshot(bytes_body=True)
+
+ def _test_show_snapshot(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_snapshot,
+ 'tempest.common.service_client.ServiceClient.get',
+ {"snapshot": self.FAKE_SNAPSHOT},
+ to_utf=bytes_body, snapshot_id=self.FAKE_SNAPSHOT["id"])
+
+ def test_show_snapshot_with_str_body(self):
+ self._test_show_snapshot()
+
+ def test_show_snapshot_with_bytes_body(self):
+ self._test_show_snapshot(bytes_body=True)
+
+ def _test_list_snapshots(self, bytes_body=False, **params):
+ self.check_service_client_function(
+ self.client.list_snapshots,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_SNAPSHOTS, to_utf=bytes_body, **params)
+
+ def test_list_snapshots_with_str_body(self):
+ self._test_list_snapshots()
+
+ def test_list_snapshots_with_byte_body(self):
+ self._test_list_snapshots(bytes_body=True)
+
+ def test_list_snapshots_with_params(self):
+ self._test_list_snapshots('fake')
+
+ def test_delete_snapshot(self):
+ self.check_service_client_function(
+ self.client.delete_snapshot,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {}, status=202, snapshot_id=self.FAKE_SNAPSHOT['id'])
+
+ def test_is_resource_deleted_true(self):
+ module = ('tempest.services.compute.json.snapshots_client.'
+ 'SnapshotsClient.show_snapshot')
+ self.useFixture(mockpatch.Patch(
+ module, side_effect=lib_exc.NotFound))
+ self.assertTrue(self.client.is_resource_deleted('fake-id'))
+
+ def test_is_resource_deleted_false(self):
+ module = ('tempest.services.compute.json.snapshots_client.'
+ 'SnapshotsClient.show_snapshot')
+ self.useFixture(mockpatch.Patch(
+ module, return_value={}))
+ self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/services/compute/test_volumes_extensions_client.py b/tempest/tests/services/compute/test_volumes_client.py
similarity index 87%
rename from tempest/tests/services/compute/test_volumes_extensions_client.py
rename to tempest/tests/services/compute/test_volumes_client.py
index 2fe8497..33d4bad 100644
--- a/tempest/tests/services/compute/test_volumes_extensions_client.py
+++ b/tempest/tests/services/compute/test_volumes_client.py
@@ -17,12 +17,12 @@
from oslotest import mockpatch
from tempest_lib import exceptions as lib_exc
-from tempest.services.compute.json import volumes_extensions_client
+from tempest.services.compute.json import volumes_client
from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
-class TestVolumesExtensionsClient(base.BaseComputeServiceTest):
+class TestVolumesClient(base.BaseComputeServiceTest):
FAKE_VOLUME = {
"id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
@@ -43,9 +43,9 @@
FAKE_VOLUMES = {"volumes": [FAKE_VOLUME]}
def setUp(self):
- super(TestVolumesExtensionsClient, self).setUp()
+ super(TestVolumesClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = volumes_extensions_client.VolumesExtensionsClient(
+ self.client = volumes_client.VolumesClient(
fake_auth, 'compute', 'regionOne')
def _test_list_volumes(self, bytes_body=False, **params):
@@ -100,15 +100,15 @@
{}, status=202, volume_id=self.FAKE_VOLUME['id'])
def test_is_resource_deleted_true(self):
- module = ('tempest.services.compute.json.volumes_extensions_client.'
- 'VolumesExtensionsClient.show_volume')
+ module = ('tempest.services.compute.json.volumes_client.'
+ 'VolumesClient.show_volume')
self.useFixture(mockpatch.Patch(
module, side_effect=lib_exc.NotFound))
self.assertTrue(self.client.is_resource_deleted('fake-id'))
def test_is_resource_deleted_false(self):
- module = ('tempest.services.compute.json.volumes_extensions_client.'
- 'VolumesExtensionsClient.show_volume')
+ module = ('tempest.services.compute.json.volumes_client.'
+ 'VolumesClient.show_volume')
self.useFixture(mockpatch.Patch(
module, return_value={}))
self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 8c371a7..1ced180 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -211,7 +211,7 @@
def resource_setup(cls):
super(BotoTestCase, cls).resource_setup()
cls.conclusion = decision_maker()
- # The trash contains cleanup functions and paramaters in tuples
+ # The trash contains cleanup functions and parameters in tuples
# (function, *args, **kwargs)
cls._resource_trash_bin = {}
cls._sequence = -1
diff --git a/tox.ini b/tox.ini
index 3250344..09c8626 100644
--- a/tox.ini
+++ b/tox.ini
@@ -24,7 +24,7 @@
bash tools/pretty_tox.sh '{posargs}'
[testenv:genconfig]
-commands = oslo-config-generator --config-file tools/config/config-generator.tempest.conf
+commands = oslo-config-generator --config-file etc/config-generator.tempest.conf
[testenv:cover]
setenv = OS_TEST_PATH=./tempest/tests