Merge "Move wait_for_qos_operations method to common.waiters"
diff --git a/README.rst b/README.rst
index 3c0463b..f1dac1c 100644
--- a/README.rst
+++ b/README.rst
@@ -92,18 +92,18 @@
be done using the :ref:`tempest_run` command. This can be done by either
running::
- $ tempest run
+ $ tempest run
from the Tempest workspace directory. Or you can use the ``--workspace``
argument to run in the workspace you created regarless of your current
working directory. For example::
- $ tempest run --workspace cloud-01
+ $ tempest run --workspace cloud-01
There is also the option to use testr directly, or any `testr`_ based test
runner, like `ostestr`_. For example, from the workspace dir run::
- $ ostestr --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))'
+ $ ostestr --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))'
will run the same set of tests as the default gate jobs.
@@ -161,9 +161,9 @@
of the configuration.
You can generate a new sample tempest.conf file, run the following
-command from the top level of the Tempest directory:
+command from the top level of the Tempest directory::
- tox -egenconfig
+ $ tox -egenconfig
The most important pieces that are needed are the user ids, openstack
endpoint, and basic flavors and images needed to run tests.
@@ -257,11 +257,11 @@
and run the tests or use tox to do the same. Tox also contains several existing
job configurations. For example::
- $ tox -efull
+ $ tox -efull
which will run the same set of tests as the OpenStack gate. (it's exactly how
the gate invokes Tempest) Or::
- $ tox -esmoke
+ $ tox -esmoke
to run the tests tagged as smoke.
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 6c55015..18269bf 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -61,10 +61,9 @@
Credential Provider Mechanisms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Tempest currently also has three different internal methods for providing
-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.
+Tempest currently has two different internal methods for providing authentication
+to tests: dynamic credentials and pre-provisioned credentials.
+Depending on which one is in use the configuration of Tempest is slightly different.
Dynamic Credentials
"""""""""""""""""""
@@ -96,7 +95,7 @@
accounts will be assigned a role on domain configured in
``default_credentials_domain_name``. This will make the accounts provisioned
usable in a cloud where domain scoped tokens are required by keystone for
-admin operations. Note that the the initial pre-provision admin accounts,
+admin operations. Note that the initial pre-provision admin accounts,
configured in tempest.conf, must have a role on the same domain as well, for
Dynamic Credentials to work.
@@ -152,7 +151,7 @@
``admin_domain_scope`` as ``default_credentials_domain_name`` are configured
properly in tempest.conf.
-Pre-Provisioned Credentials are also know as accounts.yaml or accounts file.
+Pre-Provisioned Credentials are also known as accounts.yaml or accounts file.
Compute
-------
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index d34023f..285ad5d 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -213,7 +213,7 @@
* **client_names**: Name of the classes that implement service clients in the
service clients module.
-Example usage of the the service clients in tests::
+Example usage of the service clients in tests::
# my_creds is instance of tempest.lib.auth.Credentials
# identity_uri is v2 or v3 depending on the configuration
diff --git a/releasenotes/notes/Tempest-library-interface-0eb680b810139a50.yaml b/releasenotes/notes/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml
similarity index 100%
rename from releasenotes/notes/Tempest-library-interface-0eb680b810139a50.yaml
rename to releasenotes/notes/10.0.0-Tempest-library-interface-0eb680b810139a50.yaml
diff --git a/releasenotes/notes/start-using-reno-ed9518126fd0e1a3.yaml b/releasenotes/notes/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml
similarity index 100%
rename from releasenotes/notes/start-using-reno-ed9518126fd0e1a3.yaml
rename to releasenotes/notes/10.0.0-start-using-reno-ed9518126fd0e1a3.yaml
diff --git a/releasenotes/notes/api-microversion-testing-support-2ceddd2255670932.yaml b/releasenotes/notes/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml
similarity index 100%
rename from releasenotes/notes/api-microversion-testing-support-2ceddd2255670932.yaml
rename to releasenotes/notes/11.0.0-api-microversion-testing-support-2ceddd2255670932.yaml
diff --git a/releasenotes/notes/compute-microversion-support-e0b23f960f894b9b.yaml b/releasenotes/notes/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml
similarity index 100%
rename from releasenotes/notes/compute-microversion-support-e0b23f960f894b9b.yaml
rename to releasenotes/notes/11.0.0-compute-microversion-support-e0b23f960f894b9b.yaml
diff --git a/releasenotes/notes/add-network-versions-client-d90e8334e1443f5c.yaml b/releasenotes/notes/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml
similarity index 100%
rename from releasenotes/notes/add-network-versions-client-d90e8334e1443f5c.yaml
rename to releasenotes/notes/12.1.0-add-network-versions-client-d90e8334e1443f5c.yaml
diff --git a/releasenotes/notes/add-scope-to-auth-b5a82493ea89f41e.yaml b/releasenotes/notes/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml
similarity index 100%
rename from releasenotes/notes/add-scope-to-auth-b5a82493ea89f41e.yaml
rename to releasenotes/notes/12.1.0-add-scope-to-auth-b5a82493ea89f41e.yaml
diff --git a/releasenotes/notes/add-tempest-run-3d0aaf69c2ca4115.yaml b/releasenotes/notes/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml
similarity index 100%
rename from releasenotes/notes/add-tempest-run-3d0aaf69c2ca4115.yaml
rename to releasenotes/notes/12.1.0-add-tempest-run-3d0aaf69c2ca4115.yaml
diff --git a/releasenotes/notes/add-tempest-workspaces-228a2ba4690b5589.yaml b/releasenotes/notes/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml
similarity index 100%
rename from releasenotes/notes/add-tempest-workspaces-228a2ba4690b5589.yaml
rename to releasenotes/notes/12.1.0-add-tempest-workspaces-228a2ba4690b5589.yaml
diff --git a/releasenotes/notes/add_subunit_describe_calls-5498a37e6cd66c4b.yaml b/releasenotes/notes/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
similarity index 100%
rename from releasenotes/notes/add_subunit_describe_calls-5498a37e6cd66c4b.yaml
rename to releasenotes/notes/12.1.0-add_subunit_describe_calls-5498a37e6cd66c4b.yaml
diff --git a/releasenotes/notes/bug-1486834-7ebca15836ae27a9.yaml b/releasenotes/notes/12.1.0-bug-1486834-7ebca15836ae27a9.yaml
similarity index 100%
rename from releasenotes/notes/bug-1486834-7ebca15836ae27a9.yaml
rename to releasenotes/notes/12.1.0-bug-1486834-7ebca15836ae27a9.yaml
diff --git a/releasenotes/notes/identity-clients-as-library-e663c6132fcac6c2.yaml b/releasenotes/notes/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
similarity index 100%
rename from releasenotes/notes/identity-clients-as-library-e663c6132fcac6c2.yaml
rename to releasenotes/notes/12.1.0-identity-clients-as-library-e663c6132fcac6c2.yaml
diff --git a/releasenotes/notes/image-clients-as-library-86d17caa26ce3961.yaml b/releasenotes/notes/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
similarity index 100%
rename from releasenotes/notes/image-clients-as-library-86d17caa26ce3961.yaml
rename to releasenotes/notes/12.1.0-image-clients-as-library-86d17caa26ce3961.yaml
diff --git a/releasenotes/notes/new-test-utils-module-adf34468c4d52719.yaml b/releasenotes/notes/12.1.0-new-test-utils-module-adf34468c4d52719.yaml
similarity index 100%
rename from releasenotes/notes/new-test-utils-module-adf34468c4d52719.yaml
rename to releasenotes/notes/12.1.0-new-test-utils-module-adf34468c4d52719.yaml
diff --git a/releasenotes/notes/remove-input-scenarios-functionality-01308e6d4307f580.yaml b/releasenotes/notes/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml
similarity index 100%
rename from releasenotes/notes/remove-input-scenarios-functionality-01308e6d4307f580.yaml
rename to releasenotes/notes/12.1.0-remove-input-scenarios-functionality-01308e6d4307f580.yaml
diff --git a/releasenotes/notes/remove-integrated-horizon-bb57551c1e5f5be3.yaml b/releasenotes/notes/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml
similarity index 100%
rename from releasenotes/notes/remove-integrated-horizon-bb57551c1e5f5be3.yaml
rename to releasenotes/notes/12.1.0-remove-integrated-horizon-bb57551c1e5f5be3.yaml
diff --git a/releasenotes/notes/remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml b/releasenotes/notes/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml
similarity index 100%
rename from releasenotes/notes/remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml
rename to releasenotes/notes/12.1.0-remove-legacy-credential-providers-3d653ac3ba1ada2b.yaml
diff --git a/releasenotes/notes/remove-trove-tests-666522e9113549f9.yaml b/releasenotes/notes/12.1.0-remove-trove-tests-666522e9113549f9.yaml
similarity index 100%
rename from releasenotes/notes/remove-trove-tests-666522e9113549f9.yaml
rename to releasenotes/notes/12.1.0-remove-trove-tests-666522e9113549f9.yaml
diff --git a/releasenotes/notes/routers-client-as-library-25a363379da351f6.yaml b/releasenotes/notes/12.1.0-routers-client-as-library-25a363379da351f6.yaml
similarity index 100%
rename from releasenotes/notes/routers-client-as-library-25a363379da351f6.yaml
rename to releasenotes/notes/12.1.0-routers-client-as-library-25a363379da351f6.yaml
diff --git a/releasenotes/notes/support-chunked-encoding-d71f53225f68edf3.yaml b/releasenotes/notes/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml
similarity index 100%
rename from releasenotes/notes/support-chunked-encoding-d71f53225f68edf3.yaml
rename to releasenotes/notes/12.1.0-support-chunked-encoding-d71f53225f68edf3.yaml
diff --git a/releasenotes/notes/tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml b/releasenotes/notes/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml
similarity index 100%
rename from releasenotes/notes/tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml
rename to releasenotes/notes/12.1.0-tempest-init-global-config-dir-location-changes-12260255871d3a2b.yaml
diff --git a/releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml b/releasenotes/notes/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
similarity index 100%
rename from releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
rename to releasenotes/notes/12.2.0-add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
diff --git a/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml b/releasenotes/notes/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
similarity index 100%
rename from releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml
rename to releasenotes/notes/12.2.0-add-new-identity-clients-3c3afd674a395bde.yaml
diff --git a/releasenotes/notes/clients_module-16f3025f515bf9ec.yaml b/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
similarity index 100%
rename from releasenotes/notes/clients_module-16f3025f515bf9ec.yaml
rename to releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
diff --git a/releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml b/releasenotes/notes/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml
similarity index 100%
rename from releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml
rename to releasenotes/notes/12.2.0-nova_cert_default-90eb7c1e3cde624a.yaml
diff --git a/releasenotes/notes/plugin-service-client-registration-00b19a2dd4935ba0.yaml b/releasenotes/notes/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml
similarity index 100%
rename from releasenotes/notes/plugin-service-client-registration-00b19a2dd4935ba0.yaml
rename to releasenotes/notes/12.2.0-plugin-service-client-registration-00b19a2dd4935ba0.yaml
diff --git a/releasenotes/notes/remove-javelin-276f62d04f7e4a1d.yaml b/releasenotes/notes/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml
similarity index 100%
rename from releasenotes/notes/remove-javelin-276f62d04f7e4a1d.yaml
rename to releasenotes/notes/12.2.0-remove-javelin-276f62d04f7e4a1d.yaml
diff --git a/releasenotes/notes/service_client_config-8a1d7b4de769c633.yaml b/releasenotes/notes/12.2.0-service_client_config-8a1d7b4de769c633.yaml
similarity index 100%
rename from releasenotes/notes/service_client_config-8a1d7b4de769c633.yaml
rename to releasenotes/notes/12.2.0-service_client_config-8a1d7b4de769c633.yaml
diff --git a/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml b/releasenotes/notes/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
similarity index 100%
rename from releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml
rename to releasenotes/notes/12.2.0-volume-clients-as-library-9a3444dd63c134b3.yaml
diff --git a/releasenotes/notes/12.3.0-volume-clients-as-library-660811011be29d1a.yaml b/releasenotes/notes/12.3.0-volume-clients-as-library-660811011be29d1a.yaml
new file mode 100644
index 0000000..9e9eff6
--- /dev/null
+++ b/releasenotes/notes/12.3.0-volume-clients-as-library-660811011be29d1a.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Define the v1 and v2 types_client clients for the volume service as
+ library interfaces, allowing other projects to use these modules as
+ stable libraries without maintenance changes.
diff --git a/releasenotes/notes/add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml b/releasenotes/notes/add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
index b8a8491..9e828f6 100644
--- a/releasenotes/notes/add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
+++ b/releasenotes/notes/add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
@@ -1,8 +1,15 @@
---
features:
- |
- Define identity service clients as libraries
+ Define identity service clients as libraries.
Add new service clients to the library interface so the other projects can use these modules as stable libraries without
any maintenance changes.
* identity_client(v2)
+ * groups_client(v3)
+ * trusts_client(v3)
+ * users_client(v3)
+ * identity_client(v3)
+ * roles_client(v3)
+ * inherited_roles_client(v3)
+ * credentials_client(v3)
diff --git a/releasenotes/notes/add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml b/releasenotes/notes/add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml
new file mode 100644
index 0000000..4886f16
--- /dev/null
+++ b/releasenotes/notes/add-volume-clients-as-a-library-d05b6bc35e66c6ef.yaml
@@ -0,0 +1,15 @@
+---
+features:
+ - |
+ Define volume service clients as libraries.
+ The following volume service clients are defined as library interface,
+ so the other projects can use these modules as stable libraries without
+ any maintenance changes.
+
+ * encryption_types_client (v1)
+ * encryption_types_client (v2)
+ * qos_clients (v1)
+ * qos_clients (v2)
+ * snapshots_client (v1)
+ * snapshots_client (v2)
+
diff --git a/releasenotes/notes/deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml b/releasenotes/notes/deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml
new file mode 100644
index 0000000..0884cfa
--- /dev/null
+++ b/releasenotes/notes/deprecate-get_ipv6_addr_by_EUI64-4673f07677289cf6.yaml
@@ -0,0 +1,4 @@
+---
+deprecations:
+ - Oslo.utils provides same method get_ipv6_addr_by_EUI64,
+ so deprecate it in Newton and remove it in Ocata.
diff --git a/releasenotes/notes/tempest-cleanup-nostandalone-39df2aafb2545d35.yaml b/releasenotes/notes/tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
new file mode 100644
index 0000000..20f310d
--- /dev/null
+++ b/releasenotes/notes/tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - the already depreacted tempest-cleanup standalone command has been
+ removed. The corresponding functionalities can be accessed through
+ the unified `tempest` command (`tempest cleanup`).
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 2c22408..0ec0e94 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -5,10 +5,10 @@
.. toctree::
:maxdepth: 1
+ unreleased
v12.0.0
v11.0.0
v10.0.0
- unreleased
Indices and tables
==================
diff --git a/requirements.txt b/requirements.txt
index a773d16..0a5268c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,20 +6,21 @@
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
testtools>=1.4.0 # MIT
paramiko>=2.0 # LGPLv2.1+
-netaddr!=0.7.16,>=0.7.12 # BSD
+netaddr!=0.7.16,>=0.7.13 # BSD
testrepository>=0.0.18 # Apache-2.0/BSD
oslo.concurrency>=3.8.0 # Apache-2.0
oslo.config>=3.14.0 # Apache-2.0
-oslo.i18n>=2.1.0 # Apache-2.0
-oslo.log>=1.14.0 # Apache-2.0
+oslo.log>=3.11.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.utils>=3.16.0 # Apache-2.0
six>=1.9.0 # MIT
fixtures>=3.0.0 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
PyYAML>=3.1.0 # MIT
+python-subunit>=0.0.18 # Apache-2.0/BSD
stevedore>=1.16.0 # Apache-2.0
PrettyTable<0.8,>=0.7 # BSD
os-testr>=0.7.0 # Apache-2.0
urllib3>=1.15.1 # MIT
debtcollector>=1.2.0 # Apache-2.0
+unittest2 # BSD
diff --git a/run_tempest.sh b/run_tempest.sh
index af01734..414146b 100755
--- a/run_tempest.sh
+++ b/run_tempest.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+echo "WARNING: This script is deprecated and will be removed in the near future. Please migrate to tempest run or another method of launching a test runner"
+
function usage {
echo "Usage: $0 [OPTION]..."
echo "Run Tempest test suite"
diff --git a/setup.cfg b/setup.cfg
index 50bf891..28e17ef 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -29,7 +29,6 @@
console_scripts =
verify-tempest-config = tempest.cmd.verify_tempest_config:main
run-tempest-stress = tempest.cmd.run_stress:main
- tempest-cleanup = tempest.cmd.cleanup:main
tempest-account-generator = tempest.cmd.account_generator:main
tempest = tempest.cmd.main:main
skip-tracker = tempest.lib.cmd.skip_tracker:main
diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py
index 4f48ad0..61359f1 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -16,7 +16,6 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
from tempest import test
LOG = log.getLogger(__name__)
@@ -30,24 +29,16 @@
super(AgentsAdminTestJSON, cls).setup_clients()
cls.client = cls.os_adm.agents_client
- def setUp(self):
- super(AgentsAdminTestJSON, self).setUp()
- params = self._param_helper(
+ @classmethod
+ def resource_setup(cls):
+ super(AgentsAdminTestJSON, cls).resource_setup()
+ cls.params_agent = cls._param_helper(
hypervisor='common', os='linux', architecture='x86_64',
version='7.0', url='xxx://xxxx/xxx/xxx',
md5hash='add6bb58e139be103324d04d82d8f545')
- body = self.client.create_agent(**params)['agent']
- self.agent_id = body['agent_id']
- def tearDown(self):
- try:
- test_utils.call_and_ignore_notfound_exc(
- self.client.delete_agent, self.agent_id)
- except Exception:
- LOG.exception('Exception raised deleting agent %s', self.agent_id)
- super(AgentsAdminTestJSON, self).tearDown()
-
- def _param_helper(self, **kwargs):
+ @staticmethod
+ def _param_helper(**kwargs):
rand_key = 'architecture'
if rand_key in kwargs:
# NOTE: The rand_name is for avoiding agent conflicts.
@@ -71,33 +62,42 @@
@test.idempotent_id('dc9ffd51-1c50-4f0e-a820-ae6d2a568a9e')
def test_update_agent(self):
- # Update an agent.
+ # Create and update an agent.
+ body = self.client.create_agent(**self.params_agent)['agent']
+ self.addCleanup(self.client.delete_agent, body['agent_id'])
+ agent_id = body['agent_id']
params = self._param_helper(
version='8.0', url='xxx://xxxx/xxx/xxx2',
md5hash='add6bb58e139be103324d04d82d8f547')
- body = self.client.update_agent(self.agent_id, **params)['agent']
+ body = self.client.update_agent(agent_id, **params)['agent']
for expected_item, value in params.items():
self.assertEqual(value, body[expected_item])
@test.idempotent_id('470e0b89-386f-407b-91fd-819737d0b335')
def test_delete_agent(self):
- # Delete an agent.
- self.client.delete_agent(self.agent_id)
+ # Create an agent and delete it.
+ body = self.client.create_agent(**self.params_agent)['agent']
+ self.client.delete_agent(body['agent_id'])
# Verify the list doesn't contain the deleted agent.
agents = self.client.list_agents()['agents']
- self.assertNotIn(self.agent_id, map(lambda x: x['agent_id'], agents))
+ self.assertNotIn(body['agent_id'], map(lambda x: x['agent_id'],
+ agents))
@test.idempotent_id('6a326c69-654b-438a-80a3-34bcc454e138')
def test_list_agents(self):
- # List all agents.
+ # Create an agent and list all agents.
+ body = self.client.create_agent(**self.params_agent)['agent']
+ self.addCleanup(self.client.delete_agent, body['agent_id'])
agents = self.client.list_agents()['agents']
self.assertTrue(len(agents) > 0, 'Cannot get any agents.(%s)' % agents)
- self.assertIn(self.agent_id, map(lambda x: x['agent_id'], agents))
+ self.assertIn(body['agent_id'], map(lambda x: x['agent_id'], agents))
@test.idempotent_id('eabadde4-3cd7-4ec4-a4b5-5a936d2d4408')
def test_list_agents_with_filter(self):
- # List the agent builds by the filter.
+ # Create agents and list the agent builds by the filter.
+ body = self.client.create_agent(**self.params_agent)['agent']
+ self.addCleanup(self.client.delete_agent, body['agent_id'])
params = self._param_helper(
hypervisor='xen', os='linux', architecture='x86',
version='7.0', url='xxx://xxxx/xxx/xxx1',
@@ -110,4 +110,5 @@
['agents'])
self.assertTrue(len(agents) > 0, 'Cannot get any agents.(%s)' % agents)
self.assertIn(agent_id_xen, map(lambda x: x['agent_id'], agents))
- self.assertNotIn(self.agent_id, map(lambda x: x['agent_id'], agents))
+ self.assertNotIn(body['agent_id'], map(lambda x: x['agent_id'],
+ agents))
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index fbcc1d1..667d30b 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -215,10 +215,8 @@
self.client.add_host(aggregate['id'], host=self.host)
self.addCleanup(self.client.remove_host, aggregate['id'],
host=self.host)
- server_name = data_utils.rand_name('test_server')
admin_servers_client = self.os_adm.servers_client
- server = self.create_test_server(name=server_name,
- availability_zone=az_name,
+ server = self.create_test_server(availability_zone=az_name,
wait_until='ACTIVE')
body = admin_servers_client.show_server(server['id'])['server']
self.assertEqual(self.host, body['OS-EXT-SRV-ATTR:host'])
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 95e7ef1..fde5622 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -161,6 +161,7 @@
verify_flavor_response_extension(flavor)
# Check if flavor is present in list
+ flag = False
flavors = self.user_client.list_flavors(detail=True)['flavors']
for flavor in flavors:
if flavor['name'] == flavor_name:
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 6113c04..62dbfe4 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -31,6 +31,8 @@
super(MigrationsAdminTest, cls).setup_clients()
cls.client = cls.os_adm.migrations_client
cls.flavors_admin_client = cls.os_adm.flavors_client
+ cls.admin_hosts_client = cls.os_adm.hosts_client
+ cls.admin_servers_client = cls.os_adm.servers_client
@test.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
def test_list_migrations(self):
@@ -103,3 +105,28 @@
server = self.servers_client.show_server(server['id'])['server']
self.assertEqual(flavor['id'], server['flavor']['id'])
+
+ @test.idempotent_id('4bf0be52-3b6f-4746-9a27-3143636fe30d')
+ @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+ 'Cold migration not available.')
+ def test_cold_migration(self):
+ if CONF.compute.min_compute_nodes < 2:
+ msg = "Less than 2 compute nodes, skipping multinode tests."
+ raise self.skipException(msg)
+
+ server = self.create_test_server(wait_until="ACTIVE")
+ src_host = self.admin_servers_client.show_server(
+ server['id'])['server']['OS-EXT-SRV-ATTR:host']
+
+ self.admin_servers_client.migrate_server(server['id'])
+
+ waiters.wait_for_server_status(self.servers_client,
+ server['id'], 'VERIFY_RESIZE')
+
+ self.servers_client.confirm_resize_server(server['id'])
+ waiters.wait_for_server_status(self.servers_client,
+ server['id'], 'ACTIVE')
+ dst_host = self.admin_servers_client.show_server(
+ server['id'])['server']['OS-EXT-SRV-ATTR:host']
+
+ self.assertNotEqual(src_host, dst_host)
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index b1f0755..7d97ce2 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -117,8 +117,6 @@
password=password,
project=project,
email=email)
- if 'user' in user:
- user = user['user']
user_id = user['id']
self.addCleanup(self.identity_utils.delete_user, user_id)
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index aabb40c..c9ffcca 100755
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -102,14 +102,18 @@
params = {'tenant_id': tenant_id}
body = self.client.list_servers(detail=True, **params)
servers = body['servers']
- self.assertEqual([], servers)
+ servers_name = map(lambda x: x['name'], servers)
+ self.assertNotIn(self.s1_name, servers_name)
+ self.assertNotIn(self.s2_name, servers_name)
- # List the admin tenant which has no servers
+ # List the admin tenant shouldn't get servers created by other tenants
admin_tenant_id = self.client.tenant_id
params = {'all_tenants': '', 'tenant_id': admin_tenant_id}
body = self.client.list_servers(detail=True, **params)
servers = body['servers']
- self.assertEqual([], servers)
+ servers_name = map(lambda x: x['name'], servers)
+ self.assertNotIn(self.s1_name, servers_name)
+ self.assertNotIn(self.s2_name, servers_name)
@test.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
def test_list_servers_filter_by_exist_host(self):
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index db6e682..23b16e7 100755
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -69,7 +69,7 @@
self.tenant_id)['quota_set']
ram = int(quota_set['ram'])
if ram == -1:
- raise self.skipException("default ram quota set is -1,"
+ raise self.skipException("ram quota set is -1,"
" cannot test overlimit")
ram += 1
vcpus = 8
@@ -98,7 +98,7 @@
self.tenant_id)['quota_set']
vcpus = int(quota_set['cores'])
if vcpus == -1:
- raise self.skipException("default cores quota set is -1,"
+ raise self.skipException("cores quota set is -1,"
" cannot test overlimit")
vcpus += 1
disk = 10
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 5e75493..27afff3 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -219,6 +219,8 @@
:param validatable: Whether the server will be pingable or sshable.
:param volume_backed: Whether the instance is volume backed or not.
"""
+ if 'name' not in kwargs:
+ kwargs['name'] = data_utils.rand_name(cls.__name__ + "-server")
tenant_network = cls.get_tenant_network()
body, servers = compute.create_test_server(
cls.os,
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index 6f80730..999233d 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -71,7 +71,7 @@
body = body['image'] if 'image' in body else body
cls.image_id = body['id']
cls.images.append(cls.image_id)
- image_file = six.StringIO(('*' * 1024))
+ image_file = six.BytesIO((b'*' * 1024))
if CONF.image_feature_enabled.api_v1:
cls.glance_client.update_image(cls.image_id, data=image_file)
else:
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index c0caa52..f340658 100755
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -78,7 +78,7 @@
# Wait 1 second between creation and upload to ensure a delta
# between created_at and updated_at.
time.sleep(1)
- image_file = six.StringIO(('*' * 1024))
+ image_file = six.BytesIO((b'*' * 1024))
if CONF.image_feature_enabled.api_v1:
cls.glance_client.update_image(image_id, data=image_file)
else:
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index 853ef31..4f53663 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules_negative.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -23,7 +23,8 @@
def not_existing_id():
- if CONF.service_available.neutron:
+ if (CONF.service_available.neutron and
+ test.is_extension_enabled('security-group', 'network')):
return data_utils.rand_uuid()
else:
return data_utils.rand_int_id(start=999)
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index f6353c8..755336f 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -94,8 +94,7 @@
# Create server and add the security group created
# above to the server we just created
- server_name = data_utils.rand_name('server')
- server = self.create_test_server(name=server_name)
+ server = self.create_test_server()
server_id = server['id']
waiters.wait_for_server_status(self.servers_client, server_id,
'ACTIVE')
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 7c12bf9..b936b23 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -47,22 +47,20 @@
@classmethod
def setup_clients(cls):
super(AttachInterfacesTestJSON, cls).setup_clients()
- cls.client = cls.os.interfaces_client
cls.networks_client = cls.os.networks_client
cls.subnets_client = cls.os.subnets_client
cls.ports_client = cls.os.ports_client
- cls.servers_client = cls.servers_client
def wait_for_interface_status(self, server, port_id, status):
"""Waits for an interface to reach a given status."""
- body = (self.client.show_interface(server, port_id)
+ body = (self.interfaces_client.show_interface(server, port_id)
['interfaceAttachment'])
interface_status = body['port_state']
start = int(time.time())
while(interface_status != status):
time.sleep(self.build_interval)
- body = (self.client.show_interface(server, port_id)
+ body = (self.interfaces_client.show_interface(server, port_id)
['interfaceAttachment'])
interface_status = body['port_state']
@@ -119,7 +117,7 @@
def _create_server_get_interfaces(self):
server = self.create_test_server(wait_until='ACTIVE')
- ifs = (self.client.list_interfaces(server['id'])
+ ifs = (self.interfaces_client.list_interfaces(server['id'])
['interfaceAttachments'])
body = self.wait_for_interface_status(
server['id'], ifs[0]['port_id'], 'ACTIVE')
@@ -127,7 +125,7 @@
return server, ifs
def _test_create_interface(self, server):
- iface = (self.client.create_interface(server['id'])
+ iface = (self.interfaces_client.create_interface(server['id'])
['interfaceAttachment'])
iface = self.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
@@ -136,7 +134,7 @@
def _test_create_interface_by_network_id(self, server, ifs):
network_id = ifs[0]['net_id']
- iface = self.client.create_interface(
+ iface = self.interfaces_client.create_interface(
server['id'], net_id=network_id)['interfaceAttachment']
iface = self.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
@@ -148,7 +146,7 @@
port = self.ports_client.create_port(network_id=network_id)
port_id = port['port']['id']
self.addCleanup(self.ports_client.delete_port, port_id)
- iface = self.client.create_interface(
+ iface = self.interfaces_client.create_interface(
server['id'], port_id=port_id)['interfaceAttachment']
iface = self.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
@@ -165,7 +163,7 @@
1)
fixed_ips = [{'ip_address': ip_list[0]}]
- iface = self.client.create_interface(
+ iface = self.interfaces_client.create_interface(
server['id'], net_id=network_id,
fixed_ips=fixed_ips)['interfaceAttachment']
self.addCleanup(self.ports_client.delete_port, iface['port_id'])
@@ -176,7 +174,7 @@
def _test_show_interface(self, server, ifs):
iface = ifs[0]
- _iface = self.client.show_interface(
+ _iface = self.interfaces_client.show_interface(
server['id'], iface['port_id'])['interfaceAttachment']
self._check_interface(iface, port_id=_iface['port_id'],
network_id=_iface['net_id'],
@@ -186,14 +184,14 @@
def _test_delete_interface(self, server, ifs):
# NOTE(danms): delete not the first or last, but one in the middle
iface = ifs[1]
- self.client.delete_interface(server['id'], iface['port_id'])
- _ifs = (self.client.list_interfaces(server['id'])
+ self.interfaces_client.delete_interface(server['id'], iface['port_id'])
+ _ifs = (self.interfaces_client.list_interfaces(server['id'])
['interfaceAttachments'])
start = int(time.time())
while len(ifs) == len(_ifs):
time.sleep(self.build_interval)
- _ifs = (self.client.list_interfaces(server['id'])
+ _ifs = (self.interfaces_client.list_interfaces(server['id'])
['interfaceAttachments'])
timed_out = int(time.time()) - start >= self.build_timeout
if len(ifs) == len(_ifs) and timed_out:
@@ -239,7 +237,7 @@
iface = self._test_create_interface_by_fixed_ips(server, ifs)
ifs.append(iface)
- _ifs = (self.client.list_interfaces(server['id'])
+ _ifs = (self.interfaces_client.list_interfaces(server['id'])
['interfaceAttachments'])
self._compare_iface_list(ifs, _ifs)
@@ -302,11 +300,11 @@
for server in servers:
# attach the port to the server
- iface = self.client.create_interface(
+ iface = self.interfaces_client.create_interface(
server['id'], port_id=port_id)['interfaceAttachment']
self._check_interface(iface, port_id=port_id)
# detach the port from the server; this is a cast in the compute
# API so we have to poll the port until the device_id is unset.
- self.client.delete_interface(server['id'], port_id)
+ self.interfaces_client.delete_interface(server['id'], port_id)
self.wait_for_port_detach(port_id)
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 26cbb090..611d5a2 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -119,8 +119,8 @@
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
@test.idempotent_id('ca78e20e-fddb-4ce6-b7f7-bcbf8605e66e')
- def test_list_servers_filter_by_server_status(self):
- # Filter the list of servers by server status
+ def test_list_servers_filter_by_active_status(self):
+ # Filter the list of servers by server active status
params = {'status': 'active'}
body = self.client.list_servers(**params)
servers = body['servers']
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 357c907..fcd5a24 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six import moves
-
from tempest.api.compute import base
from tempest.common import waiters
from tempest.lib import exceptions as lib_exc
@@ -38,7 +36,7 @@
# tearDownClass method of the super-class.
cls.existing_fixtures = []
cls.deleted_fixtures = []
- for x in moves.xrange(2):
+ for x in range(2):
srv = cls.create_test_server(wait_until='ACTIVE')
cls.existing_fixtures.append(srv)
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index eb1beb1..4dd26af 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -21,16 +21,10 @@
class MultipleCreateTestJSON(base.BaseV2ComputeTest):
_name = 'multiple-create-test'
- def _generate_name(self):
- return data_utils.rand_name(self._name)
-
- def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
- # NOTE: This is the right way to create_multiple servers and manage to
- # get the created servers into the servers list to be cleaned up after
- # all.
- kwargs['name'] = name if name else self._generate_name()
- if wait_until:
- kwargs['wait_until'] = wait_until
+ def _create_multiple_servers(self, **kwargs):
+ # This is the right way to create_multiple servers and manage to get
+ # the created servers into the servers list to be cleaned up after all.
+ kwargs['name'] = kwargs.get('name', data_utils.rand_name(self._name))
body = self.create_test_server(**kwargs)
return body
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index e5b4f46..c4dbe23 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -22,13 +22,10 @@
class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
_name = 'multiple-create-test'
- def _generate_name(self):
- return data_utils.rand_name(self._name)
-
- def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
+ def _create_multiple_servers(self, **kwargs):
# This is the right way to create_multiple servers and manage to get
# the created servers into the servers list to be cleaned up after all.
- kwargs['name'] = kwargs.get('name', self._generate_name())
+ kwargs['name'] = kwargs.get('name', data_utils.rand_name(self._name))
body = self.create_test_server(**kwargs)
return body
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index baa4f9a..e5ad7b4 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import base64
+from oslo_serialization import base64
from tempest.api.compute import base
from tempest.common.utils.linux import remote_client
@@ -55,7 +55,7 @@
file_contents = 'This is a test file.'
file_path = '/test.txt'
personality = [{'path': file_path,
- 'contents': base64.b64encode(file_contents)}]
+ 'contents': base64.encode_as_text(file_contents)}]
password = data_utils.rand_password()
created_server = self.create_test_server(personality=personality,
adminPass=password,
@@ -79,7 +79,7 @@
server_id = server['id']
file_contents = 'Test server rebuild.'
personality = [{'path': 'rebuild.txt',
- 'contents': base64.b64encode(file_contents)}]
+ 'contents': base64.encode_as_text(file_contents)}]
rebuilt_server = self.client.rebuild_server(server_id,
self.image_ref_alt,
personality=personality)
@@ -100,7 +100,8 @@
for i in range(0, int(max_file_limit) + 1):
path = 'etc/test' + str(i) + '.txt'
personality.append({'path': path,
- 'contents': base64.b64encode(file_contents)})
+ 'contents': base64.encode_as_text(
+ file_contents)})
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised when out of quota
self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
@@ -120,7 +121,7 @@
path = '/etc/test' + str(i) + '.txt'
person.append({
'path': path,
- 'contents': base64.b64encode(file_contents),
+ 'contents': base64.encode_as_text(file_contents),
})
password = data_utils.rand_password()
created_server = self.create_test_server(personality=person,
@@ -136,6 +137,6 @@
server=server,
servers_client=self.client)
for i in person:
- self.assertEqual(base64.b64decode(i['contents']),
+ self.assertEqual(base64.decode_as_text(i['contents']),
linux_client.exec_command(
'sudo cat %s' % i['path']))
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 2304cb7..89be3f3 100755
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -302,7 +302,7 @@
# Pass a server ID that exceeds length limit to delete server
self.assertRaises(lib_exc.NotFound, self.client.delete_server,
- sys.maxint + 1)
+ sys.maxsize + 1)
@test.attr(type=['negative'])
@test.idempotent_id('c5fa6041-80cd-483b-aa6d-4e45f19d093c')
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 80d2c78..c48169f 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -17,6 +17,7 @@
from tempest.api.compute import base
from tempest.common import compute
+from tempest.common.utils import data_utils
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
from tempest import config
@@ -57,13 +58,6 @@
waiters.wait_for_volume_status(self.volumes_client,
volume_id, 'available')
- def _delete_volume(self):
- # Delete the created Volumes
- if self.volume:
- self.volumes_client.delete_volume(self.volume['id'])
- self.volumes_client.wait_for_resource_deletion(self.volume['id'])
- self.volume = None
-
def _create_server(self):
# Start a server and wait for it to become ready
server = self.create_test_server(
@@ -78,28 +72,30 @@
def _create_and_attach_volume(self, server):
# Create a volume and wait for it to become ready
- self.volume = self.volumes_client.create_volume(
- size=CONF.volume.volume_size, display_name='test')['volume']
- self.addCleanup(self._delete_volume)
+ vol_name = data_utils.rand_name(self.__class__.__name__ + '-volume')
+ volume = self.volumes_client.create_volume(
+ size=CONF.volume.volume_size, display_name=vol_name)['volume']
+ self.addCleanup(self.delete_volume, volume['id'])
waiters.wait_for_volume_status(self.volumes_client,
- self.volume['id'], 'available')
+ volume['id'], 'available')
# Attach the volume to the server
self.attachment = self.servers_client.attach_volume(
server['id'],
- volumeId=self.volume['id'],
+ volumeId=volume['id'],
device='/dev/%s' % self.device)['volumeAttachment']
waiters.wait_for_volume_status(self.volumes_client,
- self.volume['id'], 'in-use')
+ volume['id'], 'in-use')
- self.addCleanup(self._detach, server['id'], self.volume['id'])
+ self.addCleanup(self._detach, server['id'], volume['id'])
+ return volume
@test.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
def test_attach_detach_volume(self):
# Stop and Start a server with an attached volume, ensuring that
# the volume remains attached.
server = self._create_server()
- self._create_and_attach_volume(server)
+ volume = self._create_and_attach_volume(server)
self.servers_client.stop_server(server['id'])
waiters.wait_for_server_status(self.servers_client, server['id'],
@@ -119,9 +115,10 @@
servers_client=self.servers_client)
partitions = linux_client.get_partitions()
- self.assertIn(self.device, partitions)
+ device_name_to_match = ' ' + self.device + '\n'
+ self.assertIn(device_name_to_match, partitions)
- self._detach(server['id'], self.volume['id'])
+ self._detach(server['id'], volume['id'])
self.attachment = None
self.servers_client.stop_server(server['id'])
waiters.wait_for_server_status(self.servers_client, server['id'],
@@ -141,13 +138,13 @@
servers_client=self.servers_client)
partitions = linux_client.get_partitions()
- self.assertNotIn(self.device, partitions)
+ self.assertNotIn(device_name_to_match, partitions)
@test.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
def test_list_get_volume_attachments(self):
# Create Server, Volume and attach that Volume to Server
server = self._create_server()
- self._create_and_attach_volume(server)
+ volume = self._create_and_attach_volume(server)
# List Volume attachment of the server
body = self.servers_client.list_volume_attachments(
@@ -160,7 +157,7 @@
server['id'],
self.attachment['id'])['volumeAttachment']
self.assertEqual(server['id'], body['serverId'])
- self.assertEqual(self.volume['id'], body['volumeId'])
+ self.assertEqual(volume['id'], body['volumeId'])
self.assertEqual(self.attachment['id'], body['id'])
@@ -168,7 +165,7 @@
"""Testing volume with shelved instance.
This test checks the attaching and detaching volumes from
- a shelved or shelved ofload instance.
+ a shelved or shelved offload instance.
"""
min_microversion = '2.20'
@@ -253,10 +250,10 @@
server = self._create_server()
num_vol = self._count_volumes(server)
self._shelve_server(server)
- self._create_and_attach_volume(server)
+ volume = self._create_and_attach_volume(server)
# Detach the volume
- self._detach(server['id'], self.volume['id'])
+ self._detach(server['id'], volume['id'])
self.attachment = None
# Unshelve the instance and check that we have the expected number of
diff --git a/tempest/api/identity/admin/v2/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
index 380920f..d284aac 100644
--- a/tempest/api/identity/admin/v2/test_roles.py
+++ b/tempest/api/identity/admin/v2/test_roles.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six import moves
-
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.lib.common.utils import test_utils
@@ -27,7 +25,7 @@
def resource_setup(cls):
super(RolesTestJSON, cls).resource_setup()
cls.roles = list()
- for _ in moves.xrange(5):
+ for _ in range(5):
role_name = data_utils.rand_name(name='role')
role = cls.roles_client.create_role(name=role_name)['role']
cls.roles.append(role)
diff --git a/tempest/api/identity/admin/v2/test_services.py b/tempest/api/identity/admin/v2/test_services.py
index 94291f8..3ed51f0 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six import moves
-
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
@@ -84,7 +82,7 @@
def test_list_services(self):
# Create, List, Verify and Delete Services
services = []
- for _ in moves.xrange(3):
+ for _ in range(3):
name = data_utils.rand_name('service')
s_type = data_utils.rand_name('type')
description = data_utils.rand_name('description')
diff --git a/tempest/api/identity/admin/v2/test_tenants.py b/tempest/api/identity/admin/v2/test_tenants.py
index 4faf184..f4fad53 100644
--- a/tempest/api/identity/admin/v2/test_tenants.py
+++ b/tempest/api/identity/admin/v2/test_tenants.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six import moves
-
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.lib.common.utils import test_utils
@@ -27,7 +25,7 @@
def test_tenant_list_delete(self):
# Create several tenants and delete them
tenants = []
- for _ in moves.xrange(3):
+ for _ in range(3):
tenant_name = data_utils.rand_name(name='tenant-new')
tenant = self.tenants_client.create_tenant(
name=tenant_name)['tenant']
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index 8e63498..4a4b51a 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -234,4 +234,4 @@
# Validate the updated password through getting a token.
body = self.token_client.auth(user['name'], new_pass,
tenant['name'])
- self.assertTrue('id' in body['token'])
+ self.assertIn('id', body['token'])
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index 12b236f..a0d8748 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -12,6 +12,7 @@
# 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.identity import base
from tempest.common.utils import data_utils
@@ -70,6 +71,7 @@
update_body = self.creds_client.update_credential(
cred['id'], blob=blob, project_id=self.projects[1],
type='ec2')['credential']
+ update_body['blob'] = json.loads(update_body['blob'])
self.assertEqual(cred['id'], update_body['id'])
self.assertEqual(self.projects[1], update_body['project_id'])
self.assertEqual(self.user_body['id'], update_body['user_id'])
@@ -77,6 +79,7 @@
self.assertEqual(update_body['blob']['secret'], new_keys[1])
get_body = self.creds_client.show_credential(cred['id'])['credential']
+ get_body['blob'] = json.loads(get_body['blob'])
for value1 in self.creds_list[0]:
self.assertEqual(update_body[value1],
get_body[value1])
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 48e5f02..3cbcc1f 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -91,7 +91,8 @@
# list users in group
group_users = self.groups_client.list_group_users(group['id'])['users']
- self.assertEqual(sorted(users), sorted(group_users))
+ self.assertEqual(sorted(users, key=lambda k: k['name']),
+ sorted(group_users, key=lambda k: k['name']))
# check and delete user in group
for user in users:
self.groups_client.check_group_user_existence(
@@ -118,7 +119,8 @@
self.groups_client.add_group_user(group['id'], user['id'])
# list groups which user belongs to
user_groups = self.users_client.list_user_groups(user['id'])['groups']
- self.assertEqual(sorted(groups), sorted(user_groups))
+ self.assertEqual(sorted(groups, key=lambda k: k['name']),
+ sorted(user_groups, key=lambda k: k['name']))
self.assertEqual(2, len(user_groups))
@test.idempotent_id('cc9a57a5-a9ed-4f2d-a29f-4f979a06ec71')
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index 76771bb..955b6fb 100644
--- a/tempest/api/identity/admin/v3/test_inherits.py
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -68,10 +68,10 @@
name=data_utils.rand_name('Role'))['role']
self.addCleanup(self.roles_client.delete_role, src_role['id'])
# Assign role on domains user
- self.roles_client.assign_inherited_role_on_domains_user(
+ self.inherited_roles_client.create_inherited_role_on_domains_user(
self.domain['id'], self.user['id'], src_role['id'])
# list role on domains user
- roles = self.roles_client.\
+ roles = self.inherited_roles_client.\
list_inherited_project_role_for_user_on_domain(
self.domain['id'], self.user['id'])['roles']
@@ -80,10 +80,11 @@
src_role['id'])
# Check role on domains user
- self.roles_client.check_user_inherited_project_role_on_domain(
- self.domain['id'], self.user['id'], src_role['id'])
+ (self.inherited_roles_client.
+ check_user_inherited_project_role_on_domain(
+ self.domain['id'], self.user['id'], src_role['id']))
# Revoke role from domains user.
- self.roles_client.revoke_inherited_role_from_user_on_domain(
+ self.inherited_roles_client.delete_inherited_role_from_user_on_domain(
self.domain['id'], self.user['id'], src_role['id'])
@test.idempotent_id('c7a8dda2-be50-4fb4-9a9c-e830771078b1')
@@ -93,10 +94,10 @@
name=data_utils.rand_name('Role'))['role']
self.addCleanup(self.roles_client.delete_role, src_role['id'])
# Assign role on domains group
- self.roles_client.assign_inherited_role_on_domains_group(
+ self.inherited_roles_client.create_inherited_role_on_domains_group(
self.domain['id'], self.group['id'], src_role['id'])
# List role on domains group
- roles = self.roles_client.\
+ roles = self.inherited_roles_client.\
list_inherited_project_role_for_group_on_domain(
self.domain['id'], self.group['id'])['roles']
@@ -105,10 +106,11 @@
src_role['id'])
# Check role on domains group
- self.roles_client.check_group_inherited_project_role_on_domain(
- self.domain['id'], self.group['id'], src_role['id'])
+ (self.inherited_roles_client.
+ check_group_inherited_project_role_on_domain(
+ self.domain['id'], self.group['id'], src_role['id']))
# Revoke role from domains group
- self.roles_client.revoke_inherited_role_from_group_on_domain(
+ self.inherited_roles_client.delete_inherited_role_from_group_on_domain(
self.domain['id'], self.group['id'], src_role['id'])
@test.idempotent_id('18b70e45-7687-4b72-8277-b8f1a47d7591')
@@ -118,13 +120,14 @@
name=data_utils.rand_name('Role'))['role']
self.addCleanup(self.roles_client.delete_role, src_role['id'])
# Assign role on projects user
- self.roles_client.assign_inherited_role_on_projects_user(
+ self.inherited_roles_client.create_inherited_role_on_projects_user(
self.project['id'], self.user['id'], src_role['id'])
# Check role on projects user
- self.roles_client.check_user_has_flag_on_inherited_to_project(
- self.project['id'], self.user['id'], src_role['id'])
+ (self.inherited_roles_client.
+ check_user_has_flag_on_inherited_to_project(
+ self.project['id'], self.user['id'], src_role['id']))
# Revoke role from projects user
- self.roles_client.revoke_inherited_role_from_user_on_project(
+ self.inherited_roles_client.delete_inherited_role_from_user_on_project(
self.project['id'], self.user['id'], src_role['id'])
@test.idempotent_id('26021436-d5a4-4256-943c-ded01e0d4b45')
@@ -134,11 +137,98 @@
name=data_utils.rand_name('Role'))['role']
self.addCleanup(self.roles_client.delete_role, src_role['id'])
# Assign role on projects group
- self.roles_client.assign_inherited_role_on_projects_group(
+ self.inherited_roles_client.create_inherited_role_on_projects_group(
self.project['id'], self.group['id'], src_role['id'])
# Check role on projects group
- self.roles_client.check_group_has_flag_on_inherited_to_project(
- self.project['id'], self.group['id'], src_role['id'])
+ (self.inherited_roles_client.
+ check_group_has_flag_on_inherited_to_project(
+ self.project['id'], self.group['id'], src_role['id']))
# Revoke role from projects group
- self.roles_client.revoke_inherited_role_from_group_on_project(
- self.project['id'], self.group['id'], src_role['id'])
+ (self.inherited_roles_client.
+ delete_inherited_role_from_group_on_project(
+ self.project['id'], self.group['id'], src_role['id']))
+
+ @test.idempotent_id('3acf666e-5354-42ac-8e17-8b68893bcd36')
+ def test_inherit_assign_list_revoke_user_roles_on_domain(self):
+ # Create role
+ src_role = self.roles_client.create_role(
+ name=data_utils.rand_name('Role'))['role']
+ self.addCleanup(self.roles_client.delete_role, src_role['id'])
+
+ # Create a project hierarchy
+ leaf_project_name = data_utils.rand_name('project')
+ leaf_project = self.projects_client.create_project(
+ leaf_project_name, domain_id=self.domain['id'],
+ parent_id=self.project['id'])['project']
+ self.addCleanup(
+ self.projects_client.delete_project, leaf_project['id'])
+
+ # Assign role on domain
+ self.inherited_roles_client.create_inherited_role_on_domains_user(
+ self.domain['id'], self.user['id'], src_role['id'])
+
+ # List "effective" role assignments from user on the parent project
+ assignments = (
+ self.role_assignments.list_user_project_effective_assignments(
+ self.project['id'], self.user['id']))['role_assignments']
+ self.assertNotEmpty(assignments)
+
+ # List "effective" role assignments from user on the leaf project
+ assignments = (
+ self.role_assignments.list_user_project_effective_assignments(
+ leaf_project['id'], self.user['id']))['role_assignments']
+ self.assertNotEmpty(assignments)
+
+ # Revoke role from domain
+ self.inherited_roles_client.delete_inherited_role_from_user_on_domain(
+ self.domain['id'], self.user['id'], src_role['id'])
+
+ # List "effective" role assignments from user on the parent project
+ # should return an empty list
+ assignments = (
+ self.role_assignments.list_user_project_effective_assignments(
+ self.project['id'], self.user['id']))['role_assignments']
+ self.assertEmpty(assignments)
+
+ # List "effective" role assignments from user on the leaf project
+ # should return an empty list
+ assignments = (
+ self.role_assignments.list_user_project_effective_assignments(
+ leaf_project['id'], self.user['id']))['role_assignments']
+ self.assertEmpty(assignments)
+
+ @test.idempotent_id('9f02ccd9-9b57-46b4-8f77-dd5a736f3a06')
+ def test_inherit_assign_list_revoke_user_roles_on_project_tree(self):
+ # Create role
+ src_role = self.roles_client.create_role(
+ name=data_utils.rand_name('Role'))['role']
+ self.addCleanup(self.roles_client.delete_role, src_role['id'])
+
+ # Create a project hierarchy
+ leaf_project_name = data_utils.rand_name('project')
+ leaf_project = self.projects_client.create_project(
+ leaf_project_name, domain_id=self.domain['id'],
+ parent_id=self.project['id'])['project']
+ self.addCleanup(
+ self.projects_client.delete_project, leaf_project['id'])
+
+ # Assign role on parent project
+ self.inherited_roles_client.create_inherited_role_on_projects_user(
+ self.project['id'], self.user['id'], src_role['id'])
+
+ # List "effective" role assignments from user on the leaf project
+ assignments = (
+ self.role_assignments.list_user_project_effective_assignments(
+ leaf_project['id'], self.user['id']))['role_assignments']
+ self.assertNotEmpty(assignments)
+
+ # Revoke role from parent project
+ self.inherited_roles_client.delete_inherited_role_from_user_on_project(
+ self.project['id'], self.user['id'], src_role['id'])
+
+ # List "effective" role assignments from user on the leaf project
+ # should return an empty list
+ assignments = (
+ self.role_assignments.list_user_project_effective_assignments(
+ leaf_project['id'], self.user['id']))['role_assignments']
+ self.assertEmpty(assignments)
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 6c926fb..14bf4f8 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -23,6 +23,12 @@
class BaseIdentityTest(tempest.test.BaseTestCase):
@classmethod
+ def setup_credentials(cls):
+ # Create no network resources for these test.
+ cls.set_network_resources()
+ super(BaseIdentityTest, cls).setup_credentials()
+
+ @classmethod
def disable_user(cls, user_name):
user = cls.get_user_by_name(user_name)
cls.users_client.update_user_enabled(user['id'], enabled=False)
@@ -167,6 +173,7 @@
cls.users_client = cls.os_adm.users_v3_client
cls.trusts_client = cls.os_adm.trusts_client
cls.roles_client = cls.os_adm.roles_v3_client
+ cls.inherited_roles_client = cls.os_adm.inherited_roles_client
cls.token = cls.os_adm.token_v3_client
cls.endpoints_client = cls.os_adm.endpoints_v3_client
cls.regions_client = cls.os_adm.regions_client
@@ -175,6 +182,7 @@
cls.creds_client = cls.os_adm.credentials_client
cls.groups_client = cls.os_adm.groups_client
cls.projects_client = cls.os_adm.projects_client
+ cls.role_assignments = cls.os_admin.role_assignments_client
if CONF.identity.admin_domain_scope:
# NOTE(andreaf) When keystone policy requires it, the identity
# admin clients for these tests shall use 'domain' scoped tokens.
diff --git a/tempest/api/image/admin/v2/test_images.py b/tempest/api/image/admin/v2/test_images.py
index 80da7a1..c719b7a 100644
--- a/tempest/api/image/admin/v2/test_images.py
+++ b/tempest/api/image/admin/v2/test_images.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six import moves
+import six
import testtools
from tempest.api.image import base
@@ -42,7 +42,7 @@
self.addCleanup(self.client.delete_image, image_id)
# upload an image file
content = data_utils.random_bytes()
- image_file = moves.cStringIO(content)
+ image_file = six.BytesIO(content)
self.client.store_image_file(image_id, image_file)
# deactivate image
self.admin_client.deactivate_image(image_id)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index e7a46b0..f74f97b 100755
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six import moves
+import six
from tempest.common import image as common_image
from tempest.common.utils import data_utils
@@ -118,7 +118,7 @@
cls.alt_tenant_id = cls.alt_image_member_client.tenant_id
def _create_image(self):
- image_file = moves.cStringIO(data_utils.random_bytes())
+ image_file = six.BytesIO(data_utils.random_bytes())
image = self.create_image(container_format='bare',
disk_format='raw',
is_public=False,
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 694408d..712b34b 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from six import moves
+import six
from tempest.api.image import base
from tempest.common import image as common_image
@@ -63,7 +63,7 @@
self.assertEqual(val, body.get('properties')[key])
# Now try uploading an image file
- image_file = moves.cStringIO(data_utils.random_bytes())
+ image_file = six.BytesIO(data_utils.random_bytes())
body = self.client.update_image(image_id, data=image_file)['image']
self.assertIn('size', body)
self.assertEqual(1024, body.get('size'))
@@ -199,7 +199,7 @@
Note that the size of the new image is a random number between
1024 and 4096
"""
- image_file = moves.cStringIO(data_utils.random_bytes(size))
+ image_file = six.BytesIO(data_utils.random_bytes(size))
name = 'New Standard Image %s' % name
image = cls.create_image(name=name,
container_format=container_format,
@@ -294,7 +294,7 @@
disk_format, size):
"""Create a new standard image and return newly-registered image-id"""
- image_file = moves.cStringIO(data_utils.random_bytes(size))
+ image_file = six.BytesIO(data_utils.random_bytes(size))
name = 'New Standard Image %s' % name
image = cls.create_image(name=name,
container_format=container_format,
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index 9e67c25..d8f103a 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -40,13 +40,6 @@
'x-image-meta-disk_format': 'wrong'})
@test.attr(type=['negative'])
- @test.idempotent_id('bb016f15-0820-4f27-a92d-09b2f67d2488')
- def test_delete_image_with_invalid_image_id(self):
- # An image should not be deleted with invalid image id
- self.assertRaises(lib_exc.NotFound, self.client.delete_image,
- '!@$%^&*()')
-
- @test.attr(type=['negative'])
@test.idempotent_id('ec652588-7e3c-4b67-a2f2-0fa96f57c8fc')
def test_delete_non_existent_image(self):
# Return an error while trying to delete a non-existent image
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 42a4352..f363d34 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -16,7 +16,7 @@
import random
-from six import moves
+import six
from oslo_log import log as logging
from tempest.api.image import base
@@ -60,7 +60,7 @@
# Now try uploading an image file
file_content = data_utils.random_bytes()
- image_file = moves.cStringIO(file_content)
+ image_file = six.BytesIO(file_content)
self.client.store_image_file(image_id, image_file)
# Now try to get image details
@@ -117,7 +117,7 @@
image_id = body['id']
# Now try uploading an image file
- image_file = moves.cStringIO(data_utils.random_bytes())
+ image_file = six.BytesIO(data_utils.random_bytes())
self.client.store_image_file(image_id, image_file)
# Update Image
@@ -160,7 +160,7 @@
1024 and 4096
"""
size = random.randint(1024, 4096)
- image_file = moves.cStringIO(data_utils.random_bytes(size))
+ image_file = six.BytesIO(data_utils.random_bytes(size))
name = data_utils.rand_name('image')
body = cls.create_image(name=name,
container_format=container_format,
@@ -250,6 +250,16 @@
self.assertEqual(len(images_list), params['limit'],
"Failed to get images by limit")
+ @test.idempotent_id('e9a44b91-31c8-4b40-a332-e0a39ffb4dbb')
+ def test_list_image_param_owner(self):
+ # Test to get images by owner
+ image_id = self.created_images[0]
+ # Get image metadata
+ image = self.client.show_image(image_id)
+
+ params = {"owner": image['owner']}
+ self._list_by_param_value_and_assert(params)
+
@test.idempotent_id('622b925c-479f-4736-860d-adeaf13bc371')
def test_get_image_schema(self):
# Test to get image schema
diff --git a/tempest/api/image/v2/test_images_metadefs_resource_types.py b/tempest/api/image/v2/test_images_metadefs_resource_types.py
index a5143a1..3dd432b 100644
--- a/tempest/api/image/v2/test_images_metadefs_resource_types.py
+++ b/tempest/api/image/v2/test_images_metadefs_resource_types.py
@@ -18,7 +18,7 @@
class MetadataResourceTypesTest(base.BaseV2ImageTest):
- """Test the Metadata definition ressource types basic functionality"""
+ """Test the Metadata definition resource types basic functionality"""
@test.idempotent_id('6f358a4e-5ef0-11e6-a795-080027d0d606')
def test_basic_meta_def_resource_type_association(self):
@@ -34,7 +34,7 @@
# NOTE(raiesmh08): Here intentionally I have not added addcleanup
# method for resource type dissociation because its a metadata add and
# being cleaned as soon as namespace is cleaned at test case level.
- # When namespace cleans, resource type associaion will automatically
+ # When namespace cleans, resource type association will automatically
# clean without any error or dependency.
# List resource type associations and validate creation
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 2ff31e0..3a264ff 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -87,5 +87,5 @@
@test.idempotent_id('2390f766-836d-40ef-9aeb-e810d78207fb')
def test_quotas(self):
- new_quotas = {'network': 0, 'security_group': 0}
+ new_quotas = {'network': 0, 'port': 0}
self._check_quotas(new_quotas)
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 77008ab..c1462db 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -30,7 +30,7 @@
class NetworksTestDHCPv6(base.BaseNetworkTest):
_ip_version = 6
- """ Test DHCPv6 specific features using SLAAC, stateless and
+ """Test DHCPv6 specific features using SLAAC, stateless and
stateful settings for subnets. Also it shall check dual-stack
functionality (IPv4 + IPv6 together).
The tests include:
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index caf7f14..e5972a9 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -16,6 +16,7 @@
import socket
import netaddr
+import testtools
from tempest.api.network import base
from tempest.api.network import base_security_groups as sec_base
@@ -308,11 +309,17 @@
self.assertIn(security_group, port_show['security_groups'])
@test.idempotent_id('58091b66-4ff4-4cc1-a549-05d60c7acd1a')
+ @testtools.skipUnless(
+ test.is_extension_enabled('security-group', 'network'),
+ 'security-group extension not enabled.')
def test_update_port_with_security_group_and_extra_attributes(self):
self._update_port_with_security_groups(
[data_utils.rand_name('secgroup')])
@test.idempotent_id('edf6766d-3d40-4621-bc6e-2521a44c257d')
+ @testtools.skipUnless(
+ test.is_extension_enabled('security-group', 'network'),
+ 'security-group extension not enabled.')
def test_update_port_with_two_security_groups_and_extra_attributes(self):
self._update_port_with_security_groups(
[data_utils.rand_name('secgroup'),
@@ -337,6 +344,9 @@
@test.attr(type='smoke')
@test.idempotent_id('4179dcb9-1382-4ced-84fe-1b91c54f5735')
+ @testtools.skipUnless(
+ test.is_extension_enabled('security-group', 'network'),
+ 'security-group extension not enabled.')
def test_create_port_with_no_securitygroups(self):
network = self.create_network()
self.addCleanup(self.networks_client.delete_network, network['id'])
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 85026af..fd973c6 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -58,6 +58,16 @@
cls.container_client.auth_provider.clear_auth()
cls.account_client.auth_provider.clear_auth()
+ # make sure that discoverability is enabled and that the sections
+ # have not been disallowed by Swift
+ cls.policies = None
+
+ if CONF.object_storage_feature_enabled.discoverability:
+ _, body = cls.account_client.list_extensions()
+
+ if 'swift' in body and 'policies' in body['swift']:
+ cls.policies = body['swift']['policies']
+
cls.containers = []
@classmethod
@@ -117,5 +127,5 @@
"""Check the existence and the format of response headers"""
self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
- target, method))
+ target, method, self.policies))
self.assertThat(resp, custom_matchers.AreAllWellFormatted())
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 9e9f08b..33e5852 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -15,7 +15,6 @@
import random
-from six import moves
import testtools
from tempest.api.object_storage import base
@@ -42,7 +41,7 @@
@classmethod
def resource_setup(cls):
super(AccountTest, cls).resource_setup()
- for i in moves.xrange(ord('a'), ord('f') + 1):
+ for i in range(ord('a'), ord('f') + 1):
name = data_utils.rand_name(name='%s-' % chr(i))
cls.container_client.create_container(name)
cls.containers.append(name)
@@ -80,7 +79,7 @@
# headers is checked without custom matcher.
#
# As the expected response is 204 No Content, Content-Length presence
- # is not checked here intensionally. According to RFC 7230 a server
+ # is not checked here intentionally. According to RFC 7230 a server
# MUST NOT send the header in such responses. Thus, clients should not
# depend on this header. However, the standard does not require them
# to validate the server's behavior. We leverage that to not refuse
@@ -140,7 +139,8 @@
@test.idempotent_id('5cfa4ab2-4373-48dd-a41f-a532b12b08b2')
def test_list_containers_with_limit(self):
# list containers one of them, half of them then all of them
- for limit in (1, self.containers_count / 2, self.containers_count):
+ for limit in (1, self.containers_count // 2,
+ self.containers_count):
params = {'limit': limit}
resp, container_list = \
self.account_client.list_account_containers(params=params)
@@ -161,12 +161,13 @@
self.assertEqual(len(container_list), 0)
- params = {'marker': self.containers[self.containers_count / 2]}
+ params = {'marker': self.containers[self.containers_count // 2]}
resp, container_list = \
self.account_client.list_account_containers(params=params)
self.assertHeaders(resp, 'Account', 'GET')
- self.assertEqual(len(container_list), self.containers_count / 2 - 1)
+ self.assertEqual(len(container_list),
+ self.containers_count // 2 - 1)
@test.idempotent_id('5ca164e4-7bde-43fa-bafb-913b53b9e786')
def test_list_containers_with_end_marker(self):
@@ -180,11 +181,11 @@
self.assertHeaders(resp, 'Account', 'GET')
self.assertEqual(len(container_list), 0)
- params = {'end_marker': self.containers[self.containers_count / 2]}
+ params = {'end_marker': self.containers[self.containers_count // 2]}
resp, container_list = \
self.account_client.list_account_containers(params=params)
self.assertHeaders(resp, 'Account', 'GET')
- self.assertEqual(len(container_list), self.containers_count / 2)
+ self.assertEqual(len(container_list), self.containers_count // 2)
@test.idempotent_id('ac8502c2-d4e4-4f68-85a6-40befea2ef5e')
def test_list_containers_with_marker_and_end_marker(self):
@@ -215,12 +216,12 @@
# list containers combining limit and end_marker param
limit = random.randint(1, self.containers_count)
params = {'limit': limit,
- 'end_marker': self.containers[self.containers_count / 2]}
+ 'end_marker': self.containers[self.containers_count // 2]}
resp, container_list = self.account_client.list_account_containers(
params=params)
self.assertHeaders(resp, 'Account', 'GET')
self.assertEqual(len(container_list),
- min(limit, self.containers_count / 2))
+ min(limit, self.containers_count // 2))
@test.idempotent_id('8cf98d9c-e3a0-4e44-971b-c87656fdddbd')
def test_list_containers_with_limit_and_marker_and_end_marker(self):
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 8522269..dbe8b4a 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -63,7 +63,8 @@
# create container with metadata value
container_name = data_utils.rand_name(name='TestContainer')
- metadata = {'test-container-meta': 'Meta1'}
+ # metadata name using underscores should be converted to hyphens
+ metadata = {'test_container_meta': 'Meta1'}
resp, _ = self.container_client.create_container(
container_name,
metadata=metadata)
@@ -74,7 +75,7 @@
container_name)
self.assertIn('x-container-meta-test-container-meta', resp)
self.assertEqual(resp['x-container-meta-test-container-meta'],
- metadata['test-container-meta'])
+ metadata['test_container_meta'])
@test.idempotent_id('24d16451-1c0c-4e4f-b59c-9840a3aba40e')
def test_create_container_with_remove_metadata_key(self):
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index a707ebb..8736f9a 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -47,9 +47,9 @@
object_name = data_utils.rand_name(name='LObject')
data = data_utils.arbitrary_string()
segments = 10
- data_segments = [data + str(i) for i in six.moves.xrange(segments)]
+ data_segments = [data + str(i) for i in range(segments)]
# uploading segments
- for i in six.moves.xrange(segments):
+ for i in range(segments):
resp, _ = self.object_client.create_object_segments(
self.container_name, object_name, i, data_segments[i])
@@ -901,9 +901,9 @@
object_name = data_utils.rand_name(name='LObject')
data = data_utils.arbitrary_string()
segments = 10
- data_segments = [data + str(i) for i in six.moves.xrange(segments)]
+ data_segments = [data + str(i) for i in range(segments)]
# uploading segments
- for i in six.moves.xrange(segments):
+ for i in range(segments):
resp, _ = self.object_client.create_object_segments(
self.container_name, object_name, i, data_segments[i])
# creating a manifest file
@@ -954,10 +954,7 @@
# When the file is not downloaded from Swift server, response does
# not contain 'X-Timestamp' header. This is the special case, therefore
# the existence of response headers is checked without custom matcher.
- self.assertIn('content-type', resp)
- self.assertIn('x-trans-id', resp)
self.assertIn('date', resp)
- self.assertIn('accept-ranges', resp)
# Check only the format of common headers with custom matcher
self.assertThat(resp, custom_matchers.AreAllWellFormatted())
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index 0400e76..8d12e75 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -72,10 +72,10 @@
for outputs in stack['outputs']:
output_map[outputs['output_key']] = outputs['output_value']
# Test that first key generated public and private keys
- self.assertTrue('KeyPair_PublicKey' in output_map)
- self.assertTrue("Generated" in output_map['KeyPair_PublicKey'])
- self.assertTrue('KeyPair_PrivateKey' in output_map)
- self.assertTrue('-----BEGIN' in output_map['KeyPair_PrivateKey'])
+ self.assertIn('KeyPair_PublicKey', output_map)
+ self.assertIn("Generated", output_map['KeyPair_PublicKey'])
+ self.assertIn('KeyPair_PrivateKey', output_map)
+ self.assertIn('-----BEGIN', output_map['KeyPair_PrivateKey'])
# Test that second key generated public key, and private key is not
# in the output due to save_private_key = false
self.assertTrue('KeyPairDontSavePrivate_PublicKey' in output_map)
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index f7013d8..73f1f8f 100755
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -13,9 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import base64
-import six
-
+from oslo_serialization import base64
from oslo_serialization import jsonutils as json
from tempest.api.volume import base
@@ -46,13 +44,11 @@
self.admin_backups_client.wait_for_resource_deletion(backup_id)
def _decode_url(self, backup_url):
- return json.loads(base64.decodestring(backup_url))
+ return json.loads(base64.decode_as_text(backup_url))
def _encode_backup(self, backup):
retval = json.dumps(backup)
- if six.PY3:
- retval = retval.encode('utf-8')
- return base64.encodestring(retval)
+ return base64.encode_as_text(retval)
def _modify_backup_url(self, backup_url, changes):
backup = self._decode_url(backup_url)
@@ -72,8 +68,8 @@
volume_id=self.volume['id'], name=backup_name)['backup'])
self.addCleanup(self._delete_backup, backup['id'])
self.assertEqual(backup_name, backup['name'])
- self.admin_backups_client.wait_for_backup_status(backup['id'],
- 'available')
+ waiters.wait_for_backup_status(self.admin_backups_client,
+ backup['id'], 'available')
# Export Backup
export_backup = (self.admin_backups_client.export_backup(backup['id'])
@@ -105,8 +101,8 @@
self.addCleanup(self._delete_backup, new_id)
self.assertIn("id", import_backup)
self.assertEqual(new_id, import_backup['id'])
- self.admin_backups_client.wait_for_backup_status(import_backup['id'],
- 'available')
+ waiters.wait_for_backup_status(self.admin_backups_client,
+ import_backup['id'], 'available')
# Verify Import Backup
backups = self.admin_backups_client.list_backups(
@@ -125,8 +121,8 @@
# Verify if restored volume is there in volume list
volumes = self.admin_volume_client.list_volumes()['volumes']
self.assertIn(restore['volume_id'], [v['id'] for v in volumes])
- self.admin_backups_client.wait_for_backup_status(import_backup['id'],
- 'available')
+ waiters.wait_for_backup_status(self.admin_backups_client,
+ import_backup['id'], 'available')
@test.idempotent_id('47a35425-a891-4e13-961c-c45deea21e94')
def test_volume_backup_reset_status(self):
@@ -138,13 +134,13 @@
self.addCleanup(self.admin_backups_client.delete_backup,
backup['id'])
self.assertEqual(backup_name, backup['name'])
- self.admin_backups_client.wait_for_backup_status(backup['id'],
- 'available')
+ waiters.wait_for_backup_status(self.admin_backups_client,
+ backup['id'], 'available')
# Reset backup status to error
self.admin_backups_client.reset_backup_status(backup_id=backup['id'],
status="error")
- self.admin_backups_client.wait_for_backup_status(backup['id'],
- 'error')
+ waiters.wait_for_backup_status(self.admin_backups_client,
+ backup['id'], 'error')
class VolumesBackupsAdminV1Test(VolumesBackupsAdminV2Test):
diff --git a/tempest/api/volume/v3/admin/__init__.py b/tempest/api/volume/admin/v2/__init__.py
similarity index 100%
rename from tempest/api/volume/v3/admin/__init__.py
rename to tempest/api/volume/admin/v2/__init__.py
diff --git a/tempest/api/volume/admin/test_volume_pools.py b/tempest/api/volume/admin/v2/test_volume_pools.py
similarity index 100%
rename from tempest/api/volume/admin/test_volume_pools.py
rename to tempest/api/volume/admin/v2/test_volume_pools.py
diff --git a/tempest/api/volume/admin/test_volume_type_access.py b/tempest/api/volume/admin/v2/test_volume_type_access.py
similarity index 100%
rename from tempest/api/volume/admin/test_volume_type_access.py
rename to tempest/api/volume/admin/v2/test_volume_type_access.py
diff --git a/tempest/api/volume/admin/test_volumes_list.py b/tempest/api/volume/admin/v2/test_volumes_list.py
similarity index 100%
rename from tempest/api/volume/admin/test_volumes_list.py
rename to tempest/api/volume/admin/v2/test_volumes_list.py
diff --git a/tempest/api/volume/v3/admin/__init__.py b/tempest/api/volume/admin/v3/__init__.py
similarity index 100%
copy from tempest/api/volume/v3/admin/__init__.py
copy to tempest/api/volume/admin/v3/__init__.py
diff --git a/tempest/api/volume/v3/admin/test_user_messages.py b/tempest/api/volume/admin/v3/test_user_messages.py
similarity index 100%
rename from tempest/api/volume/v3/admin/test_user_messages.py
rename to tempest/api/volume/admin/v3/test_user_messages.py
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 786538b..b49a126 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -172,14 +172,19 @@
except Exception:
pass
- @classmethod
- def create_server(cls, name, **kwargs):
- tenant_network = cls.get_tenant_network()
+ def create_server(self, name, **kwargs):
+ tenant_network = self.get_tenant_network()
body, _ = compute.create_test_server(
- cls.os,
+ self.os,
tenant_network=tenant_network,
name=name,
**kwargs)
+
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ waiters.wait_for_server_termination,
+ self.servers_client, body['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.servers_client.delete_server, body['id'])
return body
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index e529538..ee1744d 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -26,11 +26,10 @@
super(VolumesV2MetadataTest, cls).resource_setup()
# Create a volume
cls.volume = cls.create_volume()
- cls.volume_id = cls.volume['id']
def tearDown(self):
# Update the metadata to {}
- self.volumes_client.update_volume_metadata(self.volume_id, {})
+ self.volumes_client.update_volume_metadata(self.volume['id'], {})
super(VolumesV2MetadataTest, self).tearDown()
@test.idempotent_id('6f5b125b-f664-44bf-910f-751591fe5769')
@@ -41,17 +40,17 @@
"key3": "value3",
"key4": "<value&special_chars>"}
- body = self.volumes_client.create_volume_metadata(self.volume_id,
+ body = self.volumes_client.create_volume_metadata(self.volume['id'],
metadata)['metadata']
# Get the metadata of the volume
body = self.volumes_client.show_volume_metadata(
- self.volume_id)['metadata']
+ self.volume['id'])['metadata']
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
# Delete one item metadata of the volume
self.volumes_client.delete_volume_metadata_item(
- self.volume_id, "key1")
+ self.volume['id'], "key1")
body = self.volumes_client.show_volume_metadata(
- self.volume_id)['metadata']
+ self.volume['id'])['metadata']
self.assertNotIn("key1", body)
del metadata["key1"]
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
@@ -68,17 +67,17 @@
# Create metadata for the volume
body = self.volumes_client.create_volume_metadata(
- self.volume_id, metadata)['metadata']
+ self.volume['id'], metadata)['metadata']
# Get the metadata of the volume
body = self.volumes_client.show_volume_metadata(
- self.volume_id)['metadata']
+ self.volume['id'])['metadata']
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
# Update metadata
body = self.volumes_client.update_volume_metadata(
- self.volume_id, update)['metadata']
+ self.volume['id'], update)['metadata']
# Get the metadata of the volume
body = self.volumes_client.show_volume_metadata(
- self.volume_id)['metadata']
+ self.volume['id'])['metadata']
self.assertEqual(update, body)
@test.idempotent_id('862261c5-8df4-475a-8c21-946e50e36a20')
@@ -93,14 +92,14 @@
"key3": "value3_update"}
# Create metadata for the volume
body = self.volumes_client.create_volume_metadata(
- self.volume_id, metadata)['metadata']
+ self.volume['id'], metadata)['metadata']
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
# Update metadata item
body = self.volumes_client.update_volume_metadata_item(
- self.volume_id, "key3", update_item)['meta']
+ self.volume['id'], "key3", update_item)['meta']
# Get the metadata of the volume
body = self.volumes_client.show_volume_metadata(
- self.volume_id)['metadata']
+ self.volume['id'])['metadata']
self.assertThat(body.items(), matchers.ContainsAll(expect.items()))
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 7783c18..b80a4a4 100755
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -45,34 +45,25 @@
@classmethod
def resource_setup(cls):
super(VolumesV2ActionsTest, cls).resource_setup()
- # Create a test shared instance
- srv_name = data_utils.rand_name(cls.__name__ + '-Instance')
- cls.server = cls.create_server(
- name=srv_name,
- wait_until='ACTIVE')
# Create a test shared volume for attach/detach tests
cls.volume = cls.create_volume()
waiters.wait_for_volume_status(cls.client,
cls.volume['id'], 'available')
- @classmethod
- def resource_cleanup(cls):
- # Delete the test instance
- cls.servers_client.delete_server(cls.server['id'])
- waiters.wait_for_server_termination(cls.servers_client,
- cls.server['id'])
-
- super(VolumesV2ActionsTest, cls).resource_cleanup()
-
@test.idempotent_id('fff42874-7db5-4487-a8e1-ddda5fb5288d')
@test.stresstest(class_setup_per='process')
@test.attr(type='smoke')
@test.services('compute')
def test_attach_detach_volume_to_instance(self):
+ # Create a server
+ srv_name = data_utils.rand_name(self.__class__.__name__ + '-Instance')
+ server = self.create_server(
+ name=srv_name,
+ wait_until='ACTIVE')
# Volume is attached and detached successfully from an instance
self.client.attach_volume(self.volume['id'],
- instance_uuid=self.server['id'],
+ instance_uuid=server['id'],
mountpoint='/dev/%s' %
CONF.compute.volume_device_name)
waiters.wait_for_volume_status(self.client,
@@ -99,9 +90,14 @@
@test.stresstest(class_setup_per='process')
@test.services('compute')
def test_get_volume_attachment(self):
+ # Create a server
+ srv_name = data_utils.rand_name(self.__class__.__name__ + '-Instance')
+ server = self.create_server(
+ name=srv_name,
+ wait_until='ACTIVE')
# Verify that a volume's attachment information is retrieved
self.client.attach_volume(self.volume['id'],
- instance_uuid=self.server['id'],
+ instance_uuid=server['id'],
mountpoint='/dev/%s' %
CONF.compute.volume_device_name)
waiters.wait_for_volume_status(self.client,
@@ -119,7 +115,7 @@
self.assertEqual('/dev/%s' %
CONF.compute.volume_device_name,
attachment['device'])
- self.assertEqual(self.server['id'], attachment['server_id'])
+ self.assertEqual(server['id'], attachment['server_id'])
self.assertEqual(self.volume['id'], attachment['id'])
self.assertEqual(self.volume['id'], attachment['volume_id'])
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 50a1360..867e520 100755
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -30,10 +30,6 @@
if not CONF.volume_feature_enabled.backup:
raise cls.skipException("Cinder backup feature disabled")
- @classmethod
- def resource_setup(cls):
- super(VolumesBackupsV2Test, cls).resource_setup()
-
@test.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
def test_volume_backup_create_get_detailed_list_restore_delete(self):
# Create backup
@@ -50,8 +46,8 @@
self.assertEqual(backup_name, backup['name'])
waiters.wait_for_volume_status(self.volumes_client,
volume['id'], 'available')
- self.backups_client.wait_for_backup_status(backup['id'],
- 'available')
+ waiters.wait_for_backup_status(self.backups_client,
+ backup['id'], 'available')
# Get a given backup
backup = self.backups_client.show_backup(backup['id'])['backup']
@@ -71,8 +67,8 @@
self.addCleanup(self.volumes_client.delete_volume,
restore['volume_id'])
self.assertEqual(backup['id'], restore['backup_id'])
- self.backups_client.wait_for_backup_status(backup['id'],
- 'available')
+ waiters.wait_for_backup_status(self.backups_client,
+ backup['id'], 'available')
waiters.wait_for_volume_status(self.volumes_client,
restore['volume_id'], 'available')
@@ -91,7 +87,6 @@
server_name = data_utils.rand_name(
self.__class__.__name__ + '-instance')
server = self.create_server(name=server_name, wait_until='ACTIVE')
- self.addCleanup(self.servers_client.delete_server, server['id'])
# Attach volume to instance
self.servers_client.attach_volume(server['id'],
volumeId=volume['id'])
@@ -108,8 +103,8 @@
volume_id=volume['id'],
name=backup_name, force=True)['backup']
self.addCleanup(self.backups_client.delete_backup, backup['id'])
- self.backups_client.wait_for_backup_status(backup['id'],
- 'available')
+ waiters.wait_for_backup_status(self.backups_client,
+ backup['id'], 'available')
self.assertEqual(backup_name, backup['name'])
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 16c8571..e8ead5b 100755
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -15,7 +15,6 @@
from tempest.api.volume import base
from tempest.common.utils import data_utils
-from tempest.common import waiters
from tempest.lib import exceptions as lib_exc
from tempest import test
@@ -181,9 +180,6 @@
server = self.create_server(
name=srv_name,
wait_until='ACTIVE')
- self.addCleanup(waiters.wait_for_server_termination,
- self.servers_client, server['id'])
- self.addCleanup(self.servers_client.delete_server, server['id'])
self.assertRaises(lib_exc.NotFound,
self.client.attach_volume,
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 20c647a..6be569c 100755
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -14,7 +14,6 @@
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
-from tempest.lib import decorators
from tempest import test
CONF = config.CONF
@@ -32,12 +31,8 @@
def resource_setup(cls):
super(VolumesV2SnapshotTestJSON, cls).resource_setup()
cls.volume_origin = cls.create_volume()
-
cls.name_field = cls.special_fields['name_field']
cls.descrip_field = cls.special_fields['descrip_field']
- # Create 2 snapshots
- for _ in xrange(2):
- cls.create_snapshot(cls.volume_origin['id'])
def _detach(self, volume_id):
"""Detach volume."""
@@ -45,31 +40,6 @@
waiters.wait_for_volume_status(self.volumes_client,
volume_id, 'available')
- def _list_by_param_values_and_assert(self, with_detail=False, **params):
- """list or list_details with given params and validates result."""
-
- if with_detail:
- fetched_snap_list = self.snapshots_client.list_snapshots(
- detail=True, **params)['snapshots']
- else:
- fetched_snap_list = self.snapshots_client.list_snapshots(
- **params)['snapshots']
-
- # Validating params of fetched snapshots
- for snap in fetched_snap_list:
- for key in params:
- msg = "Failed to list snapshots %s by %s" % \
- ('details' if with_detail else '', key)
- self.assertEqual(params[key], snap[key], msg)
-
- def _list_snapshots_by_param_limit(self, limit, expected_elements):
- """list snapshots by limit param"""
- # Get snapshots list using limit parameter
- fetched_snap_list = self.snapshots_client.list_snapshots(
- limit=limit)['snapshots']
- # Validating filtered snapshots length equals to expected_elements
- self.assertEqual(expected_elements, len(fetched_snap_list))
-
@test.idempotent_id('b467b54c-07a4-446d-a1cf-651dedcc3ff1')
@test.services('compute')
def test_snapshot_create_with_volume_in_use(self):
@@ -80,7 +50,6 @@
server = self.create_server(
name=server_name,
wait_until='ACTIVE')
- self.addCleanup(self.servers_client.delete_server, server['id'])
self.servers_client.attach_volume(
server['id'], volumeId=self.volume_origin['id'],
device='/dev/%s' % CONF.compute.volume_device_name)
@@ -136,48 +105,6 @@
# Delete the snapshot
self.cleanup_snapshot(snapshot)
- @test.idempotent_id('59f41f43-aebf-48a9-ab5d-d76340fab32b')
- def test_snapshots_list_with_params(self):
- """list snapshots with params."""
- # Create a snapshot
- display_name = data_utils.rand_name(self.__class__.__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]}
- self._list_by_param_values_and_assert(**params)
-
- # Verify list snapshots by status filter
- params = {'status': 'available'}
- self._list_by_param_values_and_assert(**params)
-
- # Verify list snapshots by status and display name filter
- params = {'status': 'available',
- self.name_field: snapshot[self.name_field]}
- self._list_by_param_values_and_assert(**params)
-
- @test.idempotent_id('220a1022-1fcd-4a74-a7bd-6b859156cda2')
- def test_snapshots_list_details_with_params(self):
- """list snapshot details with params."""
- # Create a snapshot
- display_name = data_utils.rand_name(self.__class__.__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]}
- self._list_by_param_values_and_assert(with_detail=True, **params)
- # Verify list snapshot details by status filter
- params = {'status': 'available'}
- self._list_by_param_values_and_assert(with_detail=True, **params)
- # Verify list snapshot details by status and display name filter
- params = {'status': 'available',
- self.name_field: snapshot[self.name_field]}
- self._list_by_param_values_and_assert(with_detail=True, **params)
-
@test.idempotent_id('677863d1-3142-456d-b6ac-9924f667a7f4')
def test_volume_from_snapshot(self):
# Creates a volume a snapshot passing a size different from the source
@@ -194,25 +121,6 @@
self.assertEqual(volume['snapshot_id'], src_snap['id'])
self.assertEqual(int(volume['size']), src_size + 1)
- @test.idempotent_id('db4d8e0a-7a2e-41cc-a712-961f6844e896')
- def test_snapshot_list_param_limit(self):
- # List returns limited elements
- self._list_snapshots_by_param_limit(limit=1, expected_elements=1)
-
- @test.idempotent_id('a1427f61-420e-48a5-b6e3-0b394fa95400')
- def test_snapshot_list_param_limit_equals_infinite(self):
- # List returns all elements when request limit exceeded
- # snapshots number
- snap_list = self.snapshots_client.list_snapshots()['snapshots']
- self._list_snapshots_by_param_limit(limit=100000,
- expected_elements=len(snap_list))
-
- @decorators.skip_because(bug='1540893')
- @test.idempotent_id('e3b44b7f-ae87-45b5-8a8c-66110eb24d0a')
- def test_snapshot_list_param_limit_equals_zero(self):
- # List returns zero elements
- self._list_snapshots_by_param_limit(limit=0, expected_elements=0)
-
def cleanup_snapshot(self, snapshot):
# Delete the snapshot
self.snapshots_client.delete_snapshot(snapshot['id'])
diff --git a/tempest/api/volume/test_volumes_snapshots_list.py b/tempest/api/volume/test_volumes_snapshots_list.py
new file mode 100644
index 0000000..4416bef
--- /dev/null
+++ b/tempest/api/volume/test_volumes_snapshots_list.py
@@ -0,0 +1,116 @@
+# 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.volume import base
+from tempest import config
+from tempest.lib import decorators
+from tempest import test
+
+CONF = config.CONF
+
+
+class VolumesV2SnapshotListTestJSON(base.BaseVolumeTest):
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumesV2SnapshotListTestJSON, cls).skip_checks()
+ if not CONF.volume_feature_enabled.snapshot:
+ raise cls.skipException("Cinder volume snapshots are disabled")
+
+ @classmethod
+ def resource_setup(cls):
+ super(VolumesV2SnapshotListTestJSON, cls).resource_setup()
+ cls.volume_origin = cls.create_volume()
+ cls.name_field = cls.special_fields['name_field']
+ # Create snapshots with params
+ for _ in range(2):
+ cls.snapshot = cls.create_snapshot(cls.volume_origin['id'])
+
+ def _list_by_param_values_and_assert(self, with_detail=False, **params):
+ """list or list_details with given params and validates result."""
+
+ fetched_snap_list = self.snapshots_client.list_snapshots(
+ detail=with_detail, **params)['snapshots']
+
+ # Validating params of fetched snapshots
+ for snap in fetched_snap_list:
+ for key in params:
+ msg = "Failed to list snapshots %s by %s" % \
+ ('details' if with_detail else '', key)
+ self.assertEqual(params[key], snap[key], msg)
+
+ def _list_snapshots_by_param_limit(self, limit, expected_elements):
+ """list snapshots by limit param"""
+ # Get snapshots list using limit parameter
+ fetched_snap_list = self.snapshots_client.list_snapshots(
+ limit=limit)['snapshots']
+ # Validating filtered snapshots length equals to expected_elements
+ self.assertEqual(expected_elements, len(fetched_snap_list))
+
+ @test.idempotent_id('59f41f43-aebf-48a9-ab5d-d76340fab32b')
+ def test_snapshots_list_with_params(self):
+ """list snapshots with params."""
+ # Verify list snapshots by display_name filter
+ params = {self.name_field: self.snapshot[self.name_field]}
+ self._list_by_param_values_and_assert(**params)
+
+ # Verify list snapshots by status filter
+ params = {'status': 'available'}
+ self._list_by_param_values_and_assert(**params)
+
+ # Verify list snapshots by status and display name filter
+ params = {'status': 'available',
+ self.name_field: self.snapshot[self.name_field]}
+ self._list_by_param_values_and_assert(**params)
+
+ @test.idempotent_id('220a1022-1fcd-4a74-a7bd-6b859156cda2')
+ def test_snapshots_list_details_with_params(self):
+ """list snapshot details with params."""
+ # Verify list snapshot details by display_name filter
+ params = {self.name_field: self.snapshot[self.name_field]}
+ self._list_by_param_values_and_assert(with_detail=True, **params)
+ # Verify list snapshot details by status filter
+ params = {'status': 'available'}
+ self._list_by_param_values_and_assert(with_detail=True, **params)
+ # Verify list snapshot details by status and display name filter
+ params = {'status': 'available',
+ self.name_field: self.snapshot[self.name_field]}
+ self._list_by_param_values_and_assert(with_detail=True, **params)
+
+ @test.idempotent_id('db4d8e0a-7a2e-41cc-a712-961f6844e896')
+ def test_snapshot_list_param_limit(self):
+ # List returns limited elements
+ self._list_snapshots_by_param_limit(limit=1, expected_elements=1)
+
+ @test.idempotent_id('a1427f61-420e-48a5-b6e3-0b394fa95400')
+ def test_snapshot_list_param_limit_equals_infinite(self):
+ # List returns all elements when request limit exceeded
+ # snapshots number
+ snap_list = self.snapshots_client.list_snapshots()['snapshots']
+ self._list_snapshots_by_param_limit(limit=100000,
+ expected_elements=len(snap_list))
+
+ @decorators.skip_because(bug='1540893')
+ @test.idempotent_id('e3b44b7f-ae87-45b5-8a8c-66110eb24d0a')
+ def test_snapshot_list_param_limit_equals_zero(self):
+ # List returns zero elements
+ self._list_snapshots_by_param_limit(limit=0, expected_elements=0)
+
+ 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 VolumesV1SnapshotLimitTestJSON(VolumesV2SnapshotListTestJSON):
+ _api_version = 1
diff --git a/tempest/clients.py b/tempest/clients.py
index f8c276a..765a526 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -14,7 +14,9 @@
# under the License.
import copy
+
from oslo_log import log as logging
+
from tempest.common import negative_rest_client
from tempest import config
from tempest import exceptions
@@ -115,7 +117,7 @@
configuration[service_for_config] = (
config.service_client_config(service_for_config))
except lib_exc.UnknownServiceClient:
- LOG.warn(
+ LOG.warning(
'Could not load configuration for service %s' % service)
return configuration
@@ -246,6 +248,10 @@
self.auth_provider, **params_v3)
self.roles_v3_client = identity.v3.RolesClient(self.auth_provider,
**params_v3)
+ self.inherited_roles_client = identity.v3.InheritedRolesClient(
+ self.auth_provider, **params_v3)
+ self.role_assignments_client = identity.v3.RoleAssignmentsClient(
+ self.auth_provider, **params_v3)
self.identity_services_v3_client = identity.v3.ServicesClient(
self.auth_provider, **params_v3)
self.policies_client = identity.v3.PoliciesClient(self.auth_provider,
diff --git a/tempest/cmd/init.py b/tempest/cmd/init.py
index eeca063..baa36a2 100644
--- a/tempest/cmd/init.py
+++ b/tempest/cmd/init.py
@@ -69,7 +69,10 @@
def get_parser(self, prog_name):
parser = super(TempestInit, self).get_parser(prog_name)
- parser.add_argument('dir', nargs='?', default=os.getcwd())
+ parser.add_argument('dir', nargs='?', default=os.getcwd(),
+ help="The path to the workspace directory. If you "
+ "omit this argument, the workspace directory is "
+ "your current directory")
parser.add_argument('--config-dir', '-c', default=None)
parser.add_argument('--show-global-config-dir', '-s',
action='store_true', dest='show_global_dir',
@@ -78,7 +81,7 @@
parser.add_argument('--name', help="The workspace name", default=None)
parser.add_argument('--workspace-path', default=None,
help="The path to the workspace file, the default "
- "is ~/.tempest/workspace")
+ "is ~/.tempest/workspace.yaml")
return parser
def generate_testr_conf(self, local_path):
@@ -90,7 +93,7 @@
testr_conf_file.write(testr_conf)
def get_configparser(self, conf_path):
- config_parse = moves.configparser.SafeConfigParser()
+ config_parse = moves.configparser.ConfigParser()
config_parse.optionxform = str
# get any existing values if a config file already exists
if os.path.isfile(conf_path):
@@ -170,10 +173,10 @@
workspace_manager = workspace.WorkspaceManager(
parsed_args.workspace_path)
name = parsed_args.name or parsed_args.dir.split(os.path.sep)[-1]
- workspace_manager.register_new_workspace(
- name, parsed_args.dir, init=True)
config_dir = parsed_args.config_dir or get_tempest_default_config_dir()
if parsed_args.show_global_dir:
print("Global config dir is located at: %s" % config_dir)
sys.exit(0)
self.create_working_dir(parsed_args.dir, config_dir)
+ workspace_manager.register_new_workspace(
+ name, parsed_args.dir, init=True)
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index fef836c..236953c 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -264,8 +264,8 @@
run_thread = threading.Thread(target=run_argv_thread)
run_thread.start()
- returncodes['subunit-trace'] = subunit_trace.trace(subunit_r,
- sys.stdout)
+ returncodes['subunit-trace'] = subunit_trace.trace(
+ subunit_r, sys.stdout, post_fails=True, print_failures=True)
run_thread.join()
subunit_r.close()
# python version of pipefail
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 9947f2a..b2e72c5 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -46,7 +46,7 @@
conf_dir = os.environ.get('TEMPEST_CONFIG_DIR', default_config_dir)
conf_file = os.environ.get('TEMPEST_CONFIG', default_config_file)
path = os.path.join(conf_dir, conf_file)
- fd = open(path, 'rw')
+ fd = open(path, 'r+')
return fd
@@ -370,10 +370,9 @@
replace = opts.replace_ext
global CONF_PARSER
- outfile = sys.stdout
if update:
conf_file = _get_config_file()
- CONF_PARSER = moves.configparser.SafeConfigParser()
+ CONF_PARSER = moves.configparser.ConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index 998612b..b6ff241 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -28,7 +28,7 @@
checked in each test code.
"""
- def __init__(self, target, method):
+ def __init__(self, target, method, policies=None):
"""Initialization of ExistsAllResponseHeaders
param: target Account/Container/Object
@@ -36,6 +36,7 @@
"""
self.target = target
self.method = method
+ self.policies = policies or []
def _content_length_required(self, resp):
# Verify whether given HTTP response must contain content-length.
@@ -84,11 +85,63 @@
return NonExistentHeader('x-account-container-count')
if 'x-account-object-count' not in actual:
return NonExistentHeader('x-account-object-count')
+ if actual['x-account-container-count'] > 0:
+ acct_header = "x-account-storage-policy-"
+ matched_policy_count = 0
+
+ # Loop through the policies and look for account
+ # usage data. There should be at least 1 set
+ for policy in self.policies:
+ front_header = acct_header + policy['name'].lower()
+
+ usage_policies = [
+ front_header + '-bytes-used',
+ front_header + '-object-count',
+ front_header + '-container-count'
+ ]
+
+ # There should be 3 usage values for a give storage
+ # policy in an account bytes, object count, and
+ # container count
+ policy_hdrs = sum(1 for use_hdr in usage_policies
+ if use_hdr in actual)
+
+ # If there are less than 3 headers here then 1 is
+ # missing, let's figure out which one and report
+ if policy_hdrs == 3:
+ matched_policy_count = matched_policy_count + 1
+ else:
+ if policy_hdrs > 0 and policy_hdrs < 3:
+ for use_hdr in usage_policies:
+ if use_hdr not in actual:
+ return NonExistentHeader(use_hdr)
+
+ # Only flag an error if actual policies have been read and
+ # no usage has been found
+ if self.policies and matched_policy_count == 0:
+ return GenericError("No storage policy usage headers")
+
elif self.target == 'Container':
if 'x-container-bytes-used' not in actual:
return NonExistentHeader('x-container-bytes-used')
if 'x-container-object-count' not in actual:
return NonExistentHeader('x-container-object-count')
+ if 'x-storage-policy' not in actual:
+ return NonExistentHeader('x-storage-policy')
+ else:
+ policy_name = actual['x-storage-policy']
+
+ # loop through the policies and ensure that
+ # the value in the container header matches
+ # one of the storage policies
+ for policy in self.policies:
+ if policy['name'] == policy_name:
+ break
+ else:
+ # Ensure that there are actual policies stored
+ if self.policies:
+ return InvalidHeaderValue('x-storage-policy',
+ policy_name)
elif self.target == 'Object':
if 'etag' not in actual:
return NonExistentHeader('etag')
@@ -114,6 +167,19 @@
return None
+class GenericError(object):
+ """Informs an error message of a generic error during header evaluation"""
+
+ def __init__(self, body):
+ self.body = body
+
+ def describe(self):
+ return "%s" % self.body
+
+ def get_details(self):
+ return {}
+
+
class NonExistentHeader(object):
"""Informs an error message in the case of missing a certain header"""
@@ -127,6 +193,20 @@
return {}
+class InvalidHeaderValue(object):
+ """Informs an error message when a header contains a bad value"""
+
+ def __init__(self, header, value):
+ self.header = header
+ self.value = value
+
+ def describe(self):
+ return "InvalidValue (%s, %s)" % (self.header, self.value)
+
+ def get_details(self):
+ return {}
+
+
class AreAllWellFormatted(object):
"""Specific matcher to check the correctness of formats of values
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 04c9645..b96b1c0 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -136,8 +136,6 @@
email = data_utils.rand_name(root) + "@example.com"
user = self.creds_client.create_user(
username, user_password, project, email)
- if 'user' in user:
- user = user['user']
role_assigned = False
if admin:
self.creds_client.assign_user_role(user, project, self.admin_role)
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index caab1fa..fa951b5 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -210,6 +210,27 @@
raise exceptions.TimeoutException(message)
+def wait_for_backup_status(client, backup_id, status):
+ """Waits for a Backup to reach a given status."""
+ body = client.show_backup(backup_id)['backup']
+ backup_status = body['status']
+ start = int(time.time())
+
+ while backup_status != status:
+ time.sleep(client.build_interval)
+ body = client.show_backup(backup_id)['backup']
+ backup_status = body['status']
+ if backup_status == 'error' and backup_status != status:
+ raise exceptions.VolumeBackupException(backup_id=backup_id)
+
+ if int(time.time()) - start >= client.build_timeout:
+ message = ('Volume backup %s failed to reach %s status '
+ '(current %s) within the required time (%s s).' %
+ (backup_id, status, backup_status,
+ client.build_timeout))
+ raise exceptions.TimeoutException(message)
+
+
def wait_for_bm_node_status(client, node_id, attr, status):
"""Waits for a baremetal node attribute to reach given status.
diff --git a/tempest/config.py b/tempest/config.py
index 3fd20ab..b6fca7e 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -304,6 +304,12 @@
title="Enabled Compute Service Features")
ComputeFeaturesGroup = [
+ # NOTE(mriedem): This is a feature toggle for bug 1175464 which is fixed in
+ # mitaka and newton. This option can be removed after liberty-eol.
+ cfg.BoolOpt('allow_port_security_disabled',
+ default=False,
+ help='Does the test environment support creating ports in a '
+ 'network where port security is disabled?'),
cfg.BoolOpt('disk_config',
default=True,
help="If false, skip disk config tests"),
@@ -333,6 +339,10 @@
cfg.BoolOpt('suspend',
default=True,
help="Does the test environment support suspend/resume?"),
+ cfg.BoolOpt('cold_migration',
+ default=True,
+ help="Does the test environment support cold migration "
+ "available?"),
cfg.BoolOpt('live_migration',
default=True,
help="Does the test environment support live migration "
@@ -370,7 +380,8 @@
default=True,
help='Enables returning of the instance password by the '
'relevant server API calls such as create, rebuild '
- 'or rescue.'),
+ 'or rescue. This configuration value should be same as '
+ 'nova.conf: DEFAULT.enable_instance_password'),
cfg.BoolOpt('interface_attach',
default=True,
help='Does the test environment support dynamic network '
@@ -564,6 +575,9 @@
default=True,
help="Does the test environment support changing"
" port admin state"),
+ cfg.BoolOpt('port_security',
+ default=False,
+ help="Does the test environment support port security?"),
]
validation_group = cfg.OptGroup(name='validation',
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index e2d6585..4123ae5 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -19,7 +19,7 @@
PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'neutron',
- 'ironic', 'savanna', 'heat', 'sahara']
+ 'ironic', 'heat', 'sahara']
PYTHON_CLIENT_RE = re.compile('import (%s)client' % '|'.join(PYTHON_CLIENTS))
TEST_DEFINITION = re.compile(r'^\s*def test.*')
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index be3aa49..1239ac5 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -69,7 +69,8 @@
lines[line_no - 1] = ''.join(('{%s:s}' % patch_id, lines[line_no - 1]))
self.source_files[filename] = self._quote('\n').join(lines)
- def _save_changes(self, filename, source):
+ @staticmethod
+ def _save_changes(filename, source):
print('%s fixed' % filename)
with open(filename, 'w') as f:
f.write(source)
diff --git a/tempest/lib/common/utils/data_utils.py b/tempest/lib/common/utils/data_utils.py
index 6b6548e..4095c77 100644
--- a/tempest/lib/common/utils/data_utils.py
+++ b/tempest/lib/common/utils/data_utils.py
@@ -19,6 +19,7 @@
import string
import uuid
+from debtcollector import removals
from oslo_utils import netutils
import six.moves
@@ -153,7 +154,7 @@
This generates a string with an arbitrary number of characters, generated
by looping the base_text string. If the size is smaller than the size of
- base_text, returning string is shrinked to the size.
+ base_text, returning string is shrunk to the size.
:param int size: a returning characters size
:param str base_text: a string you want to repeat
:return: size string
@@ -171,10 +172,14 @@
:return: size randomly bytes
:rtype: string
"""
- return ''.join([chr(random.randint(0, 255))
+ return b''.join([six.int2byte(random.randint(0, 255))
for i in range(size)])
+@removals.remove(
+ message="use get_ipv6_addr_by_EUI64 from oslo_utils.netutils",
+ version="Newton",
+ removal_version="Ocata")
def get_ipv6_addr_by_EUI64(cidr, mac):
"""Generate a IPv6 addr by EUI-64 with CIDR and MAC
@@ -204,5 +209,5 @@
# Courtesy of http://stackoverflow.com/a/312464
def chunkify(sequence, chunksize):
"""Yield successive chunks from `sequence`."""
- for i in six.moves.xrange(0, len(sequence), chunksize):
+ for i in range(0, len(sequence), chunksize):
yield sequence[i:i + chunksize]
diff --git a/tempest/lib/services/compute/hosts_client.py b/tempest/lib/services/compute/hosts_client.py
index 16b5edd..1b93b00 100644
--- a/tempest/lib/services/compute/hosts_client.py
+++ b/tempest/lib/services/compute/hosts_client.py
@@ -45,8 +45,9 @@
def update_host(self, hostname, **kwargs):
"""Update a host.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#enablehost
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#enablehost
"""
request_body = {
diff --git a/tempest/lib/services/compute/images_client.py b/tempest/lib/services/compute/images_client.py
index 3dc3749..e937c13 100644
--- a/tempest/lib/services/compute/images_client.py
+++ b/tempest/lib/services/compute/images_client.py
@@ -27,8 +27,9 @@
def create_image(self, server_id, **kwargs):
"""Create an image of the original server.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#createImage
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#createImage
"""
post_body = {'createImage': kwargs}
@@ -41,8 +42,9 @@
def list_images(self, detail=False, **params):
"""Return a list of all images filtered by any parameter.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#listImages
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#listImages
"""
url = 'images'
_schema = schema.list_images
@@ -81,8 +83,9 @@
def set_image_metadata(self, image_id, meta):
"""Set the metadata for an image.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#createImageMetadata
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#createImageMetadata
"""
post_body = json.dumps({'metadata': meta})
resp, body = self.put('images/%s/metadata' % image_id, post_body)
@@ -93,8 +96,9 @@
def update_image_metadata(self, image_id, meta):
"""Update the metadata for an image.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#updateImageMetadata
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#updateImageMetadata
"""
post_body = json.dumps({'metadata': meta})
resp, body = self.post('images/%s/metadata' % image_id, post_body)
@@ -112,8 +116,9 @@
def set_image_metadata_item(self, image_id, key, meta):
"""Set the value for a specific image metadata key.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#setImageMetadataItem
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#setImageMetadataItem
"""
post_body = json.dumps({'meta': meta})
resp, body = self.put('images/%s/metadata/%s' % (image_id, key),
diff --git a/tempest/lib/services/compute/interfaces_client.py b/tempest/lib/services/compute/interfaces_client.py
index 80192a1..37157a4 100644
--- a/tempest/lib/services/compute/interfaces_client.py
+++ b/tempest/lib/services/compute/interfaces_client.py
@@ -31,8 +31,9 @@
def create_interface(self, server_id, **kwargs):
"""Create an interface.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#createAttachInterface
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#createAttachInterface
"""
post_body = {'interfaceAttachment': kwargs}
post_body = json.dumps(post_body)
diff --git a/tempest/lib/services/compute/keypairs_client.py b/tempest/lib/services/compute/keypairs_client.py
index 2246739..c3f1781 100755
--- a/tempest/lib/services/compute/keypairs_client.py
+++ b/tempest/lib/services/compute/keypairs_client.py
@@ -30,8 +30,9 @@
def list_keypairs(self, **params):
"""Lists keypairs that are associated with the account.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#listKeypairs
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#listKeypairs
"""
url = 'os-keypairs'
if params:
@@ -45,8 +46,9 @@
def show_keypair(self, keypair_name, **params):
"""Shows details for a keypair that is associated with the account.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#showKeypair
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#showKeypair
"""
url = "os-keypairs/%s" % keypair_name
if params:
@@ -60,8 +62,9 @@
def create_keypair(self, **kwargs):
"""Create a keypair.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#createKeypair
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#createKeypair
"""
post_body = json.dumps({'keypair': kwargs})
resp, body = self.post("os-keypairs", body=post_body)
@@ -73,8 +76,9 @@
def delete_keypair(self, keypair_name, **params):
"""Deletes a keypair.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#deleteKeypair
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#deleteKeypair
"""
url = "os-keypairs/%s" % keypair_name
if params:
diff --git a/tempest/lib/services/compute/migrations_client.py b/tempest/lib/services/compute/migrations_client.py
index c3bdba7..375cbda 100644
--- a/tempest/lib/services/compute/migrations_client.py
+++ b/tempest/lib/services/compute/migrations_client.py
@@ -30,8 +30,9 @@
def list_migrations(self, **params):
"""List all migrations.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#listMigrations
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#listMigrations
"""
url = 'os-migrations'
diff --git a/tempest/lib/services/compute/quota_classes_client.py b/tempest/lib/services/compute/quota_classes_client.py
index 9dc04ad..523a306 100644
--- a/tempest/lib/services/compute/quota_classes_client.py
+++ b/tempest/lib/services/compute/quota_classes_client.py
@@ -35,8 +35,9 @@
def update_quota_class_set(self, quota_class_id, **kwargs):
"""Update the quota class's limits for one or more resources.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#updatequota
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#updatequota
"""
post_body = json.dumps({'quota_class_set': kwargs})
diff --git a/tempest/lib/services/compute/quotas_client.py b/tempest/lib/services/compute/quotas_client.py
index 6d41f4b..a2b0397 100644
--- a/tempest/lib/services/compute/quotas_client.py
+++ b/tempest/lib/services/compute/quotas_client.py
@@ -45,8 +45,9 @@
def update_quota_set(self, tenant_id, user_id=None, **kwargs):
"""Updates the tenant's quota limits for one or more resources.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#updateQuota
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#updateQuota
"""
post_body = json.dumps({'quota_set': kwargs})
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 8b22be0..d5902e1 100755
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -47,8 +47,13 @@
def create_server(self, **kwargs):
"""Create server.
- Available params: see http://developer.openstack.org/
- api-ref-compute-v2.1.html#createServer
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/compute/#create-server
+
+ :param name: Server name
+ :param imageRef: Image reference (UUID)
+ :param flavorRef: Flavor reference (UUID or full URL)
Most parameters except the following are passed to the API without
any changes.
diff --git a/tempest/lib/services/identity/v2/__init__.py b/tempest/lib/services/identity/v2/__init__.py
index e69de29..b7d3c74 100644
--- a/tempest/lib/services/identity/v2/__init__.py
+++ b/tempest/lib/services/identity/v2/__init__.py
@@ -0,0 +1,24 @@
+# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from tempest.lib.services.identity.v2.endpoints_client import EndpointsClient
+from tempest.lib.services.identity.v2.identity_client import IdentityClient
+from tempest.lib.services.identity.v2.roles_client import RolesClient
+from tempest.lib.services.identity.v2.services_client import ServicesClient
+from tempest.lib.services.identity.v2.tenants_client import TenantsClient
+from tempest.lib.services.identity.v2.token_client import TokenClient
+from tempest.lib.services.identity.v2.users_client import UsersClient
+
+__all__ = ['EndpointsClient', 'IdentityClient', 'RolesClient',
+ 'ServicesClient', 'TenantsClient', 'TokenClient', 'UsersClient']
diff --git a/tempest/lib/services/identity/v2/endpoints_client.py b/tempest/lib/services/identity/v2/endpoints_client.py
index f7b265d..770e8ae 100644
--- a/tempest/lib/services/identity/v2/endpoints_client.py
+++ b/tempest/lib/services/identity/v2/endpoints_client.py
@@ -23,8 +23,9 @@
def create_endpoint(self, **kwargs):
"""Create an endpoint for service.
- Available params: http://developer.openstack.org/
- api-ref-identity-v2-ext.html#createEndpoint
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#createEndpoint
"""
post_body = json.dumps({'endpoint': kwargs})
diff --git a/tempest/lib/services/identity/v2/roles_client.py b/tempest/lib/services/identity/v2/roles_client.py
index aaa75f1..635d013 100644
--- a/tempest/lib/services/identity/v2/roles_client.py
+++ b/tempest/lib/services/identity/v2/roles_client.py
@@ -22,8 +22,9 @@
def create_role(self, **kwargs):
"""Create a role.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v2-ext.html#createRole
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#createRole
"""
post_body = json.dumps({'role': kwargs})
resp, body = self.post('OS-KSADM/roles', post_body)
@@ -34,12 +35,11 @@
def show_role(self, role_id_or_name):
"""Get a role by its id or name.
- Available params: see
- http://developer.openstack.org/
- api-ref-identity-v2-ext.html#showRoleByID
- OR
- http://developer.openstack.org/
- api-ref-identity-v2-ext.html#showRoleByName
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#showRoleByID
+ OR
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#showRoleByName
"""
resp, body = self.get('OS-KSADM/roles/%s' % role_id_or_name)
self.expected_success(200, resp.status)
@@ -49,8 +49,9 @@
def list_roles(self, **params):
"""Returns roles.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v2-ext.html#listRoles
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#listRoles
"""
url = 'OS-KSADM/roles'
if params:
@@ -63,8 +64,9 @@
def delete_role(self, role_id):
"""Delete a role.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v2-ext.html#deleteRole
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#deleteRole
"""
resp, body = self.delete('OS-KSADM/roles/%s' % role_id)
self.expected_success(204, resp.status)
@@ -73,9 +75,9 @@
def create_user_role_on_project(self, tenant_id, user_id, role_id):
"""Add roles to a user on a tenant.
- Available params: see
- http://developer.openstack.org/
- api-ref-identity-v2-ext.html#grantRoleToUserOnTenant
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#grantRoleToUserOnTenant
"""
resp, body = self.put('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
(tenant_id, user_id, role_id), "")
@@ -97,9 +99,9 @@
def delete_role_from_user_on_project(self, tenant_id, user_id, role_id):
"""Removes a role assignment for a user on a tenant.
- Available params: see
- http://developer.openstack.org/
- api-ref-identity-v2-ext.html#revokeRoleFromUserOnTenant
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#revokeRoleFromUserOnTenant
"""
resp, body = self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
(tenant_id, user_id, role_id))
diff --git a/tempest/lib/services/identity/v2/services_client.py b/tempest/lib/services/identity/v2/services_client.py
index c26d419..b3f94aa 100755
--- a/tempest/lib/services/identity/v2/services_client.py
+++ b/tempest/lib/services/identity/v2/services_client.py
@@ -24,8 +24,9 @@
def create_service(self, **kwargs):
"""Create a service.
- Available params: see http://developer.openstack.org/api-ref/identity/
- v2-ext/?expanded=#create-service-admin-extension
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-ext/?expanded=#create-service-admin-extension
"""
post_body = json.dumps({'OS-KSADM:service': kwargs})
resp, body = self.post('/OS-KSADM/services', post_body)
@@ -44,8 +45,9 @@
def list_services(self, **params):
"""List Service - Returns Services.
- Available params: see http://developer.openstack.org/api-ref/identity/
- v2-ext/?expanded=#list-services-admin-extension
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-ext/?expanded=#list-services-admin-extension
"""
url = '/OS-KSADM/services'
if params:
diff --git a/tempest/lib/services/identity/v2/tenants_client.py b/tempest/lib/services/identity/v2/tenants_client.py
index f92c703..b687332 100644
--- a/tempest/lib/services/identity/v2/tenants_client.py
+++ b/tempest/lib/services/identity/v2/tenants_client.py
@@ -24,9 +24,9 @@
def create_tenant(self, **kwargs):
"""Create a tenant
- Available params: see http://developer.openstack.org/
- api-ref/identity/v2-admin/index.html#
- create-tenant
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-admin/index.html#create-tenant
"""
post_body = json.dumps({'tenant': kwargs})
resp, body = self.post('tenants', post_body)
@@ -37,8 +37,9 @@
def delete_tenant(self, tenant_id):
"""Delete a tenant.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v2-ext.html#deleteTenant
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#deleteTenant
"""
resp, body = self.delete('tenants/%s' % str(tenant_id))
self.expected_success(204, resp.status)
@@ -47,9 +48,9 @@
def show_tenant(self, tenant_id):
"""Get tenant details.
- Available params: see
- http://developer.openstack.org/
- api-ref-identity-v2-ext.html#admin-showTenantById
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#admin-showTenantById
"""
resp, body = self.get('tenants/%s' % str(tenant_id))
self.expected_success(200, resp.status)
@@ -59,9 +60,9 @@
def list_tenants(self, **params):
"""Returns tenants.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v2-admin/index.html#
- list-tenants-admin-endpoint
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-admin/index.html#list-tenants-admin-endpoint
"""
url = 'tenants'
if params:
@@ -74,9 +75,9 @@
def update_tenant(self, tenant_id, **kwargs):
"""Updates a tenant.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v2-admin/index.html#
- update-tenant
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-admin/index.html#update-tenant
"""
if 'id' not in kwargs:
kwargs['id'] = tenant_id
@@ -89,9 +90,9 @@
def list_tenant_users(self, tenant_id, **params):
"""List users for a Tenant.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v2-admin/index.html#
- list-users-on-a-tenant
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-admin/index.html#list-users-on-a-tenant
"""
url = '/tenants/%s/users' % tenant_id
if params:
diff --git a/tempest/lib/services/identity/v2/users_client.py b/tempest/lib/services/identity/v2/users_client.py
index 2a266d9..f20fdc4 100644
--- a/tempest/lib/services/identity/v2/users_client.py
+++ b/tempest/lib/services/identity/v2/users_client.py
@@ -22,9 +22,9 @@
def create_user(self, **kwargs):
"""Create a user.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v2-admin/index.html#
- create-user-admin-endpoint
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-admin/index.html#create-user-admin-endpoint
"""
post_body = json.dumps({'user': kwargs})
resp, body = self.post('users', post_body)
@@ -35,9 +35,9 @@
def update_user(self, user_id, **kwargs):
"""Updates a user.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v2-admin/index.html#
- update-user-admin-endpoint
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-admin/index.html#update-user-admin-endpoint
"""
put_body = json.dumps({'user': kwargs})
resp, body = self.put('users/%s' % user_id, put_body)
@@ -48,8 +48,9 @@
def show_user(self, user_id):
"""GET a user.
- Available params: see http://developer.openstack.org/
- api-ref-identity-admin-v2.html#admin-showUser
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-admin-v2.html#admin-showUser
"""
resp, body = self.get("users/%s" % user_id)
self.expected_success(200, resp.status)
@@ -59,8 +60,9 @@
def delete_user(self, user_id):
"""Delete a user.
- Available params: see http://developer.openstack.org/
- api-ref-identity-admin-v2.html#admin-deleteUser
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-admin-v2.html#admin-deleteUser
"""
resp, body = self.delete("users/%s" % user_id)
self.expected_success(204, resp.status)
@@ -69,9 +71,9 @@
def list_users(self, **params):
"""Get the list of users.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v2-admin/index.html#
- list-users-admin-endpoint
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v2-admin/index.html#list-users-admin-endpoint
"""
url = "users"
if params:
@@ -84,8 +86,9 @@
def update_user_enabled(self, user_id, **kwargs):
"""Enables or disables a user.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v2-ext.html#enableUser
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-identity-v2-ext.html#enableUser
"""
# NOTE: The URL (users/<id>/enabled) is different from the api-site
# one (users/<id>/OS-KSADM/enabled) , but they are the same API
diff --git a/tempest/services/identity/v3/json/credentials_client.py b/tempest/lib/services/identity/v3/credentials_client.py
similarity index 71%
rename from tempest/services/identity/v3/json/credentials_client.py
rename to tempest/lib/services/identity/v3/credentials_client.py
index 55eeee4..6e5fd31 100644
--- a/tempest/services/identity/v3/json/credentials_client.py
+++ b/tempest/lib/services/identity/v3/credentials_client.py
@@ -14,7 +14,7 @@
# under the License.
"""
-http://developer.openstack.org/api-ref-identity-v3.html#credentials
+http://developer.openstack.org/api-ref/identity/v3/index.html#credentials
"""
from oslo_serialization import jsonutils as json
@@ -29,46 +29,47 @@
def create_credential(self, **kwargs):
"""Creates a credential.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#create-credential
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-credential
"""
post_body = json.dumps({'credential': kwargs})
resp, body = self.post('credentials', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- body['credential']['blob'] = json.loads(body['credential']['blob'])
return rest_client.ResponseBody(resp, body)
def update_credential(self, credential_id, **kwargs):
"""Updates a credential.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#update-credential
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-credential
"""
post_body = json.dumps({'credential': kwargs})
resp, body = self.patch('credentials/%s' % credential_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- body['credential']['blob'] = json.loads(body['credential']['blob'])
return rest_client.ResponseBody(resp, body)
def show_credential(self, credential_id):
"""To GET Details of a credential.
- For API details, see http://developer.openstack.org/
- api-ref-identity-v3.html#show-credential-details
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#show-credential-details
"""
resp, body = self.get('credentials/%s' % credential_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- body['credential']['blob'] = json.loads(body['credential']['blob'])
return rest_client.ResponseBody(resp, body)
def list_credentials(self, **params):
"""Lists out all the available credentials.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#list-credentials
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#list-credentials
"""
url = 'credentials'
if params:
@@ -81,8 +82,9 @@
def delete_credential(self, credential_id):
"""Deletes a credential.
- For API details, see http://developer.openstack.org/
- api-ref/identity/v3/#delete-credential
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#delete-credential
"""
resp, body = self.delete('credentials/%s' % credential_id)
self.expected_success(204, resp.status)
diff --git a/tempest/lib/services/identity/v3/endpoints_client.py b/tempest/lib/services/identity/v3/endpoints_client.py
index db30508..c4c0d8d 100644
--- a/tempest/lib/services/identity/v3/endpoints_client.py
+++ b/tempest/lib/services/identity/v3/endpoints_client.py
@@ -35,8 +35,9 @@
def create_endpoint(self, **kwargs):
"""Create endpoint.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createEndpoint
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-endpoint
"""
post_body = json.dumps({'endpoint': kwargs})
resp, body = self.post('endpoints', post_body)
@@ -47,8 +48,9 @@
def update_endpoint(self, endpoint_id, **kwargs):
"""Updates an endpoint with given parameters.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateEndpoint
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-endpoint
"""
post_body = json.dumps({'endpoint': kwargs})
resp, body = self.patch('endpoints/%s' % endpoint_id, post_body)
diff --git a/tempest/services/identity/v3/json/groups_client.py b/tempest/lib/services/identity/v3/groups_client.py
similarity index 83%
rename from tempest/services/identity/v3/json/groups_client.py
rename to tempest/lib/services/identity/v3/groups_client.py
index 3674496..5e68939 100644
--- a/tempest/services/identity/v3/json/groups_client.py
+++ b/tempest/lib/services/identity/v3/groups_client.py
@@ -29,8 +29,9 @@
def create_group(self, **kwargs):
"""Creates a group.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createGroup
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-group
"""
post_body = json.dumps({'group': kwargs})
resp, body = self.post('groups', post_body)
@@ -48,8 +49,9 @@
def list_groups(self, **params):
"""Lists the groups.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#list-groups
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#list-groups
"""
url = 'groups'
if params:
@@ -62,8 +64,9 @@
def update_group(self, group_id, **kwargs):
"""Updates a group.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateGroup
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-group
"""
post_body = json.dumps({'group': kwargs})
resp, body = self.patch('groups/%s' % group_id, post_body)
@@ -87,8 +90,9 @@
def list_group_users(self, group_id, **params):
"""List users in group.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#list-users-in-group
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#list-users-in-group
"""
url = 'groups/%s/users' % group_id
if params:
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/lib/services/identity/v3/identity_client.py
similarity index 100%
rename from tempest/services/identity/v3/json/identity_client.py
rename to tempest/lib/services/identity/v3/identity_client.py
diff --git a/tempest/lib/services/identity/v3/inherited_roles_client.py b/tempest/lib/services/identity/v3/inherited_roles_client.py
new file mode 100644
index 0000000..691c7fd
--- /dev/null
+++ b/tempest/lib/services/identity/v3/inherited_roles_client.py
@@ -0,0 +1,151 @@
+# Copyright 2016 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_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class InheritedRolesClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def create_inherited_role_on_domains_user(
+ self, domain_id, user_id, role_id):
+ """Assigns a role to a user on projects owned by a domain."""
+ resp, body = self.put(
+ "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
+ % (domain_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_inherited_role_from_user_on_domain(
+ self, domain_id, user_id, role_id):
+ """Revokes an inherited project role from a user on a domain."""
+ resp, body = self.delete(
+ "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
+ % (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_inherited_project_role_for_user_on_domain(
+ self, domain_id, user_id):
+ """Lists the inherited project roles on a domain for a user."""
+ resp, body = self.get(
+ "OS-INHERIT/domains/%s/users/%s/roles/inherited_to_projects"
+ % (domain_id, user_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_user_inherited_project_role_on_domain(
+ self, domain_id, user_id, role_id):
+ """Checks whether a user has an inherited project role on a domain."""
+ resp, body = self.head(
+ "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
+ % (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def create_inherited_role_on_domains_group(
+ self, domain_id, group_id, role_id):
+ """Assigns a role to a group on projects owned by a domain."""
+ resp, body = self.put(
+ "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (domain_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_inherited_role_from_group_on_domain(
+ self, domain_id, group_id, role_id):
+ """Revokes an inherited project role from a group on a domain."""
+ resp, body = self.delete(
+ "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_inherited_project_role_for_group_on_domain(
+ self, domain_id, group_id):
+ """Lists the inherited project roles on a domain for a group."""
+ resp, body = self.get(
+ "OS-INHERIT/domains/%s/groups/%s/roles/inherited_to_projects"
+ % (domain_id, group_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_group_inherited_project_role_on_domain(
+ self, domain_id, group_id, role_id):
+ """Checks whether a group has an inherited project role on a domain."""
+ resp, body = self.head(
+ "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def create_inherited_role_on_projects_user(
+ self, project_id, user_id, role_id):
+ """Assigns a role to a user on projects in a subtree."""
+ resp, body = self.put(
+ "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
+ % (project_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_inherited_role_from_user_on_project(
+ self, project_id, user_id, role_id):
+ """Revokes an inherited role from a user on a project."""
+ resp, body = self.delete(
+ "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
+ % (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_user_has_flag_on_inherited_to_project(
+ self, project_id, user_id, role_id):
+ """Checks whether a user has a role assignment"""
+ """with the inherited_to_projects flag on a project."""
+ resp, body = self.head(
+ "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
+ % (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def create_inherited_role_on_projects_group(
+ self, project_id, group_id, role_id):
+ """Assigns a role to a group on projects in a subtree."""
+ resp, body = self.put(
+ "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (project_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_inherited_role_from_group_on_project(
+ self, project_id, group_id, role_id):
+ """Revokes an inherited role from a group on a project."""
+ resp, body = self.delete(
+ "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_group_has_flag_on_inherited_to_project(
+ self, project_id, group_id, role_id):
+ """Checks whether a group has a role assignment"""
+ """with the inherited_to_projects flag on a project."""
+ resp, body = self.head(
+ "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
diff --git a/tempest/lib/services/identity/v3/policies_client.py b/tempest/lib/services/identity/v3/policies_client.py
index f28db9a..0282745 100644
--- a/tempest/lib/services/identity/v3/policies_client.py
+++ b/tempest/lib/services/identity/v3/policies_client.py
@@ -28,8 +28,9 @@
def create_policy(self, **kwargs):
"""Creates a Policy.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createPolicy
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-policy
"""
post_body = json.dumps({'policy': kwargs})
resp, body = self.post('policies', post_body)
@@ -55,8 +56,9 @@
def update_policy(self, policy_id, **kwargs):
"""Updates a policy.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updatePolicy
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-policy
"""
post_body = json.dumps({'policy': kwargs})
url = 'policies/%s' % policy_id
diff --git a/tempest/lib/services/identity/v3/projects_client.py b/tempest/lib/services/identity/v3/projects_client.py
index ce2f38d..20787da 100644
--- a/tempest/lib/services/identity/v3/projects_client.py
+++ b/tempest/lib/services/identity/v3/projects_client.py
@@ -25,8 +25,9 @@
def create_project(self, name, **kwargs):
"""Create a Project.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createProject
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-project
"""
# Include the project name to the kwargs parameters
@@ -49,8 +50,9 @@
def update_project(self, project_id, **kwargs):
"""Update a Project.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateProject
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-project
"""
post_body = json.dumps({'project': kwargs})
diff --git a/tempest/lib/services/identity/v3/regions_client.py b/tempest/lib/services/identity/v3/regions_client.py
index 90dd9d7..33c754a 100644
--- a/tempest/lib/services/identity/v3/regions_client.py
+++ b/tempest/lib/services/identity/v3/regions_client.py
@@ -29,11 +29,9 @@
def create_region(self, region_id=None, **kwargs):
"""Create region.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createRegion
-
- see http://developer.openstack.org/
- api-ref-identity-v3.html#createRegionWithID
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-region
"""
if region_id is not None:
method = self.put
@@ -50,8 +48,9 @@
def update_region(self, region_id, **kwargs):
"""Updates a region.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateRegion
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-region
"""
post_body = json.dumps({'region': kwargs})
resp, body = self.patch('regions/%s' % region_id, post_body)
diff --git a/tempest/lib/services/identity/v3/roles_client.py b/tempest/lib/services/identity/v3/roles_client.py
new file mode 100644
index 0000000..f1339dd
--- /dev/null
+++ b/tempest/lib/services/identity/v3/roles_client.py
@@ -0,0 +1,192 @@
+# Copyright 2016 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_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class RolesClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def create_role(self, **kwargs):
+ """Create a Role.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-role
+ """
+ post_body = json.dumps({'role': kwargs})
+ resp, body = self.post('roles', post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_role(self, role_id):
+ """GET a Role."""
+ resp, body = self.get('roles/%s' % role_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_roles(self, **params):
+ """Get the list of Roles."""
+
+ url = 'roles'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_role(self, role_id, **kwargs):
+ """Update a Role.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-role
+ """
+ post_body = json.dumps({'role': kwargs})
+ resp, body = self.patch('roles/%s' % role_id, post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role(self, role_id):
+ """Delete a role."""
+ resp, body = self.delete('roles/%s' % role_id)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def create_user_role_on_project(self, project_id, user_id, role_id):
+ """Add roles to a user on a project."""
+ resp, body = self.put('projects/%s/users/%s/roles/%s' %
+ (project_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def create_user_role_on_domain(self, domain_id, user_id, role_id):
+ """Add roles to a user on a domain."""
+ resp, body = self.put('domains/%s/users/%s/roles/%s' %
+ (domain_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_user_roles_on_project(self, project_id, user_id):
+ """list roles of a user on a project."""
+ resp, body = self.get('projects/%s/users/%s/roles' %
+ (project_id, user_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_user_roles_on_domain(self, domain_id, user_id):
+ """list roles of a user on a domain."""
+ resp, body = self.get('domains/%s/users/%s/roles' %
+ (domain_id, user_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_user_on_project(self, project_id, user_id, role_id):
+ """Delete role of a user on a project."""
+ resp, body = self.delete('projects/%s/users/%s/roles/%s' %
+ (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_user_on_domain(self, domain_id, user_id, role_id):
+ """Delete role of a user on a domain."""
+ resp, body = self.delete('domains/%s/users/%s/roles/%s' %
+ (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_user_role_existence_on_project(self, project_id,
+ user_id, role_id):
+ """Check role of a user on a project."""
+ resp, body = self.head('projects/%s/users/%s/roles/%s' %
+ (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def check_user_role_existence_on_domain(self, domain_id,
+ user_id, role_id):
+ """Check role of a user on a domain."""
+ resp, body = self.head('domains/%s/users/%s/roles/%s' %
+ (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def create_group_role_on_project(self, project_id, group_id, role_id):
+ """Add roles to a group on a project."""
+ resp, body = self.put('projects/%s/groups/%s/roles/%s' %
+ (project_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def create_group_role_on_domain(self, domain_id, group_id, role_id):
+ """Add roles to a group on a domain."""
+ resp, body = self.put('domains/%s/groups/%s/roles/%s' %
+ (domain_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_group_roles_on_project(self, project_id, group_id):
+ """list roles of a group on a project."""
+ resp, body = self.get('projects/%s/groups/%s/roles' %
+ (project_id, group_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_group_roles_on_domain(self, domain_id, group_id):
+ """list roles of a group on a domain."""
+ resp, body = self.get('domains/%s/groups/%s/roles' %
+ (domain_id, group_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_group_on_project(self, project_id, group_id, role_id):
+ """Delete role of a group on a project."""
+ resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
+ (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_group_on_domain(self, domain_id, group_id, role_id):
+ """Delete role of a group on a domain."""
+ resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
+ (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_role_from_group_on_project_existence(self, project_id,
+ group_id, role_id):
+ """Check role of a group on a project."""
+ resp, body = self.head('projects/%s/groups/%s/roles/%s' %
+ (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def check_role_from_group_on_domain_existence(self, domain_id,
+ group_id, role_id):
+ """Check role of a group on a domain."""
+ resp, body = self.head('domains/%s/groups/%s/roles/%s' %
+ (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
diff --git a/tempest/lib/services/identity/v3/services_client.py b/tempest/lib/services/identity/v3/services_client.py
index 95caf7d..14c81cc 100644
--- a/tempest/lib/services/identity/v3/services_client.py
+++ b/tempest/lib/services/identity/v3/services_client.py
@@ -29,8 +29,9 @@
def update_service(self, service_id, **kwargs):
"""Updates a service.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateService
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#update-service
"""
patch_body = json.dumps({'service': kwargs})
resp, body = self.patch('services/%s' % service_id, patch_body)
@@ -49,8 +50,9 @@
def create_service(self, **kwargs):
"""Creates a service.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createService
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#create-service
"""
body = json.dumps({'service': kwargs})
resp, body = self.post("services", body)
@@ -67,8 +69,9 @@
def list_services(self, **params):
"""List services.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#list-services
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#list-services
"""
url = 'services'
if params:
diff --git a/tempest/services/identity/v3/json/trusts_client.py b/tempest/lib/services/identity/v3/trusts_client.py
similarity index 80%
rename from tempest/services/identity/v3/json/trusts_client.py
rename to tempest/lib/services/identity/v3/trusts_client.py
index dedee05..d113905 100644
--- a/tempest/services/identity/v3/json/trusts_client.py
+++ b/tempest/lib/services/identity/v3/trusts_client.py
@@ -13,6 +13,7 @@
# limitations under the License.
from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
@@ -23,8 +24,9 @@
def create_trust(self, **kwargs):
"""Creates a trust.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3-ext.html#createTrust
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3-ext/index.html#create-trust
"""
post_body = json.dumps({'trust': kwargs})
resp, body = self.post('OS-TRUST/trusts', post_body)
@@ -38,16 +40,17 @@
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
- def list_trusts(self, trustor_user_id=None, trustee_user_id=None):
- """GET trusts."""
- if trustor_user_id:
- resp, body = self.get("OS-TRUST/trusts?trustor_user_id=%s"
- % trustor_user_id)
- elif trustee_user_id:
- resp, body = self.get("OS-TRUST/trusts?trustee_user_id=%s"
- % trustee_user_id)
- else:
- resp, body = self.get("OS-TRUST/trusts")
+ def list_trusts(self, **params):
+ """Returns trusts
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3-ext/index.html#list-trusts
+ """
+ url = "OS-TRUST/trusts/"
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+ resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/users_clients.py b/tempest/lib/services/identity/v3/users_client.py
similarity index 75%
rename from tempest/services/identity/v3/json/users_clients.py
rename to tempest/lib/services/identity/v3/users_client.py
index 0dcdacd..e99a971 100644
--- a/tempest/services/identity/v3/json/users_clients.py
+++ b/tempest/lib/services/identity/v3/users_client.py
@@ -24,8 +24,9 @@
def create_user(self, **kwargs):
"""Creates a user.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#create-user
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#create-user
"""
post_body = json.dumps({'user': kwargs})
resp, body = self.post('users', post_body)
@@ -36,8 +37,9 @@
def update_user(self, user_id, **kwargs):
"""Updates a user.
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateUser
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#update-user
"""
if 'id' not in kwargs:
kwargs['id'] = user_id
@@ -50,8 +52,9 @@
def update_user_password(self, user_id, **kwargs):
"""Update a user password
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#changeUserPassword
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/index.html#change-password-for-user
"""
update_user = json.dumps({'user': kwargs})
resp, _ = self.post('users/%s/password' % user_id, update_user)
@@ -61,8 +64,9 @@
def list_user_projects(self, user_id, **params):
"""Lists the projects on which a user has roles assigned.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#list-projects-for-user
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#list-projects-for-user
"""
url = 'users/%s/projects' % user_id
if params:
@@ -75,8 +79,9 @@
def list_users(self, **params):
"""Get the list of users.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#list-users
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#list-users
"""
url = 'users'
if params:
@@ -102,8 +107,9 @@
def list_user_groups(self, user_id, **params):
"""Lists groups which a user belongs to.
- Available params: see http://developer.openstack.org/
- api-ref/identity/v3/#list-groups-to-which-a-user-belongs
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/identity/v3/#list-groups-to-which-a-user-belongs
"""
url = 'users/%s/groups' % user_id
if params:
diff --git a/tempest/lib/services/image/v1/image_members_client.py b/tempest/lib/services/image/v1/image_members_client.py
index e7fa0c9..2318087 100644
--- a/tempest/lib/services/image/v1/image_members_client.py
+++ b/tempest/lib/services/image/v1/image_members_client.py
@@ -29,8 +29,9 @@
def list_shared_images(self, tenant_id):
"""List image memberships for the given tenant.
- Available params: see http://developer.openstack.org/
- api-ref-image-v1.html#listSharedImages-v1
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v1/#list-shared-images
"""
url = 'shared-images/%s' % tenant_id
@@ -42,8 +43,9 @@
def create_image_member(self, image_id, member_id, **kwargs):
"""Add a member to an image.
- Available params: see http://developer.openstack.org/
- api-ref-image-v1.html#addMember-v1
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v1/#add-member-to-image
"""
url = 'images/%s/members/%s' % (image_id, member_id)
body = json.dumps({'member': kwargs})
@@ -54,8 +56,9 @@
def delete_image_member(self, image_id, member_id):
"""Removes a membership from the image.
- Available params: see http://developer.openstack.org/
- api-ref-image-v1.html#removeMember-v1
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v1/#remove-member
"""
url = 'images/%s/members/%s' % (image_id, member_id)
resp, __ = self.delete(url)
diff --git a/tempest/lib/services/image/v1/images_client.py b/tempest/lib/services/image/v1/images_client.py
index 0db98f8..9737be3 100644
--- a/tempest/lib/services/image/v1/images_client.py
+++ b/tempest/lib/services/image/v1/images_client.py
@@ -61,8 +61,9 @@
def create_image(self, data=None, headers=None):
"""Create an image.
- Available params: http://developer.openstack.org/
- api-ref-image-v1.html#createImage-v1
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-image-v1.html#createImage-v1
"""
if headers is None:
headers = {}
@@ -78,8 +79,9 @@
def update_image(self, image_id, data=None, headers=None):
"""Update an image.
- Available params: http://developer.openstack.org/
- api-ref-image-v1.html#updateImage-v1
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-image-v1.html#updateImage-v1
"""
if headers is None:
headers = {}
@@ -102,8 +104,9 @@
def list_images(self, detail=False, **kwargs):
"""Return a list of all images filtered by input parameters.
- Available params: see http://developer.openstack.org/
- api-ref-image-v1.html#listImage-v1
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v1/#list-images
Most parameters except the following are passed to the API without
any changes.
diff --git a/tempest/lib/services/image/v2/image_members_client.py b/tempest/lib/services/image/v2/image_members_client.py
index d0ab165..e5118a8 100644
--- a/tempest/lib/services/image/v2/image_members_client.py
+++ b/tempest/lib/services/image/v2/image_members_client.py
@@ -21,8 +21,9 @@
def list_image_members(self, image_id):
"""List image members.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#listImageMembers-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#list-image-members
"""
url = 'images/%s/members' % image_id
resp, body = self.get(url)
@@ -33,8 +34,9 @@
def create_image_member(self, image_id, **kwargs):
"""Create an image member.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#createImageMember-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#create-image-member
"""
url = 'images/%s/members' % image_id
data = json.dumps(kwargs)
@@ -46,8 +48,9 @@
def update_image_member(self, image_id, member_id, **kwargs):
"""Update an image member.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#updateImageMember-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#update-image-member
"""
url = 'images/%s/members/%s' % (image_id, member_id)
data = json.dumps(kwargs)
@@ -59,8 +62,9 @@
def show_image_member(self, image_id, member_id):
"""Show an image member.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#showImageMember-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#show-image-member-details
"""
url = 'images/%s/members/%s' % (image_id, member_id)
resp, body = self.get(url)
@@ -70,8 +74,9 @@
def delete_image_member(self, image_id, member_id):
"""Delete an image member.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#deleteImageMember-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#delete-image-member
"""
url = 'images/%s/members/%s' % (image_id, member_id)
resp, _ = self.delete(url)
diff --git a/tempest/lib/services/image/v2/images_client.py b/tempest/lib/services/image/v2/images_client.py
index 996ce94..bcdae44 100644
--- a/tempest/lib/services/image/v2/images_client.py
+++ b/tempest/lib/services/image/v2/images_client.py
@@ -30,8 +30,9 @@
def update_image(self, image_id, patch):
"""Update an image.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#updateImage-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/index.html#update-an-image
"""
data = json.dumps(patch)
headers = {"Content-Type": "application/openstack-images-v2.0"
@@ -44,8 +45,9 @@
def create_image(self, **kwargs):
"""Create an image.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#createImage-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/index.html#create-an-image
"""
data = json.dumps(kwargs)
resp, body = self.post('images', data)
@@ -56,9 +58,10 @@
def deactivate_image(self, image_id):
"""Deactivate image.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#deactivateImage-v2
- """
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#deactivate-image
+ """
url = 'images/%s/actions/deactivate' % image_id
resp, body = self.post(url, None)
self.expected_success(204, resp.status)
@@ -67,9 +70,10 @@
def reactivate_image(self, image_id):
"""Reactivate image.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#reactivateImage-v2
- """
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#reactivate-image
+ """
url = 'images/%s/actions/reactivate' % image_id
resp, body = self.post(url, None)
self.expected_success(204, resp.status)
@@ -78,8 +82,9 @@
def delete_image(self, image_id):
"""Delete image.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#deleteImage-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#delete-an-image
"""
url = 'images/%s' % image_id
resp, _ = self.delete(url)
@@ -89,8 +94,9 @@
def list_images(self, params=None):
"""List images.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#listImages-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#show-images
"""
url = 'images'
@@ -105,8 +111,9 @@
def show_image(self, image_id):
"""Show image details.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#showImage-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#show-image-details
"""
url = 'images/%s' % image_id
resp, body = self.get(url)
@@ -129,8 +136,9 @@
def store_image_file(self, image_id, data):
"""Upload binary image data.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#storeImageFile-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#upload-binary-image-data
"""
url = 'images/%s/file' % image_id
@@ -147,8 +155,9 @@
def show_image_file(self, image_id):
"""Download binary image data.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#showImageFile-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#download-binary-image-data
"""
url = 'images/%s/file' % image_id
resp, body = self.get(url)
@@ -158,8 +167,9 @@
def add_image_tag(self, image_id, tag):
"""Add an image tag.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#addImageTag-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#add-image-tag
"""
url = 'images/%s/tags/%s' % (image_id, tag)
resp, body = self.put(url, body=None)
@@ -169,8 +179,9 @@
def delete_image_tag(self, image_id, tag):
"""Delete an image tag.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#deleteImageTag-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/#delete-image-tag
"""
url = 'images/%s/tags/%s' % (image_id, tag)
resp, _ = self.delete(url)
diff --git a/tempest/lib/services/image/v2/namespaces_client.py b/tempest/lib/services/image/v2/namespaces_client.py
index 5bd096d..c92ff3a 100644
--- a/tempest/lib/services/image/v2/namespaces_client.py
+++ b/tempest/lib/services/image/v2/namespaces_client.py
@@ -24,8 +24,9 @@
def create_namespace(self, **kwargs):
"""Create a namespace.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#createNamespace-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#create-namespace
"""
data = json.dumps(kwargs)
resp, body = self.post('metadefs/namespaces', data)
@@ -34,6 +35,12 @@
return rest_client.ResponseBody(resp, body)
def show_namespace(self, namespace):
+ """Show namespace details.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#get-namespace-details
+ """
url = 'metadefs/namespaces/%s' % namespace
resp, body = self.get(url)
self.expected_success(200, resp.status)
@@ -43,8 +50,9 @@
def update_namespace(self, namespace, **kwargs):
"""Update a namespace.
- Available params: see http://developer.openstack.org/
- api-ref-image-v2.html#updateNamespace-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#update-namespace
"""
# NOTE: On Glance API, we need to pass namespace on both URI
# and a request body.
@@ -60,8 +68,9 @@
def delete_namespace(self, namespace):
"""Delete a namespace.
- Available params: http://developer.openstack.org/
- api-ref-image-v2.html#deleteNamespace-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#delete-namespace
"""
url = 'metadefs/namespaces/%s' % namespace
resp, _ = self.delete(url)
diff --git a/tempest/lib/services/image/v2/resource_types_client.py b/tempest/lib/services/image/v2/resource_types_client.py
index 8f2a977..1b6889f 100644
--- a/tempest/lib/services/image/v2/resource_types_client.py
+++ b/tempest/lib/services/image/v2/resource_types_client.py
@@ -24,10 +24,10 @@
def list_resource_types(self):
"""Lists all resource types.
- Available params: see http://developer.openstack.org/
- api-ref/image/v2/metadefs-index.html?expanded=#
- list-resource-types
- """
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html?expanded=#list-resource-types
+ """
url = 'metadefs/resource_types'
resp, body = self.get(url)
self.expected_success(200, resp.status)
@@ -37,10 +37,10 @@
def create_resource_type_association(self, namespace_id, **kwargs):
"""Creates a resource type association in given namespace.
- Available params: see http://developer.openstack.org/
- api-ref/image/v2/metadefs-index.html?expanded=#
- create-resource-type-association
- """
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html?expanded=#create-resource-type-association
+ """
url = 'metadefs/namespaces/%s/resource_types' % namespace_id
data = json.dumps(kwargs)
resp, body = self.post(url, data)
@@ -51,10 +51,10 @@
def list_resource_type_association(self, namespace_id):
"""Lists resource type associations in given namespace.
- Available params: see http://developer.openstack.org/
- api-ref/image/v2/metadefs-index.html?expanded=#
- list-resource-type-associations
- """
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html?expanded=#list-resource-type-associations
+ """
url = 'metadefs/namespaces/%s/resource_types' % namespace_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
@@ -64,10 +64,10 @@
def delete_resource_type_association(self, namespace_id, resource_name):
"""Removes resource type association in given namespace.
- Available params: see http://developer.openstack.org/
- api-ref/image/v2/metadefs-index.html?expanded=#
- remove-resource-type-association
- """
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html?expanded=#remove-resource-type-association
+ """
url = 'metadefs/namespaces/%s/resource_types/%s' % (namespace_id,
resource_name)
resp, _ = self.delete(url)
diff --git a/tempest/lib/services/network/floating_ips_client.py b/tempest/lib/services/network/floating_ips_client.py
index f6cc0ff..2bb18e0 100755
--- a/tempest/lib/services/network/floating_ips_client.py
+++ b/tempest/lib/services/network/floating_ips_client.py
@@ -21,8 +21,9 @@
If you specify port information, associates the floating IP with an
internal port.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#createFloatingIp
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-floating-ip
"""
uri = '/floatingips'
post_data = {'floatingip': kwargs}
@@ -31,8 +32,9 @@
def update_floatingip(self, floatingip_id, **kwargs):
"""Updates a floating IP and its association with an internal port.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#updateFloatingIp
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#update-floating-ip
"""
uri = '/floatingips/%s' % floatingip_id
post_data = {'floatingip': kwargs}
@@ -41,8 +43,9 @@
def show_floatingip(self, floatingip_id, **fields):
"""Shows details for a floating IP.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#showFloatingIp
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-floating-ip-details
"""
uri = '/floatingips/%s' % floatingip_id
return self.show_resource(uri, **fields)
@@ -54,8 +57,9 @@
def list_floatingips(self, **filters):
"""Lists floating IPs.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#listFloatingIps
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-floating-ips
"""
uri = '/floatingips'
return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/network/metering_labels_client.py b/tempest/lib/services/network/metering_labels_client.py
index 12a5834..411da1f 100755
--- a/tempest/lib/services/network/metering_labels_client.py
+++ b/tempest/lib/services/network/metering_labels_client.py
@@ -18,9 +18,9 @@
def create_metering_label(self, **kwargs):
"""Creates an L3 metering label.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#
- createMeteringLabel
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-metering-label
"""
uri = '/metering/metering-labels'
post_data = {'metering_label': kwargs}
@@ -29,8 +29,9 @@
def show_metering_label(self, metering_label_id, **fields):
"""Shows details for a metering label.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#showMeteringLabel
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-metering-label-details
"""
uri = '/metering/metering-labels/%s' % metering_label_id
return self.show_resource(uri, **fields)
@@ -38,9 +39,9 @@
def delete_metering_label(self, metering_label_id):
"""Deletes an L3 metering label.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#
- deleteMeteringLabel
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#delete-metering-label
"""
uri = '/metering/metering-labels/%s' % metering_label_id
return self.delete_resource(uri)
@@ -48,9 +49,9 @@
def list_metering_labels(self, **filters):
"""Lists all L3 metering labels that belong to the tenant.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#
- listMeteringLabels
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-metering-labels
"""
uri = '/metering/metering-labels'
return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/network/networks_client.py b/tempest/lib/services/network/networks_client.py
index 6b601ee..77d4823 100755
--- a/tempest/lib/services/network/networks_client.py
+++ b/tempest/lib/services/network/networks_client.py
@@ -18,8 +18,9 @@
def create_network(self, **kwargs):
"""Creates a network.
- Available params: see http://developer.openstack.org/
- api-ref/networking/v2/index.html#create-network
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-network
"""
uri = '/networks'
post_data = {'network': kwargs}
@@ -28,8 +29,9 @@
def update_network(self, network_id, **kwargs):
"""Updates a network.
- Available params: see http://developer.openstack.org/
- api-ref/networking/v2/index.html#update-network
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#update-network
"""
uri = '/networks/%s' % network_id
post_data = {'network': kwargs}
@@ -38,8 +40,9 @@
def show_network(self, network_id, **fields):
"""Shows details for a network.
- Available params: see http://developer.openstack.org/
- api-ref/networking/v2/index.html#show-network-details
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-network-details
"""
uri = '/networks/%s' % network_id
return self.show_resource(uri, **fields)
@@ -51,8 +54,9 @@
def list_networks(self, **filters):
"""Lists networks to which the tenant has access.
- Available params: see http://developer.openstack.org/
- api-ref/networking/v2/index.html#list-networks
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-networks
"""
uri = '/networks'
return self.list_resources(uri, **filters)
@@ -60,8 +64,9 @@
def create_bulk_networks(self, **kwargs):
"""Create multiple networks in a single request.
- Available params: see http://developer.openstack.org/
- api-ref/networking/v2/index.html#bulk-create-networks
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#bulk-create-networks
"""
uri = '/networks'
return self.create_resource(uri, kwargs)
diff --git a/tempest/lib/services/network/ports_client.py b/tempest/lib/services/network/ports_client.py
index 71f1103..93138b9 100755
--- a/tempest/lib/services/network/ports_client.py
+++ b/tempest/lib/services/network/ports_client.py
@@ -19,8 +19,9 @@
def create_port(self, **kwargs):
"""Creates a port on a network.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#createPort
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-port
"""
uri = '/ports'
post_data = {'port': kwargs}
@@ -29,8 +30,9 @@
def update_port(self, port_id, **kwargs):
"""Updates a port.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#updatePort
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#update-port
"""
uri = '/ports/%s' % port_id
post_data = {'port': kwargs}
@@ -39,8 +41,9 @@
def show_port(self, port_id, **fields):
"""Shows details for a port.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#showPort
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-port-details
"""
uri = '/ports/%s' % port_id
return self.show_resource(uri, **fields)
@@ -48,8 +51,9 @@
def delete_port(self, port_id):
"""Deletes a port.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#removePort
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#delete-port
"""
uri = '/ports/%s' % port_id
return self.delete_resource(uri)
@@ -57,8 +61,9 @@
def list_ports(self, **filters):
"""Lists ports to which the tenant has access.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#listPorts
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-ports
"""
uri = '/ports'
return self.list_resources(uri, **filters)
@@ -66,8 +71,9 @@
def create_bulk_ports(self, **kwargs):
"""Create multiple ports in a single request.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#bulkCreatePorts
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html?expanded=#bulk-create-ports
"""
uri = '/ports'
return self.create_resource(uri, kwargs)
diff --git a/tempest/lib/services/network/routers_client.py b/tempest/lib/services/network/routers_client.py
index 23e9c4e..19b7627 100755
--- a/tempest/lib/services/network/routers_client.py
+++ b/tempest/lib/services/network/routers_client.py
@@ -18,8 +18,9 @@
def create_router(self, **kwargs):
"""Create a router.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#createRouter
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-router
"""
post_body = {'router': kwargs}
uri = '/routers'
@@ -28,8 +29,9 @@
def update_router(self, router_id, **kwargs):
"""Updates a logical router.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#updateRouter
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#update-router
"""
uri = '/routers/%s' % router_id
update_body = {'router': kwargs}
@@ -38,8 +40,9 @@
def show_router(self, router_id, **fields):
"""Shows details for a router.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#showRouter
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-router-details
"""
uri = '/routers/%s' % router_id
return self.show_resource(uri, **fields)
@@ -51,8 +54,9 @@
def list_routers(self, **filters):
"""Lists logical routers.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#listRouters
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-routers
"""
uri = '/routers'
return self.list_resources(uri, **filters)
@@ -60,9 +64,9 @@
def add_router_interface(self, router_id, **kwargs):
"""Add router interface.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#
- addRouterInterface
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#add-interface-to-router
"""
uri = '/routers/%s/add_router_interface' % router_id
return self.update_resource(uri, kwargs)
@@ -70,9 +74,9 @@
def remove_router_interface(self, router_id, **kwargs):
"""Remove router interface.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#
- deleteRouterInterface
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#remove-interface-from-router
"""
uri = '/routers/%s/remove_router_interface' % router_id
return self.update_resource(uri, kwargs)
diff --git a/tempest/lib/services/network/security_group_rules_client.py b/tempest/lib/services/network/security_group_rules_client.py
index 6cd01e1..d2bc4a9 100755
--- a/tempest/lib/services/network/security_group_rules_client.py
+++ b/tempest/lib/services/network/security_group_rules_client.py
@@ -18,9 +18,9 @@
def create_security_group_rule(self, **kwargs):
"""Creates an OpenStack Networking security group rule.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#
- createSecGroupRule
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-security-group-rule
"""
uri = '/security-group-rules'
post_data = {'security_group_rule': kwargs}
@@ -29,8 +29,9 @@
def show_security_group_rule(self, security_group_rule_id, **fields):
"""Shows detailed information for a security group rule.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#showSecGroupRule
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-security-group-rule
"""
uri = '/security-group-rules/%s' % security_group_rule_id
return self.show_resource(uri, **fields)
@@ -42,8 +43,9 @@
def list_security_group_rules(self, **filters):
"""Lists a summary of all OpenStack Networking security group rules.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#listSecGroupRules
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-security-group-rules
"""
uri = '/security-group-rules'
return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/network/security_groups_client.py b/tempest/lib/services/network/security_groups_client.py
index 5c89a6f..1f30216 100755
--- a/tempest/lib/services/network/security_groups_client.py
+++ b/tempest/lib/services/network/security_groups_client.py
@@ -18,8 +18,9 @@
def create_security_group(self, **kwargs):
"""Creates an OpenStack Networking security group.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#createSecGroup
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-security-group
"""
uri = '/security-groups'
post_data = {'security_group': kwargs}
@@ -28,8 +29,9 @@
def update_security_group(self, security_group_id, **kwargs):
"""Updates a security group.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#updateSecGroup
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#update-security-group
"""
uri = '/security-groups/%s' % security_group_id
post_data = {'security_group': kwargs}
@@ -38,8 +40,9 @@
def show_security_group(self, security_group_id, **fields):
"""Shows details for a security group.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#showSecGroup
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-security-group
"""
uri = '/security-groups/%s' % security_group_id
return self.show_resource(uri, **fields)
@@ -47,8 +50,9 @@
def delete_security_group(self, security_group_id):
"""Deletes an OpenStack Networking security group.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#deleteSecGroup
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#delete-security-group
"""
uri = '/security-groups/%s' % security_group_id
return self.delete_resource(uri)
@@ -56,8 +60,9 @@
def list_security_groups(self, **filters):
"""Lists OpenStack Networking security groups.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#listSecGroups
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-security-groups
"""
uri = '/security-groups'
return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/network/subnetpools_client.py b/tempest/lib/services/network/subnetpools_client.py
index f0a66a0..7e77e30 100755
--- a/tempest/lib/services/network/subnetpools_client.py
+++ b/tempest/lib/services/network/subnetpools_client.py
@@ -20,8 +20,9 @@
def list_subnetpools(self, **filters):
"""Lists subnet pools to which the tenant has access.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#listSubnetPools
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-subnet-pools
"""
uri = '/subnetpools'
return self.list_resources(uri, **filters)
@@ -29,8 +30,9 @@
def create_subnetpool(self, **kwargs):
"""Creates a subnet pool.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#createSubnetPool
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-subnet-pool
"""
uri = '/subnetpools'
post_data = {'subnetpool': kwargs}
@@ -39,8 +41,9 @@
def show_subnetpool(self, subnetpool_id, **fields):
"""Shows information for a subnet pool.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#showSubnetPool
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-subnet-pool
"""
uri = '/subnetpools/%s' % subnetpool_id
return self.show_resource(uri, **fields)
@@ -48,8 +51,9 @@
def update_subnetpool(self, subnetpool_id, **kwargs):
"""Updates a subnet pool.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#updateSubnetPool
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#update-subnet-pool
"""
uri = '/subnetpools/%s' % subnetpool_id
post_data = {'subnetpool': kwargs}
diff --git a/tempest/lib/services/network/subnets_client.py b/tempest/lib/services/network/subnets_client.py
index 0fde3ee..b843f84 100755
--- a/tempest/lib/services/network/subnets_client.py
+++ b/tempest/lib/services/network/subnets_client.py
@@ -18,8 +18,9 @@
def create_subnet(self, **kwargs):
"""Creates a subnet on a network.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#createSubnet
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#create-subnet
"""
uri = '/subnets'
post_data = {'subnet': kwargs}
@@ -28,8 +29,9 @@
def update_subnet(self, subnet_id, **kwargs):
"""Updates a subnet.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#updateSubnet
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#update-subnet
"""
uri = '/subnets/%s' % subnet_id
post_data = {'subnet': kwargs}
@@ -38,8 +40,9 @@
def show_subnet(self, subnet_id, **fields):
"""Shows details for a subnet.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#showSubnet
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#show-subnet-details
"""
uri = '/subnets/%s' % subnet_id
return self.show_resource(uri, **fields)
@@ -51,8 +54,9 @@
def list_subnets(self, **filters):
"""Lists subnets to which the tenant has access.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#listSubnets
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#list-subnets
"""
uri = '/subnets'
return self.list_resources(uri, **filters)
@@ -60,8 +64,9 @@
def create_bulk_subnets(self, **kwargs):
"""Create multiple subnets in a single request.
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#bulkCreateSubnet
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#bulk-create-subnet
"""
uri = '/subnets'
return self.create_resource(uri, kwargs)
diff --git a/tempest/services/volume/v1/json/encryption_types_client.py b/tempest/lib/services/volume/v1/encryption_types_client.py
similarity index 100%
rename from tempest/services/volume/v1/json/encryption_types_client.py
rename to tempest/lib/services/volume/v1/encryption_types_client.py
diff --git a/tempest/services/volume/base/base_qos_client.py b/tempest/lib/services/volume/v1/qos_client.py
similarity index 96%
copy from tempest/services/volume/base/base_qos_client.py
copy to tempest/lib/services/volume/v1/qos_client.py
index 0ce76a7..65ae274 100644
--- a/tempest/services/volume/base/base_qos_client.py
+++ b/tempest/lib/services/volume/v1/qos_client.py
@@ -18,8 +18,13 @@
from tempest.lib import exceptions as lib_exc
-class BaseQosSpecsClient(rest_client.RestClient):
- """Client class to send CRUD QoS API requests"""
+class QosSpecsClient(rest_client.RestClient):
+ """Volume V1 QoS client.
+
+ Client class to send CRUD QoS API requests
+ """
+
+ api_version = "v1"
def is_resource_deleted(self, qos_id):
try:
diff --git a/tempest/lib/services/volume/v1/quotas_client.py b/tempest/lib/services/volume/v1/quotas_client.py
index 8924b42..678fd82 100644
--- a/tempest/lib/services/volume/v1/quotas_client.py
+++ b/tempest/lib/services/volume/v1/quotas_client.py
@@ -45,8 +45,9 @@
def update_quota_set(self, tenant_id, **kwargs):
"""Updates quota set
- Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v1.html#updateQuota
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-blockstorage-v1.html#updateQuota
"""
put_body = jsonutils.dumps({'quota_set': kwargs})
resp, body = self.put('os-quota-sets/%s' % tenant_id, put_body)
diff --git a/tempest/services/volume/base/base_snapshots_client.py b/tempest/lib/services/volume/v1/snapshots_client.py
old mode 100755
new mode 100644
similarity index 91%
copy from tempest/services/volume/base/base_snapshots_client.py
copy to tempest/lib/services/volume/v1/snapshots_client.py
index 38a6dc7..1881078
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/lib/services/volume/v1/snapshots_client.py
@@ -17,8 +17,8 @@
from tempest.lib import exceptions as lib_exc
-class BaseSnapshotsClient(rest_client.RestClient):
- """Base Client class to send CRUD Volume API requests."""
+class SnapshotsClient(rest_client.RestClient):
+ """Client class to send CRUD Volume V1 API requests."""
create_resp = 200
@@ -26,7 +26,7 @@
"""List all the snapshot.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#listSnapshots
+ api-ref-blockstorage-v1.html#listSnapshots
"""
url = 'snapshots'
if detail:
@@ -43,7 +43,7 @@
"""Returns the details of a single snapshot.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#showSnapshot
+ api-ref-blockstorage-v1.html#showSnapshot
"""
url = "snapshots/%s" % snapshot_id
resp, body = self.get(url)
@@ -55,7 +55,7 @@
"""Creates a new snapshot.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#createSnapshot
+ api-ref-blockstorage-v1.html#createSnapshot
"""
post_body = json.dumps({'snapshot': kwargs})
resp, body = self.post('snapshots', post_body)
@@ -63,23 +63,11 @@
self.expected_success(self.create_resp, resp.status)
return rest_client.ResponseBody(resp, body)
- def update_snapshot(self, snapshot_id, **kwargs):
- """Updates a snapshot.
-
- Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#updateSnapshot
- """
- put_body = json.dumps({'snapshot': kwargs})
- resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
-
def delete_snapshot(self, snapshot_id):
"""Delete Snapshot.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#deleteSnapshot
+ api-ref-blockstorage-v1.html#deleteSnapshot
"""
resp, body = self.delete("snapshots/%s" % snapshot_id)
self.expected_success(202, resp.status)
@@ -126,11 +114,24 @@
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, body)
+ def update_snapshot(self, snapshot_id, **kwargs):
+ """Updates a snapshot.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-blockstorage-v1.html#
+ updateSnapshotMetadata
+ """
+ put_body = json.dumps({'snapshot': kwargs})
+ resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
def show_snapshot_metadata(self, snapshot_id):
"""Get metadata of the snapshot.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#
+ api-ref-blockstorage-v1.html#
showSnapshotMetadata
"""
url = "snapshots/%s/metadata" % snapshot_id
@@ -143,7 +144,7 @@
"""Update metadata for the snapshot.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#
+ api-ref-blockstorage-v1.html#
updateSnapshotMetadata
"""
put_body = json.dumps(kwargs)
diff --git a/tempest/services/volume/base/admin/base_types_client.py b/tempest/lib/services/volume/v1/types_client.py
old mode 100755
new mode 100644
similarity index 94%
rename from tempest/services/volume/base/admin/base_types_client.py
rename to tempest/lib/services/volume/v1/types_client.py
index fe70c1a..dce728d
--- a/tempest/services/volume/base/admin/base_types_client.py
+++ b/tempest/lib/services/volume/v1/types_client.py
@@ -20,7 +20,7 @@
from tempest.lib import exceptions as lib_exc
-class BaseTypesClient(rest_client.RestClient):
+class TypesClient(rest_client.RestClient):
"""Client class to send CRUD Volume Types API requests"""
def is_resource_deleted(self, id):
@@ -39,7 +39,7 @@
"""List all the volume_types created.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#showVolumeTypes
+ api-ref-blockstorage-v1.html#listVolumeTypes
"""
url = 'types'
if params:
@@ -54,7 +54,7 @@
"""Returns the details of a single volume_type.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#showVolumeType
+ api-ref-blockstorage-v1.html#showVolumeType
"""
url = "types/%s" % volume_type_id
resp, body = self.get(url)
@@ -66,7 +66,7 @@
"""Create volume type.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#createVolumeType
+ api-ref-blockstorage-v1.html#createVolumeType
"""
post_body = json.dumps({'volume_type': kwargs})
resp, body = self.post('types', post_body)
@@ -78,7 +78,7 @@
"""Deletes the Specified Volume_type.
Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#deleteVolumeType
+ api-ref-blockstorage-v1.html#deleteVolumeType
"""
resp, body = self.delete("types/%s" % volume_type_id)
self.expected_success(202, resp.status)
diff --git a/tempest/services/volume/v2/json/encryption_types_client.py b/tempest/lib/services/volume/v2/encryption_types_client.py
similarity index 100%
rename from tempest/services/volume/v2/json/encryption_types_client.py
rename to tempest/lib/services/volume/v2/encryption_types_client.py
diff --git a/tempest/services/volume/base/base_qos_client.py b/tempest/lib/services/volume/v2/qos_client.py
similarity index 96%
rename from tempest/services/volume/base/base_qos_client.py
rename to tempest/lib/services/volume/v2/qos_client.py
index 0ce76a7..5fac00f 100644
--- a/tempest/services/volume/base/base_qos_client.py
+++ b/tempest/lib/services/volume/v2/qos_client.py
@@ -18,8 +18,13 @@
from tempest.lib import exceptions as lib_exc
-class BaseQosSpecsClient(rest_client.RestClient):
- """Client class to send CRUD QoS API requests"""
+class QosSpecsClient(rest_client.RestClient):
+ """Volume V2 QoS client.
+
+ Client class to send CRUD QoS API requests
+ """
+
+ api_version = "v2"
def is_resource_deleted(self, qos_id):
try:
diff --git a/tempest/lib/services/volume/v2/quotas_client.py b/tempest/lib/services/volume/v2/quotas_client.py
index a302045..430957d 100644
--- a/tempest/lib/services/volume/v2/quotas_client.py
+++ b/tempest/lib/services/volume/v2/quotas_client.py
@@ -47,8 +47,9 @@
def update_quota_set(self, tenant_id, **kwargs):
"""Updates quota set
- Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#updateQuotas-v2
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-blockstorage-v2.html#updateQuota
"""
put_body = jsonutils.dumps({'quota_set': kwargs})
resp, body = self.put('os-quota-sets/%s' % tenant_id, put_body)
diff --git a/tempest/services/volume/base/base_snapshots_client.py b/tempest/lib/services/volume/v2/snapshots_client.py
old mode 100755
new mode 100644
similarity index 97%
rename from tempest/services/volume/base/base_snapshots_client.py
rename to tempest/lib/services/volume/v2/snapshots_client.py
index 38a6dc7..c84e557
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/lib/services/volume/v2/snapshots_client.py
@@ -17,10 +17,10 @@
from tempest.lib import exceptions as lib_exc
-class BaseSnapshotsClient(rest_client.RestClient):
- """Base Client class to send CRUD Volume API requests."""
-
- create_resp = 200
+class SnapshotsClient(rest_client.RestClient):
+ """Client class to send CRUD Volume V2 API requests."""
+ api_version = "v2"
+ create_resp = 202
def list_snapshots(self, detail=False, **params):
"""List all the snapshot.
diff --git a/tempest/services/volume/base/admin/base_types_client.py b/tempest/lib/services/volume/v2/types_client.py
old mode 100755
new mode 100644
similarity index 77%
copy from tempest/services/volume/base/admin/base_types_client.py
copy to tempest/lib/services/volume/v2/types_client.py
index fe70c1a..d399e99
--- a/tempest/services/volume/base/admin/base_types_client.py
+++ b/tempest/lib/services/volume/v2/types_client.py
@@ -20,8 +20,9 @@
from tempest.lib import exceptions as lib_exc
-class BaseTypesClient(rest_client.RestClient):
- """Client class to send CRUD Volume Types API requests"""
+class TypesClient(rest_client.RestClient):
+ """Client class to send CRUD Volume V2 API requests"""
+ api_version = "v2"
def is_resource_deleted(self, id):
try:
@@ -158,3 +159,42 @@
body = json.loads(body)
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, body)
+
+ def add_type_access(self, volume_type_id, **kwargs):
+ """Adds volume type access for the given project.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-blockstorage-v2.html
+ #createVolumeTypeAccessExt
+ """
+ post_body = json.dumps({'addProjectAccess': kwargs})
+ url = 'types/%s/action' % volume_type_id
+ resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def remove_type_access(self, volume_type_id, **kwargs):
+ """Removes volume type access for the given project.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-blockstorage-v2.html
+ #removeVolumeTypeAccessExt
+ """
+ post_body = json.dumps({'removeProjectAccess': kwargs})
+ url = 'types/%s/action' % volume_type_id
+ resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_type_access(self, volume_type_id):
+ """Print access information about the given volume type.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-blockstorage-v2.html#
+ listVolumeTypeAccessExt
+ """
+ url = 'types/%s/os-volume-type-access' % volume_type_id
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 233d747..4baf420 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -658,7 +658,8 @@
def _create_network(self, networks_client=None,
routers_client=None, tenant_id=None,
- namestart='network-smoke-'):
+ namestart='network-smoke-',
+ port_security_enabled=True):
if not networks_client:
networks_client = self.networks_client
if not routers_client:
@@ -666,7 +667,12 @@
if not tenant_id:
tenant_id = networks_client.tenant_id
name = data_utils.rand_name(namestart)
- result = networks_client.create_network(name=name, tenant_id=tenant_id)
+ network_kwargs = dict(name=name, tenant_id=tenant_id)
+ # Neutron disables port security by default so we have to check the
+ # config before trying to create the network with port_security_enabled
+ if CONF.network_feature_enabled.port_security:
+ network_kwargs['port_security_enabled'] = port_security_enabled
+ result = networks_client.create_network(**network_kwargs)
network = result['network']
self.assertEqual(network['name'], name)
@@ -977,7 +983,7 @@
def _default_security_group(self, client=None, tenant_id=None):
"""Get default secgroup for given tenant_id.
- :returns: DeletableSecurityGroup -- default secgroup for given tenant
+ :returns: default secgroup for given tenant
"""
if client is None:
client = self.security_groups_client
@@ -1141,7 +1147,8 @@
def create_networks(self, networks_client=None,
routers_client=None, subnets_client=None,
- tenant_id=None, dns_nameservers=None):
+ tenant_id=None, dns_nameservers=None,
+ port_security_enabled=True):
"""Create a network with a subnet connected to a router.
The baremetal driver is a special case since all nodes are
@@ -1167,7 +1174,8 @@
else:
network = self._create_network(
networks_client=networks_client,
- tenant_id=tenant_id)
+ tenant_id=tenant_id,
+ port_security_enabled=port_security_enabled)
router = self._get_router(client=routers_client,
tenant_id=tenant_id)
subnet_kwargs = dict(network=network,
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 086b82d..43adfb1 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -36,7 +36,6 @@
super(TestAggregatesBasicOps, cls).setup_clients()
# Use admin client by default
cls.manager = cls.admin_manager
- super(TestAggregatesBasicOps, cls).resource_setup()
cls.aggregates_client = cls.manager.aggregates_client
cls.hosts_client = cls.manager.hosts_client
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index dba1c92..3ac6759 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -47,12 +47,6 @@
10. Check SSH connection to instance after reboot
"""
-
- def nova_list(self):
- servers = self.servers_client.list_servers()
- # The list servers in the compute client is inconsistent...
- return servers['servers']
-
def nova_show(self, server):
got_server = (self.servers_client.show_server(server['id'])
['server'])
@@ -96,6 +90,13 @@
'%s' % (secgroup['id'], server['id']))
raise exceptions.TimeoutException(msg)
+ def _get_floating_ip_in_server_addresses(self, floating_ip, server):
+ for network_name, addresses in server['addresses'].items():
+ for address in addresses:
+ if (address['OS-EXT-IPS:type'] == 'floating' and
+ address['addr'] == floating_ip['ip']):
+ return address
+
@test.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
@test.services('compute', 'volume', 'image', 'network')
def test_minimum_basic_scenario(self):
@@ -105,7 +106,7 @@
server = self.create_server(image_id=image,
key_name=keypair['name'],
wait_until='ACTIVE')
- servers = self.nova_list()
+ servers = self.servers_client.list_servers()['servers']
self.assertIn(server['id'], [x['id'] for x in servers])
self.nova_show(server)
@@ -121,6 +122,16 @@
self.cinder_show(volume)
floating_ip = self.create_floating_ip(server)
+ # fetch the server again to make sure the addresses were refreshed
+ # after associating the floating IP
+ server = self.servers_client.show_server(server['id'])['server']
+ address = self._get_floating_ip_in_server_addresses(
+ floating_ip, server)
+ self.assertIsNotNone(
+ address,
+ "Failed to find floating IP '%s' in server addresses: %s" %
+ (floating_ip['ip'], server['addresses']))
+
self.create_and_add_security_group_to_server(server)
# check that we can SSH to the server before reboot
@@ -135,3 +146,21 @@
floating_ip['ip'], private_key=keypair['private_key'])
self.check_partitions()
+
+ # delete the floating IP, this should refresh the server addresses
+ self.compute_floating_ips_client.delete_floating_ip(floating_ip['id'])
+
+ def is_floating_ip_detached_from_server():
+ server_info = self.servers_client.show_server(
+ server['id'])['server']
+ address = self._get_floating_ip_in_server_addresses(
+ floating_ip, server_info)
+ return (not address)
+
+ if not test_utils.call_until_true(
+ is_floating_ip_detached_from_server,
+ CONF.compute.build_timeout,
+ CONF.compute.build_interval):
+ msg = ("Floating IP '%s' should not be in server addresses: %s" %
+ (floating_ip['ip'], server['addresses']))
+ raise exceptions.TimeoutException(msg)
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index a89147a..3390aff 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -50,28 +50,30 @@
cls.set_network_resources()
super(TestNetworkAdvancedServerOps, cls).setup_credentials()
- def _setup_network_and_servers(self):
- keypair = self.create_keypair()
+ def _setup_server(self, keypair):
security_groups = []
if test.is_extension_enabled('security-group', 'network'):
security_group = self._create_security_group()
security_groups = [{'name': security_group['name']}]
network, subnet, router = self.create_networks()
- public_network_id = CONF.network.public_network_id
- server_name = data_utils.rand_name('server')
+ server_name = data_utils.rand_name(self.__class__.__name__ + '-server')
server = self.create_server(
name=server_name,
networks=[{'uuid': network['id']}],
key_name=keypair['name'],
security_groups=security_groups,
wait_until='ACTIVE')
+ return server
+
+ def _setup_network(self, server, keypair):
+ public_network_id = CONF.network.public_network_id
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(
server, keypair, floating_ip)
- return server, keypair, floating_ip
+ return floating_ip
def _check_network_connectivity(self, server, keypair, floating_ip,
should_connect=True):
@@ -99,7 +101,9 @@
@test.stresstest(class_setup_per='process')
@test.services('compute', 'network')
def test_server_connectivity_stop_start(self):
- server, keypair, floating_ip = self._setup_network_and_servers()
+ keypair = self.create_keypair()
+ server = self._setup_server(keypair)
+ floating_ip = self._setup_network(server, keypair)
self.servers_client.stop_server(server['id'])
waiters.wait_for_server_status(self.servers_client, server['id'],
'SHUTOFF')
@@ -112,7 +116,9 @@
@test.idempotent_id('7b6860c2-afa3-4846-9522-adeb38dfbe08')
@test.services('compute', 'network')
def test_server_connectivity_reboot(self):
- server, keypair, floating_ip = self._setup_network_and_servers()
+ keypair = self.create_keypair()
+ server = self._setup_server(keypair)
+ floating_ip = self._setup_network(server, keypair)
self.servers_client.reboot_server(server['id'], type='SOFT')
self._wait_server_status_and_check_network_connectivity(
server, keypair, floating_ip)
@@ -120,7 +126,9 @@
@test.idempotent_id('88a529c2-1daa-4c85-9aec-d541ba3eb699')
@test.services('compute', 'network')
def test_server_connectivity_rebuild(self):
- server, keypair, floating_ip = self._setup_network_and_servers()
+ keypair = self.create_keypair()
+ server = self._setup_server(keypair)
+ floating_ip = self._setup_network(server, keypair)
image_ref_alt = CONF.compute.image_ref_alt
self.servers_client.rebuild_server(server['id'],
image_ref=image_ref_alt)
@@ -132,7 +140,9 @@
'Pause is not available.')
@test.services('compute', 'network')
def test_server_connectivity_pause_unpause(self):
- server, keypair, floating_ip = self._setup_network_and_servers()
+ keypair = self.create_keypair()
+ server = self._setup_server(keypair)
+ floating_ip = self._setup_network(server, keypair)
self.servers_client.pause_server(server['id'])
waiters.wait_for_server_status(self.servers_client, server['id'],
'PAUSED')
@@ -147,7 +157,9 @@
'Suspend is not available.')
@test.services('compute', 'network')
def test_server_connectivity_suspend_resume(self):
- server, keypair, floating_ip = self._setup_network_and_servers()
+ keypair = self.create_keypair()
+ server = self._setup_server(keypair)
+ floating_ip = self._setup_network(server, keypair)
self.servers_client.suspend_server(server['id'])
waiters.wait_for_server_status(self.servers_client, server['id'],
'SUSPENDED')
@@ -166,7 +178,9 @@
if resize_flavor == CONF.compute.flavor_ref:
msg = "Skipping test - flavor_ref and flavor_ref_alt are identical"
raise self.skipException(msg)
- server, keypair, floating_ip = self._setup_network_and_servers()
+ keypair = self.create_keypair()
+ server = self._setup_server(keypair)
+ floating_ip = self._setup_network(server, keypair)
self.servers_client.resize_server(server['id'],
flavor_ref=resize_flavor)
waiters.wait_for_server_status(self.servers_client, server['id'],
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 519dbec..a295b6a 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -473,11 +473,11 @@
def test_hotplug_nic(self):
"""Test hotplug network interface
- 1. create a new network, with no gateway (to prevent overwriting VM's
- gateway)
- 2. connect VM to new network
- 3. set static ip and bring new nic up
- 4. check VM can ping new network dhcp port
+ 1. Create a network and a VM.
+ 2. Check connectivity to the VM via a public network.
+ 3. Create a new network, with no gateway.
+ 4. Bring up a new interface
+ 5. check the VM reach the new network
"""
self._setup_network_and_servers()
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 86185c8..2c16be8 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log
+import testtools
from tempest import clients
from tempest.common.utils import data_utils
@@ -256,7 +257,7 @@
# and distributed routers; 'device_owner' is "" by default.
return port['device_owner'].startswith('network:router_interface')
- def _create_server(self, name, tenant, security_groups=None, **kwargs):
+ def _create_server(self, name, tenant, security_groups, **kwargs):
"""Creates a server and assigns it to security group.
If multi-host is enabled, Ensures servers are created on different
@@ -264,8 +265,6 @@
as scheduler_hints on creation.
Validates servers are created as requested, using admin client.
"""
- if security_groups is None:
- security_groups = [tenant.security_groups['default']]
security_groups_names = [{'name': s['name']} for s in security_groups]
if self.multi_node:
kwargs["scheduler_hints"] = {'different_host': self.servers}
@@ -277,9 +276,10 @@
wait_until='ACTIVE',
clients=tenant.manager,
**kwargs)
- self.assertEqual(
- sorted([s['name'] for s in security_groups]),
- sorted([s['name'] for s in server['security_groups']]))
+ if 'security_groups' in server:
+ self.assertEqual(
+ sorted([s['name'] for s in security_groups]),
+ sorted([s['name'] for s in server['security_groups']]))
# Verify servers are on different compute nodes
if self.multi_node:
@@ -303,7 +303,8 @@
num=i
)
name = data_utils.rand_name(name)
- server = self._create_server(name, tenant)
+ server = self._create_server(name, tenant,
+ [tenant.security_groups['default']])
tenant.servers.append(server)
def _set_access_point(self, tenant):
@@ -326,11 +327,12 @@
client=tenant.manager.floating_ips_client)
self.floating_ips.setdefault(server['id'], floating_ip)
- def _create_tenant_network(self, tenant):
+ def _create_tenant_network(self, tenant, port_security_enabled=True):
network, subnet, router = self.create_networks(
networks_client=tenant.manager.networks_client,
routers_client=tenant.manager.routers_client,
- subnets_client=tenant.manager.subnets_client)
+ subnets_client=tenant.manager.subnets_client,
+ port_security_enabled=port_security_enabled)
tenant.set_network(network, subnet, router)
def _deploy_tenant(self, tenant_or_id):
@@ -533,7 +535,8 @@
tenant=new_tenant.creds.tenant_name
)
name = data_utils.rand_name(name)
- server = self._create_server(name, new_tenant)
+ server = self._create_server(name, new_tenant,
+ [new_tenant.security_groups['default']])
# Check connectivity failure with default security group
try:
@@ -599,7 +602,8 @@
tenant=new_tenant.creds.tenant_name
)
name = data_utils.rand_name(name)
- server = self._create_server(name, new_tenant)
+ server = self._create_server(name, new_tenant,
+ [new_tenant.security_groups['default']])
access_point_ssh = self._connect_to_access_point(new_tenant)
server_id = server['id']
@@ -624,3 +628,32 @@
for tenant in self.tenants.values():
self._log_console_output(servers=tenant.servers)
raise
+
+ @test.requires_ext(service='network', extension='port-security')
+ @test.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
+ @testtools.skipUnless(
+ CONF.compute_feature_enabled.allow_port_security_disabled,
+ 'Port security must be enabled.')
+ # TODO(mriedem): We shouldn't actually need to check this since neutron
+ # disables the port_security extension by default, but the problem is nova
+ # assumes port_security_enabled=True if it's not set on the network
+ # resource, which will mean nova may attempt to apply a security group on
+ # a port on that network which would fail. This is really a bug in nova.
+ @testtools.skipUnless(
+ CONF.network_feature_enabled.port_security,
+ 'Port security must be enabled.')
+ @test.services('compute', 'network')
+ def test_boot_into_disabled_port_security_network_without_secgroup(self):
+ tenant = self.primary_tenant
+ self._create_tenant_network(tenant, port_security_enabled=False)
+ self.assertFalse(tenant.network['port_security_enabled'])
+ name = data_utils.rand_name('server-smoke')
+ sec_groups = []
+ server = self._create_server(name, tenant, sec_groups)
+ server_id = server['id']
+ ports = self._list_ports(device_id=server_id)
+ self.assertEqual(1, len(ports))
+ for port in ports:
+ self.assertEmpty(port['security_groups'],
+ "Neutron shouldn't even use it's default sec "
+ "group.")
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index 0cf72c3..b323d2a 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -42,7 +42,6 @@
# this is needed so that we can use the availability_zone:host
# scheduler hint, which is admin_only by default
cls.servers_client = cls.admin_manager.servers_client
- super(TestServerMultinode, cls).resource_setup()
@test.idempotent_id('9cecbe35-b9d4-48da-a37e-7ce70aa43d30')
@test.attr(type='smoke')
diff --git a/tempest/services/identity/__init__.py b/tempest/services/identity/__init__.py
index 0e24926..53c223f 100644
--- a/tempest/services/identity/__init__.py
+++ b/tempest/services/identity/__init__.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations under
# the License.
-from tempest.services.identity import v2
+from tempest.lib.services.identity import v2
from tempest.services.identity import v3
__all__ = ['v2', 'v3']
diff --git a/tempest/services/identity/v2/__init__.py b/tempest/services/identity/v2/__init__.py
deleted file mode 100644
index b7d3c74..0000000
--- a/tempest/services/identity/v2/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
-# use this file except in compliance with the License. You may obtain a copy of
-# the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations under
-# the License.
-
-from tempest.lib.services.identity.v2.endpoints_client import EndpointsClient
-from tempest.lib.services.identity.v2.identity_client import IdentityClient
-from tempest.lib.services.identity.v2.roles_client import RolesClient
-from tempest.lib.services.identity.v2.services_client import ServicesClient
-from tempest.lib.services.identity.v2.tenants_client import TenantsClient
-from tempest.lib.services.identity.v2.token_client import TokenClient
-from tempest.lib.services.identity.v2.users_client import UsersClient
-
-__all__ = ['EndpointsClient', 'IdentityClient', 'RolesClient',
- 'ServicesClient', 'TenantsClient', 'TokenClient', 'UsersClient']
diff --git a/tempest/services/identity/v2/json/__init__.py b/tempest/services/identity/v2/json/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/identity/v2/json/__init__.py
+++ /dev/null
diff --git a/tempest/services/identity/v3/__init__.py b/tempest/services/identity/v3/__init__.py
index c77c78d..9b40b77 100644
--- a/tempest/services/identity/v3/__init__.py
+++ b/tempest/services/identity/v3/__init__.py
@@ -12,22 +12,27 @@
# License for the specific language governing permissions and limitations under
# the License.
+from tempest.lib.services.identity.v3.credentials_client import \
+ CredentialsClient
from tempest.lib.services.identity.v3.endpoints_client import EndPointsClient
+from tempest.lib.services.identity.v3.groups_client import GroupsClient
+from tempest.lib.services.identity.v3.identity_client import IdentityClient
+from tempest.lib.services.identity.v3.inherited_roles_client import \
+ InheritedRolesClient
from tempest.lib.services.identity.v3.policies_client import PoliciesClient
from tempest.lib.services.identity.v3.projects_client import ProjectsClient
from tempest.lib.services.identity.v3.regions_client import RegionsClient
+from tempest.lib.services.identity.v3.roles_client import RolesClient
from tempest.lib.services.identity.v3.services_client import ServicesClient
from tempest.lib.services.identity.v3.token_client import V3TokenClient
-from tempest.services.identity.v3.json.credentials_client import \
- CredentialsClient
+from tempest.lib.services.identity.v3.trusts_client import TrustsClient
+from tempest.lib.services.identity.v3.users_client import UsersClient
from tempest.services.identity.v3.json.domains_client import DomainsClient
-from tempest.services.identity.v3.json.groups_client import GroupsClient
-from tempest.services.identity.v3.json.identity_client import IdentityClient
-from tempest.services.identity.v3.json.roles_client import RolesClient
-from tempest.services.identity.v3.json.trusts_client import TrustsClient
-from tempest.services.identity.v3.json.users_clients import UsersClient
+from tempest.services.identity.v3.json.role_assignments_client import \
+ RoleAssignmentsClient
-__all__ = ['EndPointsClient', 'PoliciesClient', 'ProjectsClient',
- 'RegionsClient', 'ServicesClient', 'V3TokenClient',
- 'CredentialsClient', 'DomainsClient', 'GroupsClient',
- 'IdentityClient', 'RolesClient', 'TrustsClient', 'UsersClient', ]
+__all__ = ['CredentialsClient', 'EndPointsClient', 'GroupsClient',
+ 'IdentityClient', 'InheritedRolesClient', 'PoliciesClient',
+ 'ProjectsClient', 'RegionsClient', 'RoleAssignmentsClient',
+ 'RolesClient', 'ServicesClient', 'V3TokenClient', 'TrustsClient',
+ 'UsersClient', 'DomainsClient', ]
diff --git a/tempest/services/identity/v3/json/role_assignments_client.py b/tempest/services/identity/v3/json/role_assignments_client.py
new file mode 100644
index 0000000..9fd7736
--- /dev/null
+++ b/tempest/services/identity/v3/json/role_assignments_client.py
@@ -0,0 +1,31 @@
+# Copyright 2016 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_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class RoleAssignmentsClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def list_user_project_effective_assignments(
+ self, project_id, user_id):
+ """List the effective role assignments for a user in a project."""
+ resp, body = self.get(
+ "role_assignments?scope.project.id=%s&user.id=%s&effective" %
+ (project_id, user_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/roles_client.py b/tempest/services/identity/v3/json/roles_client.py
deleted file mode 100644
index 3f165fa..0000000
--- a/tempest/services/identity/v3/json/roles_client.py
+++ /dev/null
@@ -1,320 +0,0 @@
-# Copyright 2016 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_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.lib.common import rest_client
-
-
-class RolesClient(rest_client.RestClient):
- api_version = "v3"
-
- def create_role(self, **kwargs):
- """Create a Role.
-
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createRole
- """
- post_body = json.dumps({'role': kwargs})
- resp, body = self.post('roles', post_body)
- self.expected_success(201, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def show_role(self, role_id):
- """GET a Role."""
- resp, body = self.get('roles/%s' % role_id)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def list_roles(self, **params):
- """Get the list of Roles."""
-
- url = 'roles'
- if params:
- url += '?%s' % urllib.urlencode(params)
- resp, body = self.get(url)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def update_role(self, role_id, **kwargs):
- """Update a Role.
-
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateRole
- """
- post_body = json.dumps({'role': kwargs})
- resp, body = self.patch('roles/%s' % role_id, post_body)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def delete_role(self, role_id):
- """Delete a role."""
- resp, body = self.delete('roles/%s' % role_id)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def create_user_role_on_project(self, project_id, user_id, role_id):
- """Add roles to a user on a project."""
- resp, body = self.put('projects/%s/users/%s/roles/%s' %
- (project_id, user_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def create_user_role_on_domain(self, domain_id, user_id, role_id):
- """Add roles to a user on a domain."""
- resp, body = self.put('domains/%s/users/%s/roles/%s' %
- (domain_id, user_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def list_user_roles_on_project(self, project_id, user_id):
- """list roles of a user on a project."""
- resp, body = self.get('projects/%s/users/%s/roles' %
- (project_id, user_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def list_user_roles_on_domain(self, domain_id, user_id):
- """list roles of a user on a domain."""
- resp, body = self.get('domains/%s/users/%s/roles' %
- (domain_id, user_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def delete_role_from_user_on_project(self, project_id, user_id, role_id):
- """Delete role of a user on a project."""
- resp, body = self.delete('projects/%s/users/%s/roles/%s' %
- (project_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def delete_role_from_user_on_domain(self, domain_id, user_id, role_id):
- """Delete role of a user on a domain."""
- resp, body = self.delete('domains/%s/users/%s/roles/%s' %
- (domain_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def check_user_role_existence_on_project(self, project_id,
- user_id, role_id):
- """Check role of a user on a project."""
- resp, body = self.head('projects/%s/users/%s/roles/%s' %
- (project_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
-
- def check_user_role_existence_on_domain(self, domain_id,
- user_id, role_id):
- """Check role of a user on a domain."""
- resp, body = self.head('domains/%s/users/%s/roles/%s' %
- (domain_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
-
- def create_group_role_on_project(self, project_id, group_id, role_id):
- """Add roles to a group on a project."""
- resp, body = self.put('projects/%s/groups/%s/roles/%s' %
- (project_id, group_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def create_group_role_on_domain(self, domain_id, group_id, role_id):
- """Add roles to a group on a domain."""
- resp, body = self.put('domains/%s/groups/%s/roles/%s' %
- (domain_id, group_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def list_group_roles_on_project(self, project_id, group_id):
- """list roles of a group on a project."""
- resp, body = self.get('projects/%s/groups/%s/roles' %
- (project_id, group_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def list_group_roles_on_domain(self, domain_id, group_id):
- """list roles of a group on a domain."""
- resp, body = self.get('domains/%s/groups/%s/roles' %
- (domain_id, group_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def delete_role_from_group_on_project(self, project_id, group_id, role_id):
- """Delete role of a group on a project."""
- resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
- (project_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def delete_role_from_group_on_domain(self, domain_id, group_id, role_id):
- """Delete role of a group on a domain."""
- resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
- (domain_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def check_role_from_group_on_project_existence(self, project_id,
- group_id, role_id):
- """Check role of a group on a project."""
- resp, body = self.head('projects/%s/groups/%s/roles/%s' %
- (project_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
-
- def check_role_from_group_on_domain_existence(self, domain_id,
- group_id, role_id):
- """Check role of a group on a domain."""
- resp, body = self.head('domains/%s/groups/%s/roles/%s' %
- (domain_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
-
- def assign_inherited_role_on_domains_user(
- self, domain_id, user_id, role_id):
- """Assigns a role to a user on projects owned by a domain."""
- resp, body = self.put(
- "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
- % (domain_id, user_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def revoke_inherited_role_from_user_on_domain(
- self, domain_id, user_id, role_id):
- """Revokes an inherited project role from a user on a domain."""
- resp, body = self.delete(
- "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
- % (domain_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def list_inherited_project_role_for_user_on_domain(
- self, domain_id, user_id):
- """Lists the inherited project roles on a domain for a user."""
- resp, body = self.get(
- "OS-INHERIT/domains/%s/users/%s/roles/inherited_to_projects"
- % (domain_id, user_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def check_user_inherited_project_role_on_domain(
- self, domain_id, user_id, role_id):
- """Checks whether a user has an inherited project role on a domain."""
- resp, body = self.head(
- "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
- % (domain_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
-
- def assign_inherited_role_on_domains_group(
- self, domain_id, group_id, role_id):
- """Assigns a role to a group on projects owned by a domain."""
- resp, body = self.put(
- "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
- % (domain_id, group_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def revoke_inherited_role_from_group_on_domain(
- self, domain_id, group_id, role_id):
- """Revokes an inherited project role from a group on a domain."""
- resp, body = self.delete(
- "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
- % (domain_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def list_inherited_project_role_for_group_on_domain(
- self, domain_id, group_id):
- """Lists the inherited project roles on a domain for a group."""
- resp, body = self.get(
- "OS-INHERIT/domains/%s/groups/%s/roles/inherited_to_projects"
- % (domain_id, group_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return rest_client.ResponseBody(resp, body)
-
- def check_group_inherited_project_role_on_domain(
- self, domain_id, group_id, role_id):
- """Checks whether a group has an inherited project role on a domain."""
- resp, body = self.head(
- "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
- % (domain_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
-
- def assign_inherited_role_on_projects_user(
- self, project_id, user_id, role_id):
- """Assigns a role to a user on projects in a subtree."""
- resp, body = self.put(
- "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
- % (project_id, user_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def revoke_inherited_role_from_user_on_project(
- self, project_id, user_id, role_id):
- """Revokes an inherited role from a user on a project."""
- resp, body = self.delete(
- "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
- % (project_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def check_user_has_flag_on_inherited_to_project(
- self, project_id, user_id, role_id):
- """Checks whether a user has a role assignment"""
- """with the inherited_to_projects flag on a project."""
- resp, body = self.head(
- "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
- % (project_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
-
- def assign_inherited_role_on_projects_group(
- self, project_id, group_id, role_id):
- """Assigns a role to a group on projects in a subtree."""
- resp, body = self.put(
- "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
- % (project_id, group_id, role_id), None)
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def revoke_inherited_role_from_group_on_project(
- self, project_id, group_id, role_id):
- """Revokes an inherited role from a group on a project."""
- resp, body = self.delete(
- "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
- % (project_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def check_group_has_flag_on_inherited_to_project(
- self, project_id, group_id, role_id):
- """Checks whether a group has a role assignment"""
- """with the inherited_to_projects flag on a project."""
- resp, body = self.head(
- "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
- % (project_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp)
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index a7db30e..ec36fb7 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -195,7 +195,6 @@
# Read the 100 status prior to sending the data
response = conn.response_class(conn.sock,
- strict=conn.strict,
method=conn._method)
_, status, _ = response._read_status()
diff --git a/tempest/services/volume/base/admin/__init__.py b/tempest/services/volume/base/admin/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/volume/base/admin/__init__.py
+++ /dev/null
diff --git a/tempest/services/volume/base/base_backups_client.py b/tempest/services/volume/base/base_backups_client.py
index a57e628..1b35feb 100644
--- a/tempest/services/volume/base/base_backups_client.py
+++ b/tempest/services/volume/base/base_backups_client.py
@@ -13,11 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import time
-
from oslo_serialization import jsonutils as json
-from tempest import exceptions
from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
@@ -96,26 +93,6 @@
self.expected_success(202, resp.status)
return rest_client.ResponseBody(resp, body)
- def wait_for_backup_status(self, backup_id, status):
- """Waits for a Backup to reach a given status."""
- body = self.show_backup(backup_id)['backup']
- backup_status = body['status']
- start = int(time.time())
-
- while backup_status != status:
- time.sleep(self.build_interval)
- body = self.show_backup(backup_id)['backup']
- backup_status = body['status']
- if backup_status == 'error' and backup_status != status:
- raise exceptions.VolumeBackupException(backup_id=backup_id)
-
- if int(time.time()) - start >= self.build_timeout:
- message = ('Volume backup %s failed to reach %s status '
- '(current %s) within the required time (%s s).' %
- (backup_id, status, backup_status,
- self.build_timeout))
- raise exceptions.TimeoutException(message)
-
def is_resource_deleted(self, id):
try:
self.show_backup(id)
diff --git a/tempest/services/volume/base/base_volumes_client.py b/tempest/services/volume/base/base_volumes_client.py
index 308f818..1cb1ef5 100755
--- a/tempest/services/volume/base/base_volumes_client.py
+++ b/tempest/services/volume/base/base_volumes_client.py
@@ -52,34 +52,6 @@
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, body)
- def show_pools(self, detail=False):
- """List all the volumes pools (hosts).
-
- Output params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#listPools
- """
- url = 'scheduler-stats/get_pools'
- if detail:
- url += '?detail=True'
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def show_backend_capabilities(self, host):
- """Shows capabilities for a storage back end.
-
- Output params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html
- #showBackendCapabilities
- """
- url = 'capabilities/%s' % host
- resp, body = self.get(url)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
-
def show_volume(self, volume_id):
"""Returns the details of a single volume."""
url = "volumes/%s" % volume_id
@@ -316,28 +288,6 @@
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, body)
- def update_volume_image_metadata(self, volume_id, **kwargs):
- """Update image metadata for the volume.
-
- Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html
- #setVolumeimagemetadata
- """
- post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
- url = "volumes/%s/action" % (volume_id)
- resp, body = self.post(url, post_body)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def delete_volume_image_metadata(self, volume_id, key_name):
- """Delete image metadata item for the volume."""
- post_body = json.dumps({'os-unset_image_metadata': {'key': key_name}})
- url = "volumes/%s/action" % (volume_id)
- resp, body = self.post(url, post_body)
- self.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
-
def retype_volume(self, volume_id, **kwargs):
"""Updates volume with new volume type."""
post_body = json.dumps({'os-retype': kwargs})
diff --git a/tempest/services/volume/v1/__init__.py b/tempest/services/volume/v1/__init__.py
index 72868bc..e386faf 100644
--- a/tempest/services/volume/v1/__init__.py
+++ b/tempest/services/volume/v1/__init__.py
@@ -14,19 +14,20 @@
from tempest.lib.services.volume.v1.availability_zone_client import \
AvailabilityZoneClient
+from tempest.lib.services.volume.v1.encryption_types_client import \
+ EncryptionTypesClient
from tempest.lib.services.volume.v1.extensions_client import ExtensionsClient
from tempest.lib.services.volume.v1.hosts_client import HostsClient
+from tempest.lib.services.volume.v1.qos_client import QosSpecsClient
from tempest.lib.services.volume.v1.quotas_client import QuotasClient
from tempest.lib.services.volume.v1.services_client import ServicesClient
-from tempest.services.volume.v1.json.admin.types_client import TypesClient
+from tempest.lib.services.volume.v1.snapshots_client import SnapshotsClient
+from tempest.lib.services.volume.v1.types_client import TypesClient
from tempest.services.volume.v1.json.backups_client import BackupsClient
-from tempest.services.volume.v1.json.encryption_types_client import \
- EncryptionTypesClient
-from tempest.services.volume.v1.json.qos_client import QosSpecsClient
-from tempest.services.volume.v1.json.snapshots_client import SnapshotsClient
from tempest.services.volume.v1.json.volumes_client import VolumesClient
-__all__ = ['HostsClient', 'QuotasClient', 'ServicesClient', 'TypesClient',
- 'AvailabilityZoneClient', 'BackupsClient', 'ExtensionsClient',
- 'QosSpecsClient', 'SnapshotsClient', 'VolumesClient',
- 'EncryptionTypesClient']
+__all__ = ['AvailabilityZoneClient', 'EncryptionTypesClient',
+ 'ExtensionsClient', 'HostsClient', 'QuotasClient',
+ 'QosSpecsClient', 'ServicesClient',
+ 'SnapshotsClient', 'TypesClient', 'BackupsClient',
+ 'VolumesClient', ]
diff --git a/tempest/services/volume/v1/json/admin/__init__.py b/tempest/services/volume/v1/json/admin/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/volume/v1/json/admin/__init__.py
+++ /dev/null
diff --git a/tempest/services/volume/v1/json/admin/types_client.py b/tempest/services/volume/v1/json/admin/types_client.py
deleted file mode 100644
index 0e84296..0000000
--- a/tempest/services/volume/v1/json/admin/types_client.py
+++ /dev/null
@@ -1,20 +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 tempest.services.volume.base.admin import base_types_client
-
-
-class TypesClient(base_types_client.BaseTypesClient):
- """Volume V1 Volume Types client"""
diff --git a/tempest/services/volume/v1/json/qos_client.py b/tempest/services/volume/v1/json/qos_client.py
deleted file mode 100644
index b2b2195..0000000
--- a/tempest/services/volume/v1/json/qos_client.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.volume.base import base_qos_client
-
-
-class QosSpecsClient(base_qos_client.BaseQosSpecsClient):
- """Volume V1 QoS client."""
diff --git a/tempest/services/volume/v1/json/snapshots_client.py b/tempest/services/volume/v1/json/snapshots_client.py
deleted file mode 100644
index b039c2b..0000000
--- a/tempest/services/volume/v1/json/snapshots_client.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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.volume.base import base_snapshots_client
-
-
-class SnapshotsClient(base_snapshots_client.BaseSnapshotsClient):
- """Client class to send CRUD Volume V1 API requests."""
diff --git a/tempest/services/volume/v2/__init__.py b/tempest/services/volume/v2/__init__.py
index 4afcc29..fcc34f9 100644
--- a/tempest/services/volume/v2/__init__.py
+++ b/tempest/services/volume/v2/__init__.py
@@ -14,19 +14,19 @@
from tempest.lib.services.volume.v2.availability_zone_client import \
AvailabilityZoneClient
+from tempest.lib.services.volume.v2.encryption_types_client import \
+ EncryptionTypesClient
from tempest.lib.services.volume.v2.extensions_client import ExtensionsClient
from tempest.lib.services.volume.v2.hosts_client import HostsClient
+from tempest.lib.services.volume.v2.qos_client import QosSpecsClient
from tempest.lib.services.volume.v2.quotas_client import QuotasClient
from tempest.lib.services.volume.v2.services_client import ServicesClient
-from tempest.services.volume.v2.json.admin.types_client import TypesClient
+from tempest.lib.services.volume.v2.snapshots_client import SnapshotsClient
+from tempest.lib.services.volume.v2.types_client import TypesClient
from tempest.services.volume.v2.json.backups_client import BackupsClient
-from tempest.services.volume.v2.json.encryption_types_client import \
- EncryptionTypesClient
-from tempest.services.volume.v2.json.qos_client import QosSpecsClient
-from tempest.services.volume.v2.json.snapshots_client import SnapshotsClient
from tempest.services.volume.v2.json.volumes_client import VolumesClient
-__all__ = ['HostsClient', 'QuotasClient', 'ServicesClient', 'TypesClient',
- 'AvailabilityZoneClient', 'BackupsClient', 'ExtensionsClient',
- 'QosSpecsClient', 'SnapshotsClient', 'VolumesClient',
- 'EncryptionTypesClient']
+__all__ = ['AvailabilityZoneClient', 'EncryptionTypesClient',
+ 'ExtensionsClient', 'HostsClient', 'QosSpecsClient',
+ 'QuotasClient', 'ServicesClient', 'SnapshotsClient',
+ 'TypesClient', 'BackupsClient', 'VolumesClient', ]
diff --git a/tempest/services/volume/v2/json/admin/__init__.py b/tempest/services/volume/v2/json/admin/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/volume/v2/json/admin/__init__.py
+++ /dev/null
diff --git a/tempest/services/volume/v2/json/admin/types_client.py b/tempest/services/volume/v2/json/admin/types_client.py
deleted file mode 100644
index f76e8dc..0000000
--- a/tempest/services/volume/v2/json/admin/types_client.py
+++ /dev/null
@@ -1,63 +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.lib.common import rest_client
-from tempest.services.volume.base.admin import base_types_client
-
-
-class TypesClient(base_types_client.BaseTypesClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
-
- def add_type_access(self, volume_type_id, **kwargs):
- """Adds volume type access for the given project.
-
- Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html
- #createVolumeTypeAccessExt
- """
- post_body = json.dumps({'addProjectAccess': kwargs})
- url = 'types/%s/action' % volume_type_id
- resp, body = self.post(url, post_body)
- self.expected_success(202, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def remove_type_access(self, volume_type_id, **kwargs):
- """Removes volume type access for the given project.
-
- Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html
- #removeVolumeTypeAccessExt
- """
- post_body = json.dumps({'removeProjectAccess': kwargs})
- url = 'types/%s/action' % volume_type_id
- resp, body = self.post(url, post_body)
- self.expected_success(202, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def list_type_access(self, volume_type_id):
- """Print access information about the given volume type.
-
- Available params: see http://developer.openstack.org/
- api-ref-blockstorage-v2.html#
- listVolumeTypeAccessExt
- """
- url = 'types/%s/os-volume-type-access' % volume_type_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/v2/json/qos_client.py b/tempest/services/volume/v2/json/qos_client.py
deleted file mode 100644
index 3c0f74f..0000000
--- a/tempest/services/volume/v2/json/qos_client.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.volume.base import base_qos_client
-
-
-class QosSpecsClient(base_qos_client.BaseQosSpecsClient):
- api_version = "v2"
diff --git a/tempest/services/volume/v2/json/snapshots_client.py b/tempest/services/volume/v2/json/snapshots_client.py
deleted file mode 100644
index a2d415f..0000000
--- a/tempest/services/volume/v2/json/snapshots_client.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.volume.base import base_snapshots_client
-
-
-class SnapshotsClient(base_snapshots_client.BaseSnapshotsClient):
- """Client class to send CRUD Volume V2 API requests."""
- api_version = "v2"
- create_resp = 202
diff --git a/tempest/services/volume/v2/json/volumes_client.py b/tempest/services/volume/v2/json/volumes_client.py
index b7d9dfb..f21a1a3 100644
--- a/tempest/services/volume/v2/json/volumes_client.py
+++ b/tempest/services/volume/v2/json/volumes_client.py
@@ -13,6 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
from tempest.services.volume.base import base_volumes_client
@@ -20,3 +23,49 @@
"""Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
create_resp = 202
+
+ def update_volume_image_metadata(self, volume_id, **kwargs):
+ """Update image metadata for the volume.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-blockstorage-v2.html
+ #setVolumeimagemetadata
+ """
+ post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
+ url = "volumes/%s/action" % (volume_id)
+ resp, body = self.post(url, post_body)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_volume_image_metadata(self, volume_id, key_name):
+ """Delete image metadata item for the volume."""
+ post_body = json.dumps({'os-unset_image_metadata': {'key': key_name}})
+ url = "volumes/%s/action" % (volume_id)
+ resp, body = self.post(url, post_body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_pools(self, detail=False):
+ # List all the volumes pools (hosts)
+ url = 'scheduler-stats/get_pools'
+ if detail:
+ url += '?detail=True'
+
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_backend_capabilities(self, host):
+ """Shows capabilities for a storage back end.
+
+ Output params: see http://developer.openstack.org/
+ api-ref-blockstorage-v2.html
+ #showBackendCapabilities
+ """
+ url = 'capabilities/%s' % host
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/stress/actions/server_create_destroy.py b/tempest/stress/actions/server_create_destroy.py
index 44b6f62..183bc6c 100644
--- a/tempest/stress/actions/server_create_destroy.py
+++ b/tempest/stress/actions/server_create_destroy.py
@@ -27,7 +27,7 @@
self.flavor = CONF.compute.flavor_ref
def run(self):
- name = data_utils.rand_name("instance")
+ name = data_utils.rand_name(self.__class__.__name__ + "-instance")
self.logger.info("creating %s" % name)
server = self.manager.servers_client.create_server(
name=name, imageRef=self.image, flavorRef=self.flavor)['server']
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index c9a4d38..845b4a7 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -70,7 +70,8 @@
self.server_id, self.floating['ip'])
def _create_vm(self):
- self.name = name = data_utils.rand_name("instance")
+ self.name = name = data_utils.rand_name(
+ self.__class__.__name__ + "-instance")
servers_client = self.manager.servers_client
self.logger.info("creating %s" % name)
vm_args = self.vm_extra_args.copy()
@@ -92,7 +93,7 @@
def _create_sec_group(self):
sec_grp_cli = self.manager.compute_security_groups_client
- s_name = data_utils.rand_name('sec_grp')
+ s_name = data_utils.rand_name(self.__class__.__name__ + '-sec_grp')
s_description = data_utils.rand_name('desc')
self.sec_grp = sec_grp_cli.create_security_group(
name=s_name, description=s_description)['security_group']
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index e06c364..5fc006e 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -27,7 +27,7 @@
def run(self):
# Step 1: create volume
- name = data_utils.rand_name("volume")
+ name = data_utils.rand_name(self.__class__.__name__ + "-volume")
self.logger.info("creating volume: %s" % name)
volume = self.manager.volumes_client.create_volume(
display_name=name, size=CONF.volume.volume_size)['volume']
@@ -36,7 +36,7 @@
self.logger.info("created volume: %s" % volume['id'])
# Step 2: create vm instance
- vm_name = data_utils.rand_name("instance")
+ vm_name = data_utils.rand_name(self.__class__.__name__ + "-instance")
self.logger.info("creating vm: %s" % vm_name)
server = self.manager.servers_client.create_server(
name=vm_name, imageRef=self.image, flavorRef=self.flavor)['server']
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index 743cb11..4fbb851 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -33,7 +33,8 @@
self.manager.keypairs_client.delete_keypair(self.key['name'])
def _create_vm(self):
- self.name = name = data_utils.rand_name("instance")
+ self.name = name = data_utils.rand_name(
+ self.__class__.__name__ + "-instance")
servers_client = self.manager.servers_client
self.logger.info("creating %s" % name)
vm_args = self.vm_extra_args.copy()
@@ -55,7 +56,7 @@
def _create_sec_group(self):
sec_grp_cli = self.manager.compute_security_groups_client
- s_name = data_utils.rand_name('sec_grp')
+ s_name = data_utils.rand_name(self.__class__.__name__ + '-sec_grp')
s_description = data_utils.rand_name('desc')
self.sec_grp = sec_grp_cli.create_security_group(
name=s_name, description=s_description)['security_group']
@@ -81,7 +82,7 @@
self.logger.info("Deleted Floating IP %s", str(self.floating['ip']))
def _create_volume(self):
- name = data_utils.rand_name("volume")
+ name = data_utils.rand_name(self.__class__.__name__ + "-volume")
self.logger.info("creating volume: %s" % name)
volumes_client = self.manager.volumes_client
self.volume = volumes_client.create_volume(
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 925d765..1e33e88 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -20,8 +20,6 @@
from oslo_log import log as logging
from oslo_utils import importutils
import six
-from six import moves
-
from tempest import clients
from tempest.common import cred_client
@@ -142,7 +140,7 @@
manager = admin_manager
else:
raise NotImplemented('Non admin tests are not supported')
- for p_number in moves.xrange(test.get('threads', default_thread_num)):
+ for p_number in range(test.get('threads', default_thread_num)):
if test.get('use_isolated_tenants', False):
username = data_utils.rand_name("stress_user")
tenant_name = data_utils.rand_name("stress_tenant")
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
index 2844371..79510be 100644
--- a/tempest/tests/cmd/test_tempest_init.py
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -137,3 +137,18 @@
self.assertTrue(os.path.isfile(fake_file_moved))
self.assertTrue(os.path.isfile(local_conf_file))
self.assertTrue(os.path.isfile(local_testr_conf))
+
+ def test_take_action_fails(self):
+ class ParsedArgs(object):
+ workspace_dir = self.useFixture(fixtures.TempDir()).path
+ workspace_path = os.path.join(workspace_dir, 'workspace.yaml')
+ name = 'test'
+ dir_base = self.useFixture(fixtures.TempDir()).path
+ dir = os.path.join(dir_base, 'foo', 'bar')
+ config_dir = self.useFixture(fixtures.TempDir()).path
+ show_global_dir = False
+ pa = ParsedArgs()
+ init_cmd = init.TempestInit(None, None)
+ self.assertRaises(OSError, init_cmd.take_action, pa)
+ # one more trying should be a same error not "workspace already exists"
+ self.assertRaises(OSError, init_cmd.take_action, pa)
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index d74734e..0033d4e 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -28,14 +28,15 @@
v2_tenants_client
from tempest.lib.services.identity.v2 import token_client as v2_token_client
from tempest.lib.services.identity.v2 import users_client as v2_users_client
+from tempest.lib.services.identity.v3 import identity_client as v3_iden_client
from tempest.lib.services.identity.v3 import projects_client as \
v3_projects_client
+from tempest.lib.services.identity.v3 import roles_client as v3_roles_client
from tempest.lib.services.identity.v3 import token_client as v3_token_client
+from tempest.lib.services.identity.v3 import users_client as \
+ v3_users_client
from tempest.lib.services.network import routers_client
from tempest.services.identity.v3.json import domains_client
-from tempest.services.identity.v3.json import identity_client as v3_iden_client
-from tempest.services.identity.v3.json import roles_client as v3_roles_client
-from tempest.services.identity.v3.json import users_clients as v3_users_client
from tempest.tests import base
from tempest.tests import fake_config
from tempest.tests.lib import fake_http
diff --git a/tempest/tests/fake_auth_provider.py b/tempest/tests/fake_auth_provider.py
deleted file mode 100644
index 769f6a6..0000000
--- a/tempest/tests/fake_auth_provider.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2014 Hewlett-Packard Development Company, L.P.
-# 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.
-
-
-class FakeAuthProvider(object):
-
- def auth_request(self, method, url, headers=None, body=None, filters=None):
- return url, headers, body
-
- def get_token(self):
- return "faketoken"
-
- def base_url(self, filters, auth_data=None):
- return "https://example.com"
diff --git a/tempest/tests/lib/common/utils/test_data_utils.py b/tempest/tests/lib/common/utils/test_data_utils.py
index 94a4847..4446e5c 100644
--- a/tempest/tests/lib/common/utils/test_data_utils.py
+++ b/tempest/tests/lib/common/utils/test_data_utils.py
@@ -125,13 +125,13 @@
def test_random_bytes(self):
actual = data_utils.random_bytes() # default size=1024
- self.assertIsInstance(actual, str)
- self.assertRegex(actual, "^[\x00-\xFF]{1024}")
+ self.assertIsInstance(actual, bytes)
+ self.assertEqual(1024, len(actual))
actual2 = data_utils.random_bytes()
self.assertNotEqual(actual, actual2)
actual = data_utils.random_bytes(size=2048)
- self.assertRegex(actual, "^[\x00-\xFF]{2048}")
+ self.assertEqual(2048, len(actual))
def test_get_ipv6_addr_by_EUI64(self):
actual = data_utils.get_ipv6_addr_by_EUI64('2001:db8::',
diff --git a/tempest/tests/lib/fake_auth_provider.py b/tempest/tests/lib/fake_auth_provider.py
index fa8ab47..e4582f8 100644
--- a/tempest/tests/lib/fake_auth_provider.py
+++ b/tempest/tests/lib/fake_auth_provider.py
@@ -27,6 +27,9 @@
def base_url(self, filters, auth_data=None):
return self.fake_base_url or "https://example.com"
+ def get_token(self):
+ return "faketoken"
+
class FakeCredentials(object):
diff --git a/tempest/tests/lib/services/identity/v3/test_credentials_client.py b/tempest/tests/lib/services/identity/v3/test_credentials_client.py
new file mode 100644
index 0000000..29d7496
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_credentials_client.py
@@ -0,0 +1,179 @@
+# Copyright 2016 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.identity.v3 import credentials_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestCredentialsClient(base.BaseServiceTest):
+ FAKE_CREATE_CREDENTIAL = {
+ "credential": {
+ "blob": "{\"access\":\"181920\",\"secret\":\"secretKey\"}",
+ "project_id": "731fc6f265cd486d900f16e84c5cb594",
+ "type": "ec2",
+ "user_id": "bb5476fd12884539b41d5a88f838d773"
+ }
+ }
+
+ FAKE_INFO_CREDENTIAL = {
+ "credential": {
+ "user_id": "bb5476fd12884539b41d5a88f838d773",
+ "links": {
+ "self": "http://example.com/identity/v3/credentials/" +
+ "207e9b76935efc03804d3dd6ab52d22e9b22a0711e4" +
+ "ada4ff8b76165a07311d7"
+ },
+ "blob": "{\"access\": \"a42a27755ce6442596b049bd7dd8a563\"," +
+ " \"secret\": \"71faf1d40bb24c82b479b1c6fbbd9f0c\"}",
+ "project_id": "6e01855f345f4c59812999b5e459137d",
+ "type": "ec2",
+ "id": "207e9b76935efc03804d3dd6ab52d22e9b22a0711e4ada4f"
+ }
+ }
+
+ FAKE_LIST_CREDENTIALS = {
+ "credentials": [
+ {
+ "user_id": "bb5476fd12884539b41d5a88f838d773",
+ "links": {
+ "self": "http://example.com/identity/v3/credentials/" +
+ "207e9b76935efc03804d3dd6ab52d22e9b22a0711e4" +
+ "ada4ff8b76165a07311d7"
+ },
+ "blob": "{\"access\": \"a42a27755ce6442596b049bd7dd8a563\"," +
+ " \"secret\": \"71faf1d40bb24c82b479b1c6fbbd9f0c\"," +
+ " \"trust_id\": null}",
+ "project_id": "6e01855f345f4c59812999b5e459137d",
+ "type": "ec2",
+ "id": "207e9b76935efc03804d3dd6ab52d22e9b22a0711e4ada4f"
+ },
+ {
+ "user_id": "6f556708d04b4ea6bc72d7df2296b71a",
+ "links": {
+ "self": "http://example.com/identity/v3/credentials/" +
+ "2441494e52ab6d594a34d74586075cb299489bdd1e9" +
+ "389e3ab06467a4f460609"
+ },
+ "blob": "{\"access\": \"7da79ff0aa364e1396f067e352b9b79a\"," +
+ " \"secret\": \"7a18d68ba8834b799d396f3ff6f1e98c\"," +
+ " \"trust_id\": null}",
+ "project_id": "1a1d14690f3c4ec5bf5f321c5fde3c16",
+ "type": "ec2",
+ "id": "2441494e52ab6d594a34d74586075cb299489bdd1e9389e3"
+ },
+ {
+ "user_id": "c14107e65d5c4a7f8894fc4b3fc209ff",
+ "links": {
+ "self": "http://example.com/identity/v3/credentials/" +
+ "3397b204b5f04c495bcdc8f34c8a39996f280f91726" +
+ "58241873e15f070ec79d7"
+ },
+ "blob": "{\"access\": \"db9c58a558534a10a070110de4f9f20c\"," +
+ " \"secret\": \"973e790b88db447ba6f93bca02bc745b\"," +
+ " \"trust_id\": null}",
+ "project_id": "7396e43183db40dcbf40dd727637b548",
+ "type": "ec2",
+ "id": "3397b204b5f04c495bcdc8f34c8a39996f280f9172658241"
+ },
+ {
+ "user_id": "bb5476fd12884539b41d5a88f838d773",
+ "links": {
+ "self": "http://example.com/identity/v3/credentials/" +
+ "7ef4faa904ae7b8b4ddc7bad15b05ee359dad7d7a9b" +
+ "82861d4ad92fdbbb2eb4e"
+ },
+ "blob": "{\"access\": \"7d7559359b57419eb5f5f5dcd65ab57d\"," +
+ " \"secret\": \"570652bcf8c2483c86eb29e9734eed3c\"," +
+ " \"trust_id\": null}",
+ "project_id": "731fc6f265cd486d900f16e84c5cb594",
+ "type": "ec2",
+ "id": "7ef4faa904ae7b8b4ddc7bad15b05ee359dad7d7a9b82861"
+ },
+ ],
+ "links": {
+ "self": "http://example.com/identity/v3/credentials",
+ "previous": None,
+ "next": None
+ }
+ }
+
+ def setUp(self):
+ super(TestCredentialsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = credentials_client.CredentialsClient(fake_auth,
+ 'identity',
+ 'regionOne')
+
+ def _test_create_credential(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_credential,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_CREDENTIAL,
+ bytes_body, status=201)
+
+ def _test_show_credential(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_credential,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_INFO_CREDENTIAL,
+ bytes_body,
+ credential_id="207e9b76935efc03804d3dd6ab52d22e9b22a0711e4ada4f")
+
+ def _test_update_credential(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_credential,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_INFO_CREDENTIAL,
+ bytes_body,
+ credential_id="207e9b76935efc03804d3dd6ab52d22e9b22a0711e4ada4f")
+
+ def _test_list_credentials(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_credentials,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_CREDENTIALS,
+ bytes_body)
+
+ def test_create_credential_with_str_body(self):
+ self._test_create_credential()
+
+ def test_create_credential_with_bytes_body(self):
+ self._test_create_credential(bytes_body=True)
+
+ def test_show_credential_with_str_body(self):
+ self._test_show_credential()
+
+ def test_show_credential_with_bytes_body(self):
+ self._test_show_credential(bytes_body=True)
+
+ def test_update_credential_with_str_body(self):
+ self._test_update_credential()
+
+ def test_update_credential_with_bytes_body(self):
+ self._test_update_credential(bytes_body=True)
+
+ def test_list_credentials_with_str_body(self):
+ self._test_list_credentials()
+
+ def test_list_credentials_with_bytes_body(self):
+ self._test_list_credentials(bytes_body=True)
+
+ def test_delete_credential(self):
+ self.check_service_client_function(
+ self.client.delete_credential,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ credential_id="207e9b76935efc03804d3dd6ab52d22e9b22a0711e4ada4f",
+ status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_groups_client.py b/tempest/tests/lib/services/identity/v3/test_groups_client.py
new file mode 100644
index 0000000..38cf3ae
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_groups_client.py
@@ -0,0 +1,213 @@
+# Copyright 2016 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 tempest.lib.services.identity.v3 import groups_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestGroupsClient(base.BaseServiceTest):
+ FAKE_CREATE_GROUP = {
+ 'group': {
+ 'description': 'Tempest Group Description',
+ 'domain_id': 'TempestDomain',
+ 'name': 'Tempest Group',
+ }
+ }
+
+ FAKE_GROUP_INFO = {
+ 'group': {
+ 'description': 'Tempest Group Description',
+ 'domain_id': 'TempestDomain',
+ 'id': '6e13e2068cf9466e98950595baf6bb35',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups/' +
+ '6e13e2068cf9466e98950595baf6bb35'
+ },
+ 'name': 'Tempest Group',
+ }
+ }
+
+ FAKE_GROUP_LIST = {
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups',
+ 'previous': None,
+ 'next': None,
+ },
+ 'groups': [
+ {
+ 'description': 'Tempest Group One Description',
+ 'domain_id': 'TempestDomain',
+ 'id': '1c92f3453ed34291a074b87493455b8f',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups/' +
+ '1c92f3453ed34291a074b87493455b8f'
+ },
+ 'name': 'Tempest Group One',
+ },
+ {
+ 'description': 'Tempest Group Two Description',
+ 'domain_id': 'TempestDomain',
+ 'id': 'ce9e7dafed3b4877a7d4466ed730a9ee',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups/' +
+ 'ce9e7dafed3b4877a7d4466ed730a9ee'
+ },
+ 'name': 'Tempest Group Two',
+ },
+ ]
+ }
+
+ FAKE_USER_LIST = {
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups/' +
+ '6e13e2068cf9466e98950595baf6bb35/users',
+ 'previous': None,
+ 'next': None,
+ },
+ 'users': [
+ {
+ 'domain_id': 'TempestDomain',
+ 'description': 'Tempest Test User One Description',
+ 'enabled': True,
+ 'id': '642688fa65a84217b86cef3c063de2b9',
+ 'name': 'TempestUserOne',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/users/' +
+ '642688fa65a84217b86cef3c063de2b9'
+ }
+ },
+ {
+ 'domain_id': 'TempestDomain',
+ 'description': 'Tempest Test User Two Description',
+ 'enabled': True,
+ 'id': '1048ead6f8ef4a859b44ffbce3ac0b52',
+ 'name': 'TempestUserTwo',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/users/' +
+ '1048ead6f8ef4a859b44ffbce3ac0b52'
+ }
+ },
+ ]
+ }
+
+ def setUp(self):
+ super(TestGroupsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = groups_client.GroupsClient(fake_auth, 'identity',
+ 'regionOne')
+
+ def _test_create_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_group,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_GROUP,
+ bytes_body,
+ status=201,
+ )
+
+ def _test_show_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_group,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_GROUP_INFO,
+ bytes_body,
+ group_id='6e13e2068cf9466e98950595baf6bb35',
+ )
+
+ def _test_list_groups(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_groups,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_GROUP_LIST,
+ bytes_body,
+ )
+
+ def _test_update_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_group,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_GROUP_INFO,
+ bytes_body,
+ group_id='6e13e2068cf9466e98950595baf6bb35',
+ name='NewName',
+ )
+
+ def _test_list_users_in_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_group_users,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_USER_LIST,
+ bytes_body,
+ group_id='6e13e2068cf9466e98950595baf6bb35',
+ )
+
+ def test_create_group_with_string_body(self):
+ self._test_create_group()
+
+ def test_create_group_with_bytes_body(self):
+ self._test_create_group(bytes_body=True)
+
+ def test_show_group_with_string_body(self):
+ self._test_show_group()
+
+ def test_show_group_with_bytes_body(self):
+ self._test_show_group(bytes_body=True)
+
+ def test_list_groups_with_string_body(self):
+ self._test_list_groups()
+
+ def test_list_groups_with_bytes_body(self):
+ self._test_list_groups(bytes_body=True)
+
+ def test_update_group_with_string_body(self):
+ self._test_update_group()
+
+ def test_update_group_with_bytes_body(self):
+ self._test_update_group(bytes_body=True)
+
+ def test_list_users_in_group_with_string_body(self):
+ self._test_list_users_in_group()
+
+ def test_list_users_in_group_with_bytes_body(self):
+ self._test_list_users_in_group(bytes_body=True)
+
+ def test_delete_group(self):
+ self.check_service_client_function(
+ self.client.delete_group,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ group_id='6e13e2068cf9466e98950595baf6bb35',
+ status=204,
+ )
+
+ def test_add_user_to_group(self):
+ self.check_service_client_function(
+ self.client.add_group_user,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ status=204,
+ group_id='6e13e2068cf9466e98950595baf6bb35',
+ user_id='642688fa65a84217b86cef3c063de2b9',
+ )
+
+ def test_check_user_in_group(self):
+ self.check_service_client_function(
+ self.client.check_group_user_existence,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ status=204,
+ group_id='6e13e2068cf9466e98950595baf6bb35',
+ user_id='642688fa65a84217b86cef3c063de2b9',
+ )
diff --git a/tempest/tests/lib/services/identity/v3/test_identity_client.py b/tempest/tests/lib/services/identity/v3/test_identity_client.py
new file mode 100644
index 0000000..9eaaaaf
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_identity_client.py
@@ -0,0 +1,75 @@
+# Copyright 2016 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.identity.v3 import identity_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestIdentityClient(base.BaseServiceTest):
+ FAKE_TOKEN = {
+ "tokens": {
+ "id": "cbc36478b0bd8e67e89",
+ "name": "FakeToken",
+ "type": "token",
+ }
+ }
+
+ FAKE_API_INFO = {
+ "name": "API_info",
+ "type": "API",
+ "description": "test_description"
+ }
+
+ def setUp(self):
+ super(TestIdentityClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = identity_client.IdentityClient(fake_auth,
+ 'identity',
+ 'regionOne')
+
+ def _test_show_api_description(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_api_description,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_API_INFO,
+ bytes_body)
+
+ def _test_show_token(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_token,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_TOKEN,
+ bytes_body,
+ resp_token="cbc36478b0bd8e67e89")
+
+ def test_show_api_description_with_str_body(self):
+ self._test_show_api_description()
+
+ def test_show_api_description_with_bytes_body(self):
+ self._test_show_api_description(bytes_body=True)
+
+ def test_show_token_with_str_body(self):
+ self._test_show_token()
+
+ def test_show_token_with_bytes_body(self):
+ self._test_show_token(bytes_body=True)
+
+ def test_delete_token(self):
+ self.check_service_client_function(
+ self.client.delete_token,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ resp_token="cbc36478b0bd8e67e89",
+ status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_inherited_roles_client.py b/tempest/tests/lib/services/identity/v3/test_inherited_roles_client.py
new file mode 100644
index 0000000..9da3cce
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_inherited_roles_client.py
@@ -0,0 +1,220 @@
+# Copyright 2016 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.identity.v3 import inherited_roles_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestInheritedRolesClient(base.BaseServiceTest):
+ FAKE_LIST_INHERITED_ROLES = {
+ "roles": [
+ {
+ "id": "1",
+ "name": "test",
+ "links": "example.com"
+ },
+ {
+ "id": "2",
+ "name": "test2",
+ "links": "example.com"
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestInheritedRolesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = inherited_roles_client.InheritedRolesClient(
+ fake_auth, 'identity', 'regionOne')
+
+ def _test_create_inherited_role_on_domains_user(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_inherited_role_on_domains_user,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def _test_list_inherited_project_role_for_user_on_domain(
+ self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_inherited_project_role_for_user_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_INHERITED_ROLES,
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123")
+
+ def _test_create_inherited_role_on_domains_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_inherited_role_on_domains_group,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def _test_list_inherited_project_role_for_group_on_domain(
+ self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_inherited_project_role_for_group_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_INHERITED_ROLES,
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123")
+
+ def _test_create_inherited_role_on_projects_user(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_inherited_role_on_projects_user,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ project_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def _test_create_inherited_role_on_projects_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_inherited_role_on_projects_group,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ project_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_create_inherited_role_on_domains_user_with_str_body(self):
+ self._test_create_inherited_role_on_domains_user()
+
+ def test_create_inherited_role_on_domains_user_with_bytes_body(self):
+ self._test_create_inherited_role_on_domains_user(bytes_body=True)
+
+ def test_create_inherited_role_on_domains_group_with_str_body(self):
+ self._test_create_inherited_role_on_domains_group()
+
+ def test_create_inherited_role_on_domains_group_with_bytes_body(self):
+ self._test_create_inherited_role_on_domains_group(bytes_body=True)
+
+ def test_create_inherited_role_on_projects_user_with_str_body(self):
+ self._test_create_inherited_role_on_projects_user()
+
+ def test_create_inherited_role_on_projects_group_with_bytes_body(self):
+ self._test_create_inherited_role_on_projects_group(bytes_body=True)
+
+ def test_list_inherited_project_role_for_user_on_domain_with_str_body(
+ self):
+ self._test_list_inherited_project_role_for_user_on_domain()
+
+ def test_list_inherited_project_role_for_user_on_domain_with_bytes_body(
+ self):
+ self._test_list_inherited_project_role_for_user_on_domain(
+ bytes_body=True)
+
+ def test_list_inherited_project_role_for_group_on_domain_with_str_body(
+ self):
+ self._test_list_inherited_project_role_for_group_on_domain()
+
+ def test_list_inherited_project_role_for_group_on_domain_with_bytes_body(
+ self):
+ self._test_list_inherited_project_role_for_group_on_domain(
+ bytes_body=True)
+
+ def test_delete_inherited_role_from_user_on_domain(self):
+ self.check_service_client_function(
+ self.client.delete_inherited_role_from_user_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_user_inherited_project_role_on_domain(self):
+ self.check_service_client_function(
+ self.client.check_user_inherited_project_role_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_delete_inherited_role_from_group_on_domain(self):
+ self.check_service_client_function(
+ self.client.delete_inherited_role_from_group_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_group_inherited_project_role_on_domain(self):
+ self.check_service_client_function(
+ self.client.check_group_inherited_project_role_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_delete_inherited_role_from_user_on_project(self):
+ self.check_service_client_function(
+ self.client.delete_inherited_role_from_user_on_project,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_user_has_flag_on_inherited_to_project(self):
+ self.check_service_client_function(
+ self.client.check_user_has_flag_on_inherited_to_project,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_delete_inherited_role_from_group_on_project(self):
+ self.check_service_client_function(
+ self.client.delete_inherited_role_from_group_on_project,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_group_has_flag_on_inherited_to_project(self):
+ self.check_service_client_function(
+ self.client.check_group_has_flag_on_inherited_to_project,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_roles_client.py b/tempest/tests/lib/services/identity/v3/test_roles_client.py
new file mode 100644
index 0000000..bad1ef9
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_roles_client.py
@@ -0,0 +1,313 @@
+# Copyright 2016 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.identity.v3 import roles_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestRolesClient(base.BaseServiceTest):
+ FAKE_ROLE_INFO = {
+ "role": {
+ "domain_id": "1",
+ "id": "1",
+ "name": "test",
+ "links": "example.com"
+ }
+ }
+
+ FAKE_LIST_ROLES = {
+ "roles": [
+ {
+ "domain_id": "1",
+ "id": "1",
+ "name": "test",
+ "links": "example.com"
+ },
+ {
+ "domain_id": "2",
+ "id": "2",
+ "name": "test2",
+ "links": "example.com"
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestRolesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = roles_client.RolesClient(fake_auth,
+ 'identity', 'regionOne')
+
+ def _test_create_role(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_role,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_ROLE_INFO,
+ bytes_body,
+ domain_id="1",
+ name="test",
+ status=201)
+
+ def _test_show_role(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_role,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_ROLE_INFO,
+ bytes_body,
+ role_id="1")
+
+ def _test_list_roles(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_roles,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_ROLES,
+ bytes_body)
+
+ def _test_update_role(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_role,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_ROLE_INFO,
+ bytes_body,
+ role_id="1",
+ name="test")
+
+ def _test_create_user_role_on_project(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_user_role_on_project,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ project_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def _test_create_user_role_on_domain(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_user_role_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def _test_list_user_roles_on_project(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_user_roles_on_project,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_ROLES,
+ bytes_body,
+ project_id="b344506af7644f6794d9cb316600b020",
+ user_id="123")
+
+ def _test_list_user_roles_on_domain(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_user_roles_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_ROLES,
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123")
+
+ def _test_create_group_role_on_project(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_group_role_on_project,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ project_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def _test_create_group_role_on_domain(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_group_role_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def _test_list_group_roles_on_project(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_group_roles_on_project,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_ROLES,
+ bytes_body,
+ project_id="b344506af7644f6794d9cb316600b020",
+ group_id="123")
+
+ def _test_list_group_roles_on_domain(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_group_roles_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_ROLES,
+ bytes_body,
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123")
+
+ def test_create_role_with_str_body(self):
+ self._test_create_role()
+
+ def test_create_role_with_bytes_body(self):
+ self._test_create_role(bytes_body=True)
+
+ def test_show_role_with_str_body(self):
+ self._test_show_role()
+
+ def test_show_role_with_bytes_body(self):
+ self._test_show_role(bytes_body=True)
+
+ def test_list_roles_with_str_body(self):
+ self._test_list_roles()
+
+ def test_list_roles_with_bytes_body(self):
+ self._test_list_roles(bytes_body=True)
+
+ def test_update_role_with_str_body(self):
+ self._test_update_role()
+
+ def test_update_role_with_bytes_body(self):
+ self._test_update_role(bytes_body=True)
+
+ def test_delete_role(self):
+ self.check_service_client_function(
+ self.client.delete_role,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ role_id="1",
+ status=204)
+
+ def test_create_user_role_on_project_with_str_body(self):
+ self._test_create_user_role_on_project()
+
+ def test_create_user_role_on_project_with_bytes_body(self):
+ self._test_create_user_role_on_project(bytes_body=True)
+
+ def test_create_user_role_on_domain_with_str_body(self):
+ self._test_create_user_role_on_domain()
+
+ def test_create_user_role_on_domain_with_bytes_body(self):
+ self._test_create_user_role_on_domain(bytes_body=True)
+
+ def test_create_group_role_on_domain_with_str_body(self):
+ self._test_create_group_role_on_domain()
+
+ def test_create_group_role_on_domain_with_bytes_body(self):
+ self._test_create_group_role_on_domain(bytes_body=True)
+
+ def test_list_user_roles_on_project_with_str_body(self):
+ self._test_list_user_roles_on_project()
+
+ def test_list_user_roles_on_project_with_bytes_body(self):
+ self._test_list_user_roles_on_project(bytes_body=True)
+
+ def test_list_user_roles_on_domain_with_str_body(self):
+ self._test_list_user_roles_on_domain()
+
+ def test_list_user_roles_on_domain_with_bytes_body(self):
+ self._test_list_user_roles_on_domain(bytes_body=True)
+
+ def test_list_group_roles_on_domain_with_str_body(self):
+ self._test_list_group_roles_on_domain()
+
+ def test_list_group_roles_on_domain_with_bytes_body(self):
+ self._test_list_group_roles_on_domain(bytes_body=True)
+
+ def test_delete_role_from_user_on_project(self):
+ self.check_service_client_function(
+ self.client.delete_role_from_user_on_project,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_delete_role_from_user_on_domain(self):
+ self.check_service_client_function(
+ self.client.delete_role_from_user_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_delete_role_from_group_on_project(self):
+ self.check_service_client_function(
+ self.client.delete_role_from_group_on_project,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_delete_role_from_group_on_domain(self):
+ self.check_service_client_function(
+ self.client.delete_role_from_group_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_user_role_existence_on_project(self):
+ self.check_service_client_function(
+ self.client.check_user_role_existence_on_project,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_user_role_existence_on_domain(self):
+ self.check_service_client_function(
+ self.client.check_user_role_existence_on_domain,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ user_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_role_from_group_on_project_existence(self):
+ self.check_service_client_function(
+ self.client.check_role_from_group_on_project_existence,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ project_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
+
+ def test_check_role_from_group_on_domain_existence(self):
+ self.check_service_client_function(
+ self.client.check_role_from_group_on_domain_existence,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ domain_id="b344506af7644f6794d9cb316600b020",
+ group_id="123",
+ role_id="1234",
+ status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_trusts_client.py b/tempest/tests/lib/services/identity/v3/test_trusts_client.py
new file mode 100644
index 0000000..a1ca020
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_trusts_client.py
@@ -0,0 +1,150 @@
+# Copyright 2016 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 tempest.lib.services.identity.v3 import trusts_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestTrustsClient(base.BaseServiceTest):
+ FAKE_CREATE_TRUST = {
+ "trust": {
+ "expires_at": "2013-02-27T18:30:59.999999Z",
+ "impersonation": True,
+ "allow_redelegation": True,
+ "project_id": "ddef321",
+ "roles": [
+ {
+ "name": "member"
+ }
+ ],
+ "trustee_user_id": "86c0d5",
+ "trustor_user_id": "a0fdfd"
+ }
+ }
+
+ FAKE_LIST_TRUSTS = {
+ "trusts": [
+ {
+ "id": "1ff900",
+ "expires_at":
+ "2013-02-27T18:30:59.999999Z",
+ "impersonation": True,
+ "links": {
+ "self":
+ "http://example.com/identity/v3/OS-TRUST/trusts/1ff900"
+ },
+ "project_id": "0f1233",
+ "trustee_user_id": "86c0d5",
+ "trustor_user_id": "a0fdfd"
+ },
+ {
+ "id": "f4513a",
+ "impersonation": False,
+ "links": {
+ "self":
+ "http://example.com/identity/v3/OS-TRUST/trusts/f45513a"
+ },
+ "project_id": "0f1233",
+ "trustee_user_id": "86c0d5",
+ "trustor_user_id": "3cd2ce"
+ }
+ ]
+ }
+
+ FAKE_TRUST_INFO = {
+ "trust": {
+ "id": "987fe8",
+ "expires_at": "2013-02-27T18:30:59.999999Z",
+ "impersonation": True,
+ "links": {
+ "self":
+ "http://example.com/identity/v3/OS-TRUST/trusts/987fe8"
+ },
+ "roles": [
+ {
+ "id": "ed7b78",
+ "links": {
+ "self":
+ "http://example.com/identity/v3/roles/ed7b78"
+ },
+ "name": "member"
+ }
+ ],
+ "roles_links": {
+ "next": None,
+ "previous": None,
+ "self":
+ "http://example.com/identity/v3/OS-TRUST/trusts/1ff900/roles"
+ },
+ "project_id": "0f1233",
+ "trustee_user_id": "be34d1",
+ "trustor_user_id": "56ae32"
+ }
+ }
+
+ def setUp(self):
+ super(TestTrustsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = trusts_client.TrustsClient(fake_auth, 'identity',
+ 'regionOne')
+
+ def _test_create_trust(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_trust,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_TRUST,
+ bytes_body,
+ status=201)
+
+ def _test_show_trust(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_trust,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_TRUST_INFO,
+ bytes_body,
+ trust_id="1ff900")
+
+ def _test_list_trusts(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_trusts,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_TRUSTS,
+ bytes_body)
+
+ def test_create_trust_with_str_body(self):
+ self._test_create_trust()
+
+ def test_create_trust_with_bytes_body(self):
+ self._test_create_trust(bytes_body=True)
+
+ def test_show_trust_with_str_body(self):
+ self._test_show_trust()
+
+ def test_show_trust_with_bytes_body(self):
+ self._test_show_trust(bytes_body=True)
+
+ def test_list_trusts_with_str_body(self):
+ self._test_list_trusts()
+
+ def test_list_trusts_with_bytes_body(self):
+ self._test_list_trusts(bytes_body=True)
+
+ def test_delete_trust(self):
+ self.check_service_client_function(
+ self.client.delete_trust,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ trust_id="1ff900",
+ status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_users_client.py b/tempest/tests/lib/services/identity/v3/test_users_client.py
new file mode 100644
index 0000000..5b572f5
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_users_client.py
@@ -0,0 +1,205 @@
+# Copyright 2016 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 tempest.lib.services.identity.v3 import users_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestUsersClient(base.BaseServiceTest):
+ FAKE_CREATE_USER = {
+ 'user': {
+ 'default_project_id': '95f8c3f8e7b54409a418fc30717f9ae0',
+ 'domain_id': '8347b31afc3545c4b311cb4cce788a08',
+ 'enabled': True,
+ 'name': 'Tempest User',
+ 'password': 'TempestPassword',
+ }
+ }
+
+ FAKE_USER_INFO = {
+ 'user': {
+ 'default_project_id': '95f8c3f8e7b54409a418fc30717f9ae0',
+ 'domain_id': '8347b31afc3545c4b311cb4cce788a08',
+ 'enabled': True,
+ 'id': '817fb3c23fd7465ba6d7fe1b1320121d',
+ 'links': {
+ 'self': 'http://example.com/identity',
+ },
+ 'name': 'Tempest User',
+ 'password_expires_at': '2016-11-06T15:32:17.000000',
+ }
+ }
+
+ FAKE_USER_LIST = {
+ 'links': {
+ 'next': None,
+ 'previous': None,
+ 'self': 'http://example.com/identity/v3/users',
+ },
+ 'users': [
+ {
+ 'domain_id': 'TempestDomain',
+ 'enabled': True,
+ 'id': '817fb3c23fd7465ba6d7fe1b1320121d',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/users/' +
+ '817fb3c23fd7465ba6d7fe1b1320121d',
+ },
+ 'name': 'Tempest User',
+ 'password_expires_at': '2016-11-06T15:32:17.000000',
+ },
+ {
+ 'domain_id': 'TempestDomain',
+ 'enabled': True,
+ 'id': 'bdbfb1e2f1344be197e90a778379cca1',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/users/' +
+ 'bdbfb1e2f1344be197e90a778379cca1',
+ },
+ 'name': 'Tempest User',
+ 'password_expires_at': None,
+ },
+ ]
+ }
+
+ FAKE_GROUP_LIST = {
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups',
+ 'previous': None,
+ 'next': None,
+ },
+ 'groups': [
+ {
+ 'description': 'Tempest Group One Description',
+ 'domain_id': 'TempestDomain',
+ 'id': '1c92f3453ed34291a074b87493455b8f',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups/' +
+ '1c92f3453ed34291a074b87493455b8f'
+ },
+ 'name': 'Tempest Group One',
+ },
+ {
+ 'description': 'Tempest Group Two Description',
+ 'domain_id': 'TempestDomain',
+ 'id': 'ce9e7dafed3b4877a7d4466ed730a9ee',
+ 'links': {
+ 'self': 'http://example.com/identity/v3/groups/' +
+ 'ce9e7dafed3b4877a7d4466ed730a9ee'
+ },
+ 'name': 'Tempest Group Two',
+ },
+ ]
+ }
+
+ def setUp(self):
+ super(TestUsersClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = users_client.UsersClient(fake_auth, 'identity',
+ 'regionOne')
+
+ def _test_create_user(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_user,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_USER,
+ bytes_body,
+ status=201,
+ )
+
+ def _test_show_user(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_user,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_USER_INFO,
+ bytes_body,
+ user_id='817fb3c23fd7465ba6d7fe1b1320121d',
+ )
+
+ def _test_list_users(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_users,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_USER_LIST,
+ bytes_body,
+ )
+
+ def _test_update_user(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_user,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_USER_INFO,
+ bytes_body,
+ user_id='817fb3c23fd7465ba6d7fe1b1320121d',
+ name='NewName',
+ )
+
+ def _test_list_user_groups(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_user_groups,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_GROUP_LIST,
+ bytes_body,
+ user_id='817fb3c23fd7465ba6d7fe1b1320121d',
+ )
+
+ def test_create_user_with_string_body(self):
+ self._test_create_user()
+
+ def test_create_user_with_bytes_body(self):
+ self._test_create_user(bytes_body=True)
+
+ def test_show_user_with_string_body(self):
+ self._test_show_user()
+
+ def test_show_user_with_bytes_body(self):
+ self._test_show_user(bytes_body=True)
+
+ def test_list_users_with_string_body(self):
+ self._test_list_users()
+
+ def test_list_users_with_bytes_body(self):
+ self._test_list_users(bytes_body=True)
+
+ def test_update_user_with_string_body(self):
+ self._test_update_user()
+
+ def test_update_user_with_bytes_body(self):
+ self._test_update_user(bytes_body=True)
+
+ def test_list_user_groups_with_string_body(self):
+ self._test_list_user_groups()
+
+ def test_list_user_groups_with_bytes_body(self):
+ self._test_list_user_groups(bytes_body=True)
+
+ def test_delete_user(self):
+ self.check_service_client_function(
+ self.client.delete_user,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ user_id='817fb3c23fd7465ba6d7fe1b1320121d',
+ status=204,
+ )
+
+ def test_change_user_password(self):
+ self.check_service_client_function(
+ self.client.update_user_password,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ {},
+ status=204,
+ user_id='817fb3c23fd7465ba6d7fe1b1320121d',
+ password='NewTempestPassword',
+ original_password='OldTempestPassword')
diff --git a/tempest/tests/negative/test_negative_generators.py b/tempest/tests/negative/test_negative_generators.py
index 2e45ef7..7e1ee2c 100644
--- a/tempest/tests/negative/test_negative_generators.py
+++ b/tempest/tests/negative/test_negative_generators.py
@@ -107,7 +107,7 @@
def _validate_result(self, valid_schema, invalid_schema):
for k, v in six.iteritems(valid_schema):
- self.assertTrue(k in invalid_schema)
+ self.assertIn(k, invalid_schema)
def test_generator_mandatory_functions(self):
for data_type in self.types:
diff --git a/tempest/tests/services/object_storage/test_object_client.py b/tempest/tests/services/object_storage/test_object_client.py
index cd8c8f1..cc1dc1a 100644
--- a/tempest/tests/services/object_storage/test_object_client.py
+++ b/tempest/tests/services/object_storage/test_object_client.py
@@ -20,7 +20,7 @@
from tempest.lib import exceptions
from tempest.services.object_storage import object_client
from tempest.tests import base
-from tempest.tests import fake_auth_provider
+from tempest.tests.lib import fake_auth_provider
class TestObjectClient(base.TestCase):
diff --git a/tempest/tests/test_negative_rest_client.py b/tempest/tests/test_negative_rest_client.py
index 9d9c20f..05f9f3e 100644
--- a/tempest/tests/test_negative_rest_client.py
+++ b/tempest/tests/test_negative_rest_client.py
@@ -21,8 +21,8 @@
from tempest.common import negative_rest_client
from tempest import config
from tempest.tests import base
-from tempest.tests import fake_auth_provider
from tempest.tests import fake_config
+from tempest.tests.lib import fake_auth_provider
class TestNegativeRestClient(base.TestCase):
diff --git a/test-requirements.txt b/test-requirements.txt
index 04c3d6d..2d15daa 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,9 +3,9 @@
# process, which may cause wedges in the gate later.
hacking<0.12,>=0.11.0 # Apache-2.0
# needed for doc build
-sphinx!=1.3b1,<1.3,>=1.2.1 # BSD
+sphinx!=1.3b1,<1.4,>=1.2.1 # BSD
python-subunit>=0.0.18 # Apache-2.0/BSD
-oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
+oslosphinx>=4.7.0 # Apache-2.0
reno>=1.8.0 # Apache2
mock>=2.0 # BSD
coverage>=3.6 # Apache-2.0
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index 03dbd9b..03e838e 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -48,6 +48,8 @@
def has_tempest_plugin(proj):
+ if proj.startswith('openstack/deb-'):
+ return False
r = requests.get(
"https://git.openstack.org/cgit/%s/plain/setup.cfg" % proj)
p = re.compile('^tempest\.test_plugins', re.M)
diff --git a/tools/pretty_tox.sh b/tools/pretty_tox.sh
index fb4e6d5..0b83b91 100755
--- a/tools/pretty_tox.sh
+++ b/tools/pretty_tox.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+echo "WARNING: This script is deprecated and will be removed in the near future. Please migrate to tempest run or another method of launching a test runner"
+
set -o pipefail
TESTRARGS=$1
diff --git a/tools/pretty_tox_serial.sh b/tools/pretty_tox_serial.sh
index e0fca0f..1f8204e 100755
--- a/tools/pretty_tox_serial.sh
+++ b/tools/pretty_tox_serial.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+echo "WARNING: This script is deprecated and will be removed in the near future. Please migrate to tempest run or another method of launching a test runner"
+
set -o pipefail
TESTRARGS=$@
diff --git a/tox.ini b/tox.ini
index a621492..7096e60 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = pep8,py35,py34,py27
+envlist = pep8,py35,py34,py27,pip-check-reqs
minversion = 2.3.1
skipsdist = True
@@ -16,6 +16,7 @@
setenv =
VIRTUAL_ENV={envdir}
OS_TEST_PATH=./tempest/tests
+ PYTHONWARNINGS=default::DeprecationWarning
passenv = OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_TEST_TIMEOUT OS_TEST_LOCK_PATH OS_TEST_PATH TEMPEST_CONFIG TEMPEST_CONFIG_DIR http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
usedevelop = True
install_command = pip install -U {opts} {packages}
@@ -44,7 +45,7 @@
deps = {[tempestenv]deps}
commands =
find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '{posargs}'
+ tempest run --regex {posargs}
[testenv:ostestr]
sitepackages = {[tempestenv]sitepackages}
@@ -66,7 +67,7 @@
deps = {[tempestenv]deps}
commands =
find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '{posargs}'
+ tempest run --regex {posargs}
[testenv:full]
envdir = .tox/tempest
@@ -77,7 +78,7 @@
# See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
commands =
find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)) {posargs}'
+ tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))' {posargs}
[testenv:full-serial]
envdir = .tox/tempest
@@ -88,7 +89,7 @@
# See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
commands =
find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)) {posargs}'
+ tempest run --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))' {posargs}
[testenv:smoke]
envdir = .tox/tempest
@@ -97,7 +98,7 @@
deps = {[tempestenv]deps}
commands =
find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox.sh '\[.*\bsmoke\b.*\] {posargs}'
+ tempest run --regex '\[.*\bsmoke\b.*\]' {posargs}
[testenv:smoke-serial]
envdir = .tox/tempest
@@ -109,7 +110,7 @@
# job would fail if we moved it to parallel.
commands =
find . -type f -name "*.pyc" -delete
- bash tools/pretty_tox_serial.sh '\[.*\bsmoke\b.*\] {posargs}'
+ tempest run --serial --regex '\[.*\bsmoke\b.*\]' {posargs}
[testenv:stress]
envdir = .tox/tempest
@@ -153,7 +154,18 @@
# Skipped because of new hacking 0.9: H405
ignore = E125,E123,E129
show-source = True
-exclude = .git,.venv,.tox,dist,doc,openstack,*egg
+exclude = .git,.venv,.tox,dist,doc,*egg
[testenv:releasenotes]
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
+
+[testenv:pip-check-reqs]
+# Do not install test-requirements as that will pollute the virtualenv for
+# determining missing packages.
+# This also means that pip-check-reqs must be installed separately, outside
+# of the requirements.txt files
+deps = pip_check_reqs
+ -r{toxinidir}/requirements.txt
+commands=
+ pip-extra-reqs -d --ignore-file=tempest/tests/* tempest
+ pip-missing-reqs -d --ignore-file=tempest/tests/* tempest