Merge "add detaches to attachment test"
diff --git a/HACKING.rst b/HACKING.rst
index 446d865..cb9821e 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -358,10 +358,10 @@
When adding tests for new features that were not in previous releases of the
projects the new test has to be properly skipped with a feature flag. Whether
-this is just as simple as using the @test.requires_ext() decorator to check
-if the required extension (or discoverable optional API) is enabled or adding
-a new config option to the appropriate section. If there isn't a method of
-selecting the new **feature** from the config file then there won't be a
+this is just as simple as using the @utils.requires_ext() decorator to
+check if the required extension (or discoverable optional API) is enabled or
+adding a new config option to the appropriate section. If there isn't a method
+of selecting the new **feature** from the config file then there won't be a
mechanism to disable the test with older stable releases and the new test won't
be able to merge.
diff --git a/bindep.txt b/bindep.txt
index 8914ade..efd3a10 100644
--- a/bindep.txt
+++ b/bindep.txt
@@ -1,5 +1,5 @@
# This file contains runtime (non-python) dependencies
-# More info at: http://docs.openstack.org/infra/bindep/readme.html
+# More info at: https://docs.openstack.org/infra/bindep/readme.html
libffi-dev [platform:dpkg]
libffi-devel [platform:rpm]
diff --git a/doc/source/library/credential_providers.rst b/doc/source/library/credential_providers.rst
index 7e831cc..f4eb37d 100644
--- a/doc/source/library/credential_providers.rst
+++ b/doc/source/library/credential_providers.rst
@@ -6,7 +6,7 @@
These library interfaces are used to deal with allocating credentials on demand
either dynamically by calling keystone to allocate new credentials, or from
a list of preprovisioned credentials. These 2 modules are implementations of
-the same abstract credential providers class and can be used interchangably.
+the same abstract credential providers class and can be used interchangeably.
However, each implementation has some additional parameters that are used to
influence the behavior of the modules. The API reference at the bottom of this
doc shows the interface definitions for both modules, however that may be a bit
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index d80081d..573b7d4 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -300,35 +300,35 @@
* `2.2`_
- .. _2.2: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id2
+ .. _2.2: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id2
* `2.10`_
- .. _2.10: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id9
+ .. _2.10: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id9
* `2.20`_
- .. _2.20: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id18
+ .. _2.20: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id18
* `2.25`_
- .. _2.25: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-mitaka
+ .. _2.25: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-mitaka
* `2.32`_
- .. _2.32: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id29
+ .. _2.32: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id29
* `2.37`_
- .. _2.37: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id34
+ .. _2.37: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id34
* `2.42`_
- .. _2.42: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-ocata
+ .. _2.42: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#maximum-in-ocata
* `2.47`_
- .. _2.47: http://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id42
+ .. _2.47: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id42
* `2.48`_
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index b3af92f..77ef9ed 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -28,6 +28,7 @@
* tempest.lib.*
* tempest.config
* tempest.test_discover.plugins
+* tempest.common.credentials_factory
If there is an interface from tempest that you need to rely on in your plugin
which is not listed above, it likely needs to be migrated to tempest.lib. In
diff --git a/releasenotes/notes/add-ip-version-check-in-addresses-x491ac6d9abaxa12.yaml b/releasenotes/notes/add-ip-version-check-in-addresses-x491ac6d9abaxa12.yaml
new file mode 100644
index 0000000..957e903
--- /dev/null
+++ b/releasenotes/notes/add-ip-version-check-in-addresses-x491ac6d9abaxa12.yaml
@@ -0,0 +1,4 @@
+---
+fixes:
+ Add more accurate ip version check in addresses schema which will
+ limit the ip version value in [4, 6].
diff --git a/releasenotes/notes/add-is-resource-deleted-sg-client-f4a7a7a54ff024d7.yaml b/releasenotes/notes/add-is-resource-deleted-sg-client-f4a7a7a54ff024d7.yaml
new file mode 100644
index 0000000..e046326
--- /dev/null
+++ b/releasenotes/notes/add-is-resource-deleted-sg-client-f4a7a7a54ff024d7.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Implement the `rest_client` method `is_resource_deleted` in the network
+ security group client.
diff --git a/releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml b/releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml
index 4abfe9e..ca42014 100644
--- a/releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml
+++ b/releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml
@@ -1,5 +1,7 @@
---
fixes:
- Add a missing return statement to the retype_volume API in the v2 volumes_client library.
- This changes the response body from None to an empty dictionary.
+ - |
+ Add a missing return statement to the retype_volume API in the v2
+ volumes_client library: Bug#1703997
+ This changes the response body from None to an empty dictionary.
diff --git a/releasenotes/notes/add-update-group-tempest-tests-72f8ec19b2809849.yaml b/releasenotes/notes/add-update-group-tempest-tests-72f8ec19b2809849.yaml
new file mode 100644
index 0000000..23c30af
--- /dev/null
+++ b/releasenotes/notes/add-update-group-tempest-tests-72f8ec19b2809849.yaml
@@ -0,0 +1,4 @@
+---
+features:
+ - |
+ Add update_group to groups_client in the volume service library.
diff --git a/releasenotes/notes/credentials-factory-stable-c8037bd9ae642482.yaml b/releasenotes/notes/credentials-factory-stable-c8037bd9ae642482.yaml
new file mode 100644
index 0000000..6faa536
--- /dev/null
+++ b/releasenotes/notes/credentials-factory-stable-c8037bd9ae642482.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ The credentials_factory.py module is now marked as stable for Tempest
+ plugins. It provides helpers that can be used by Tempest plugins to
+ obtain test credentials for their test cases in a format that honors the
+ Tempest configuration in use.
+ Credentials may be provisioned on the fly during the test run, or they
+ can be setup in advance and fed to test via a YAML file; they can be
+ setup for identity v2 or identity v3.
diff --git a/releasenotes/notes/fix-remoteclient-default-ssh-shell-prologue-33e99343d086f601.yaml b/releasenotes/notes/fix-remoteclient-default-ssh-shell-prologue-33e99343d086f601.yaml
new file mode 100644
index 0000000..5063fd5
--- /dev/null
+++ b/releasenotes/notes/fix-remoteclient-default-ssh-shell-prologue-33e99343d086f601.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Fix RemoteClient default ssh_shell_prologue: Bug#1707478
+
+ The default ssh_shell_proloque has been modified from
+ specifying erroneous PATH=$$PATH:/sbin to PATH=$PATH:/sbin.
diff --git a/releasenotes/notes/raise-exception-when-error-deleting-on-volume-18d0d0c5886212dd.yaml b/releasenotes/notes/raise-exception-when-error-deleting-on-volume-18d0d0c5886212dd.yaml
new file mode 100644
index 0000000..194dbc1
--- /dev/null
+++ b/releasenotes/notes/raise-exception-when-error-deleting-on-volume-18d0d0c5886212dd.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+ - |
+ Tempest checks a volume delete by waiting for NotFound(404) on
+ show_volume(). Sometime a volume delete fails and the volume status
+ becomes error_deleting which means the delete is failed.
+ So Tempest doesn't need to wait anymore. A new release of Tempest
+ raises an exception DeleteErrorException instead of waiting.
diff --git a/requirements.txt b/requirements.txt
index a74f5c2..36b9efa 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,17 +5,17 @@
cliff>=2.8.0 # Apache-2.0
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
testtools>=1.4.0 # MIT
-paramiko>=2.0 # LGPLv2.1+
+paramiko>=2.0.0 # LGPLv2.1+
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!=4.3.0,!=4.4.0,>=4.0.0 # Apache-2.0
-oslo.log>=3.22.0 # Apache-2.0
+oslo.log>=3.30.0 # Apache-2.0
oslo.serialization!=2.19.1,>=1.10.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0
six>=1.9.0 # MIT
fixtures>=3.0.0 # Apache-2.0/BSD
-PyYAML>=3.10.0 # MIT
+PyYAML>=3.10 # MIT
python-subunit>=0.0.18 # Apache-2.0/BSD
stevedore>=1.20.0 # Apache-2.0
PrettyTable<0.8,>=0.7.1 # BSD
diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py
index 69cbfb5..0901374 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -86,7 +86,7 @@
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.assertNotEmpty(agents, 'Cannot get any agents.(%s)' % agents)
+ self.assertNotEmpty(agents, 'Cannot get any agents.')
self.assertIn(body['agent_id'], map(lambda x: x['agent_id'], agents))
@decorators.idempotent_id('eabadde4-3cd7-4ec4-a4b5-5a936d2d4408')
@@ -104,7 +104,7 @@
agent_id_xen = agent_xen['agent_id']
agents = (self.client.list_agents(hypervisor=agent_xen['hypervisor'])
['agents'])
- self.assertNotEmpty(agents, 'Cannot get any agents.(%s)' % agents)
+ self.assertNotEmpty(agents, 'Cannot get any agents.')
self.assertIn(agent_id_xen, 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_auto_allocate_network.py b/tempest/api/compute/admin/test_auto_allocate_network.py
index 83fe215..ea92563 100644
--- a/tempest/api/compute/admin/test_auto_allocate_network.py
+++ b/tempest/api/compute/admin/test_auto_allocate_network.py
@@ -17,11 +17,11 @@
from tempest.api.compute import base
from tempest.common import compute
from tempest.common import credentials_factory as credentials
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_excs
-from tempest import test
CONF = config.CONF
LOG = log.getLogger(__name__)
@@ -53,7 +53,8 @@
raise cls.skipException(msg)
if not CONF.service_available.neutron:
raise cls.skipException('Neutron is required')
- if not test.is_extension_enabled('auto-allocated-topology', 'network'):
+ if not utils.is_extension_enabled('auto-allocated-topology',
+ 'network'):
raise cls.skipException(
'auto-allocated-topology extension is not available')
diff --git a/tempest/api/compute/admin/test_create_server.py b/tempest/api/compute/admin/test_create_server.py
index 3449aba..66bedd9 100644
--- a/tempest/api/compute/admin/test_create_server.py
+++ b/tempest/api/compute/admin/test_create_server.py
@@ -25,8 +25,6 @@
class ServersWithSpecificFlavorTestJSON(base.BaseV2ComputeAdminTest):
- disk_config = 'AUTO'
-
@classmethod
def setup_credentials(cls):
cls.prepare_instance_network()
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index 1e09eeb..69c8a82 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -49,17 +49,17 @@
break
@decorators.idempotent_id('16b7d848-2f7c-4709-85a3-2dfb4576cc52')
- @test.services('network')
+ @utils.services('network')
def test_list_fixed_ip_details(self):
fixed_ip = self.client.show_fixed_ip(self.ip)
self.assertEqual(fixed_ip['fixed_ip']['address'], self.ip)
@decorators.idempotent_id('5485077b-7e46-4cec-b402-91dc3173433b')
- @test.services('network')
+ @utils.services('network')
def test_set_reserve(self):
self.client.reserve_fixed_ip(self.ip, reserve="None")
@decorators.idempotent_id('7476e322-b9ff-4710-bf82-49d51bac6e2e')
- @test.services('network')
+ @utils.services('network')
def test_set_unreserve(self):
self.client.reserve_fixed_ip(self.ip, unreserve="None")
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index a77011e..c54c866 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -13,10 +13,10 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -51,14 +51,14 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('9f17f47d-daad-4adc-986e-12370c93e407')
- @test.services('network')
+ @utils.services('network')
def test_list_fixed_ip_details_with_non_admin_user(self):
self.assertRaises(lib_exc.Forbidden,
self.non_admin_client.show_fixed_ip, self.ip)
@decorators.attr(type=['negative'])
@decorators.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
- @test.services('network')
+ @utils.services('network')
def test_set_reserve_with_non_admin_user(self):
self.assertRaises(lib_exc.Forbidden,
self.non_admin_client.reserve_fixed_ip,
@@ -66,7 +66,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
- @test.services('network')
+ @utils.services('network')
def test_set_unreserve_with_non_admin_user(self):
self.assertRaises(lib_exc.Forbidden,
self.non_admin_client.reserve_fixed_ip,
@@ -74,7 +74,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
- @test.services('network')
+ @utils.services('network')
def test_set_reserve_with_invalid_ip(self):
# NOTE(maurosr): since this exercises the same code snippet, we do it
# only for reserve action
@@ -87,7 +87,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
- @test.services('network')
+ @utils.services('network')
def test_fixed_ip_with_invalid_action(self):
self.assertRaises(lib_exc.BadRequest,
self.client.reserve_fixed_ip,
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 36ebc25..1483c2e 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -16,10 +16,10 @@
import uuid
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -28,7 +28,7 @@
@classmethod
def skip_checks(cls):
super(FlavorsAdminTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+ if not utils.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
msg = "OS-FLV-EXT-DATA extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 2c236ec..b8e2b42 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -14,8 +14,8 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class FlavorsAccessTestJSON(base.BaseV2ComputeAdminTest):
@@ -27,7 +27,7 @@
@classmethod
def skip_checks(cls):
super(FlavorsAccessTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+ if not utils.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
msg = "OS-FLV-EXT-DATA extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index be165cb..45ca10a 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class FlavorsAccessNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -30,7 +30,7 @@
@classmethod
def skip_checks(cls):
super(FlavorsAccessNegativeTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+ if not utils.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
msg = "OS-FLV-EXT-DATA extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 747cb42..d4e7bd5 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class FlavorsExtraSpecsTestJSON(base.BaseV2ComputeAdminTest):
@@ -29,7 +29,7 @@
@classmethod
def skip_checks(cls):
super(FlavorsExtraSpecsTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+ if not utils.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
msg = "OS-FLV-EXT-DATA extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index f39feb9..bc32346 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -15,10 +15,10 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class FlavorsExtraSpecsNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -30,7 +30,7 @@
@classmethod
def skip_checks(cls):
super(FlavorsExtraSpecsNegativeTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+ if not utils.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
msg = "OS-FLV-EXT-DATA extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index 496f119..ba19937 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -16,11 +16,11 @@
import netaddr
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions
-from tempest import test
CONF = config.CONF
@@ -57,7 +57,7 @@
return
@decorators.idempotent_id('2c8f145f-8012-4cb8-ac7e-95a587f0e4ab')
- @test.services('network')
+ @utils.services('network')
def test_create_list_delete_floating_ips_bulk(self):
# Create, List and delete the Floating IPs Bulk
pool = 'test_pool'
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 0db802c..404fd94 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -30,26 +30,23 @@
hypers = self.client.list_hypervisors()['hypervisors']
return hypers
- def assertHypervisors(self, hypers):
- self.assertNotEmpty(hypers, "No hypervisors found: %s" % hypers)
-
@decorators.idempotent_id('7f0ceacd-c64d-4e96-b8ee-d02943142cc5')
def test_get_hypervisor_list(self):
# List of hypervisor and available hypervisors hostname
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
@decorators.idempotent_id('1e7fdac2-b672-4ad1-97a4-bad0e3030118')
def test_get_hypervisor_list_details(self):
# Display the details of the all hypervisor
hypers = self.client.list_hypervisors(detail=True)['hypervisors']
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
@decorators.idempotent_id('94ff9eae-a183-428e-9cdb-79fde71211cc')
def test_get_hypervisor_show_details(self):
# Display the details of the specified hypervisor
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
details = self.client.show_hypervisor(hypers[0]['id'])['hypervisor']
self.assertNotEmpty(details)
@@ -60,7 +57,7 @@
def test_get_hypervisor_show_servers(self):
# Show instances about the specific hypervisors
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
hostname = hypers[0]['hypervisor_hostname']
hypervisors = (self.client.list_servers_on_hypervisor(hostname)
@@ -116,7 +113,7 @@
@decorators.idempotent_id('d7e1805b-3b14-4a3b-b6fd-50ec6d9f361f')
def test_search_hypervisor(self):
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
hypers = self.client.search_hypervisor(
hypers[0]['hypervisor_hostname'])['hypervisors']
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 256a267..14be947 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -20,10 +20,10 @@
from tempest.api.compute import base
from tempest.common import compute
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -122,7 +122,7 @@
@decorators.skip_because(bug="1524898")
@decorators.idempotent_id('5071cf17-3004-4257-ae61-73a84e28badd')
- @test.services('volume')
+ @utils.services('volume')
def test_volume_backed_live_migration(self):
self._test_live_migration(volume_backed=True)
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 1aa9227..5894e80 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -157,8 +157,7 @@
def _restore_default_quotas(self, original_defaults):
LOG.debug("restoring quota class defaults")
- self.adm_client.update_quota_class_set(
- 'default', **original_defaults)['quota_class_set']
+ self.adm_client.update_quota_class_set('default', **original_defaults)
# NOTE(sdague): this test is problematic as it changes
# global state, and possibly needs to be part of a set of
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 747f320..5ef7ee4 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -13,11 +13,11 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -89,7 +89,7 @@
condition=CONF.service_available.neutron)
@decorators.attr(type=['negative'])
@decorators.idempotent_id('7c6c8f3b-2bf6-4918-b240-57b136a66aa0')
- @test.services('network')
+ @utils.services('network')
def test_security_groups_exceed_limit(self):
# Negative test: Creation Security Groups over limit should FAIL
# Set the quota to number of used security groups
@@ -108,7 +108,7 @@
condition=CONF.service_available.neutron)
@decorators.attr(type=['negative'])
@decorators.idempotent_id('6e9f436d-f1ed-4f8e-a493-7275dfaa4b4d')
- @test.services('network')
+ @utils.services('network')
def test_security_groups_rules_exceed_limit(self):
# Negative test: Creation of Security Group Rules should FAIL
# when we reach limit maxSecurityGroupRules
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 8abe03a..ff9caa3 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class SecurityGroupsTestAdminJSON(base.BaseV2ComputeAdminTest):
@@ -34,7 +34,7 @@
self.client.delete_security_group(securitygroup_id)
@decorators.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1')
- @test.services('network')
+ @utils.services('network')
def test_list_security_groups_list_all_tenants_filter(self):
# Admin can list security groups of all tenants
# List of all security groups created
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index d9a7800..3f06c4e 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -13,9 +13,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common import compute
from tempest.common import waiters
-from tempest.lib.common import fixed_network
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
@@ -126,26 +124,17 @@
@decorators.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
def test_list_servers_filter_by_exist_host(self):
# Filter the list of servers by existent host
- name = data_utils.rand_name(self.__class__.__name__ + '-server')
- network = self.get_tenant_network()
- network_kwargs = fixed_network.set_networks_kwarg(network)
- # We need to create the server as an admin, so we can't use
- # self.create_test_server() here as this method creates the server
- # in the "primary" (i.e non-admin) tenant.
- test_server, _ = compute.create_test_server(
- self.os_admin, wait_until="ACTIVE", name=name, **network_kwargs)
- self.addCleanup(self.client.delete_server, test_server['id'])
- server = self.client.show_server(test_server['id'])['server']
- self.assertEqual(server['status'], 'ACTIVE')
+ server = self.client.show_server(self.s1_id)['server']
hostname = server['OS-EXT-SRV-ATTR:host']
- params = {'host': hostname}
- body = self.client.list_servers(**params)
- servers = body['servers']
- nonexistent_params = {'host': 'nonexistent_host'}
+ params = {'host': hostname, 'all_tenants': '1'}
+ servers = self.client.list_servers(**params)['servers']
+ self.assertIn(server['id'], map(lambda x: x['id'], servers))
+
+ nonexistent_params = {'host': 'nonexistent_host',
+ 'all_tenants': '1'}
nonexistent_body = self.client.list_servers(**nonexistent_params)
nonexistent_servers = nonexistent_body['servers']
- self.assertIn(test_server['id'], map(lambda x: x['id'], servers))
- self.assertNotIn(test_server['id'],
+ self.assertNotIn(server['id'],
map(lambda x: x['id'], nonexistent_servers))
@decorators.idempotent_id('ee8ae470-db70-474d-b752-690b7892cab1')
diff --git a/tempest/api/compute/admin/test_servers_on_multinodes.py b/tempest/api/compute/admin/test_servers_on_multinodes.py
index 72f4ddc..2e7b07b 100644
--- a/tempest/api/compute/admin/test_servers_on_multinodes.py
+++ b/tempest/api/compute/admin/test_servers_on_multinodes.py
@@ -76,3 +76,38 @@
wait_until='ACTIVE')['id']
host02 = self._get_host(server02)
self.assertNotEqual(self.host01, host02)
+
+ @decorators.idempotent_id('f8bd0867-e459-45f5-ba53-59134552fe04')
+ @testtools.skipUnless(
+ compute.is_scheduler_filter_enabled("ServerGroupAntiAffinityFilter"),
+ 'ServerGroupAntiAffinityFilter is not available.')
+ def test_create_server_with_scheduler_hint_group_anti_affinity(self):
+ """Tests the ServerGroupAntiAffinityFilter
+
+ Creates two servers in an anti-affinity server group and
+ asserts the servers are in the group and on different hosts.
+ """
+ group_id = self.create_test_server_group(
+ policy=['anti-affinity'])['id']
+ hints = {'group': group_id}
+ reservation_id = self.create_test_server(
+ scheduler_hints=hints, wait_until='ACTIVE', min_count=2,
+ return_reservation_id=True)['reservation_id']
+
+ # Get the servers using the reservation_id.
+ servers = self.servers_client.list_servers(
+ detail=True, reservation_id=reservation_id)['servers']
+ self.assertEqual(2, len(servers))
+
+ # Assert the servers are in the group.
+ server_group = self.server_groups_client.show_server_group(
+ group_id)['server_group']
+ hosts = {}
+ for server in servers:
+ self.assertIn(server['id'], server_group['members'])
+ hosts[server['id']] = self._get_host(server['id'])
+
+ # Assert the servers are on different hosts.
+ hostnames = list(hosts.values())
+ self.assertNotEqual(hostnames[0], hostnames[1],
+ 'Servers are on the same host: %s' % hosts)
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 22a5bc4..d715a42 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -13,11 +13,11 @@
import time
from tempest.api.compute import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -80,7 +80,7 @@
raise lib_exc.TimeoutException(message)
@decorators.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813')
- @test.services('volume')
+ @utils.services('volume')
def test_volume_swap(self):
# Create two volumes.
# NOTE(gmann): Volumes are created before server creation so that
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index feabe35..746f83a 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -97,8 +97,8 @@
cls.security_group_default_rules_client = (
cls.os_primary.security_group_default_rules_client)
cls.versions_client = cls.os_primary.compute_versions_client
-
- cls.volumes_client = cls.os_primary.volumes_v2_client
+ if CONF.service_available.cinder:
+ cls.volumes_client = cls.os_primary.volumes_client_latest
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
index ebb9d2e..efd4f0e 100644
--- a/tempest/api/compute/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -19,11 +19,11 @@
from tempest.api.compute import base
from tempest.common import image as common_image
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -43,7 +43,7 @@
'[image-feature-enabled].')
@decorators.attr(type=['negative'])
- @test.services('image')
+ @utils.services('image')
@decorators.idempotent_id('90f0d93a-91c1-450c-91e6-07d18172cefe')
def test_boot_with_low_ram(self):
"""Try boot a vm with lower than min ram
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index faa7b5d..4001e26 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -16,11 +16,11 @@
import testtools
from tempest.api.compute.floating_ips import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -62,7 +62,7 @@
super(FloatingIPsTestJSON, cls).resource_cleanup()
@decorators.idempotent_id('f7bfb946-297e-41b8-9e8c-aba8e9bb5194')
- @test.services('network')
+ @utils.services('network')
def test_allocate_floating_ip(self):
# Positive test:Allocation of a new floating IP to a project
# should be successful
@@ -78,7 +78,7 @@
self.assertIn(floating_ip_details, body)
@decorators.idempotent_id('de45e989-b5ca-4a9b-916b-04a52e7bbb8b')
- @test.services('network')
+ @utils.services('network')
def test_delete_floating_ip(self):
# Positive test:Deletion of valid floating IP from project
# should be successful
@@ -93,7 +93,7 @@
self.client.wait_for_resource_deletion(floating_ip_body['id'])
@decorators.idempotent_id('307efa27-dc6f-48a0-8cd2-162ce3ef0b52')
- @test.services('network')
+ @utils.services('network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_associate_disassociate_floating_ip(self):
@@ -116,7 +116,7 @@
self.server_id)
@decorators.idempotent_id('6edef4b2-aaf1-4abc-bbe3-993e2561e0fe')
- @test.services('network')
+ @utils.services('network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_associate_already_associated_floating_ip(self):
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index 483bd95..3455a81 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -16,11 +16,11 @@
import testtools
from tempest.api.compute.floating_ips import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -58,7 +58,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('6e0f059b-e4dd-48fb-8207-06e3bba5b074')
- @test.services('network')
+ @utils.services('network')
def test_allocate_floating_ip_from_nonexistent_pool(self):
# Negative test:Allocation of a new floating IP from a nonexistent_pool
# to a project should fail
@@ -68,7 +68,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('ae1c55a8-552b-44d4-bfb6-2a115a15d0ba')
- @test.services('network')
+ @utils.services('network')
def test_delete_nonexistent_floating_ip(self):
# Negative test:Deletion of a nonexistent floating IP
# from project should fail
@@ -79,7 +79,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('595fa616-1a71-4670-9614-46564ac49a4c')
- @test.services('network')
+ @utils.services('network')
def test_associate_nonexistent_floating_ip(self):
# Negative test:Association of a non existent floating IP
# to specific server should fail
@@ -90,7 +90,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('0a081a66-e568-4e6b-aa62-9587a876dca8')
- @test.services('network')
+ @utils.services('network')
def test_dissociate_nonexistent_floating_ip(self):
# Negative test:Dissociation of a non existent floating IP should fail
# Dissociating non existent floating IP
@@ -100,7 +100,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('804b4fcb-bbf5-412f-925d-896672b61eb3')
- @test.services('network')
+ @utils.services('network')
def test_associate_ip_to_server_without_passing_floating_ip(self):
# Negative test:Association of empty floating IP to specific server
# should raise NotFound or BadRequest(In case of Nova V2.1) exception.
@@ -110,7 +110,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('58a80596-ffb2-11e6-9393-fa163e4fa634')
- @test.services('network')
+ @utils.services('network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_associate_ip_to_server_with_floating_ip(self):
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index 913b992..04d18c0 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -53,7 +53,7 @@
super(FloatingIPDetailsTestJSON, cls).resource_cleanup()
@decorators.idempotent_id('16db31c3-fb85-40c9-bbe2-8cf7b67ff99f')
- @test.services('network')
+ @utils.services('network')
def test_list_floating_ips(self):
# Positive test:Should return the list of floating IPs
body = self.client.list_floating_ips()['floating_ips']
@@ -64,7 +64,7 @@
self.assertIn(self.floating_ip[i], floating_ips)
@decorators.idempotent_id('eef497e0-8ff7-43c8-85ef-558440574f84')
- @test.services('network')
+ @utils.services('network')
def test_get_floating_ip_details(self):
# Positive test:Should be able to GET the details of floatingIP
# Creating a floating IP for which details are to be checked
@@ -86,7 +86,7 @@
self.assertEqual(floating_ip_id, body['id'])
@decorators.idempotent_id('df389fc8-56f5-43cc-b290-20eda39854d3')
- @test.services('network')
+ @utils.services('network')
def test_list_floating_ip_pools(self):
# Positive test:Should return the list of floating IP Pools
floating_ip_pools = self.pools_client.list_floating_ip_pools()
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index b5bbb8c..f0b9fa5 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -14,11 +14,11 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -38,7 +38,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('7ab18834-4a4b-4f28-a2c5-440579866695')
- @test.services('network')
+ @utils.services('network')
def test_get_nonexistent_floating_ip_details(self):
# Negative test:Should not be able to GET the details
# of non-existent floating IP
diff --git a/tempest/api/compute/security_groups/base.py b/tempest/api/compute/security_groups/base.py
index 6148e16..5260a99 100644
--- a/tempest/api/compute/security_groups/base.py
+++ b/tempest/api/compute/security_groups/base.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
-from tempest import test
CONF = config.CONF
@@ -32,7 +32,7 @@
@staticmethod
def generate_random_security_group_id():
if (CONF.service_available.neutron and
- test.is_extension_enabled('security-group', 'network')):
+ utils.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_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 124db0e..06edc1c 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -14,8 +14,8 @@
# under the License.
from tempest.api.compute.security_groups import base
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class SecurityGroupRulesTestJSON(base.BaseSecurityGroupsTest):
@@ -55,7 +55,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('850795d7-d4d3-4e55-b527-a774c0123d3a')
- @test.services('network')
+ @utils.services('network')
def test_security_group_rules_create(self):
# Positive test: Creation of Security Group rule
# should be successful
@@ -73,7 +73,7 @@
self._check_expected_response(rule)
@decorators.idempotent_id('7a01873e-3c38-4f30-80be-31a043cfe2fd')
- @test.services('network')
+ @utils.services('network')
def test_security_group_rules_create_with_optional_cidr(self):
# Positive test: Creation of Security Group rule
# with optional argument cidr
@@ -96,7 +96,7 @@
self._check_expected_response(rule)
@decorators.idempotent_id('7f5d2899-7705-4d4b-8458-4505188ffab6')
- @test.services('network')
+ @utils.services('network')
def test_security_group_rules_create_with_optional_group_id(self):
# Positive test: Creation of Security Group rule
# with optional argument group_id
@@ -125,7 +125,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('a6154130-5a55-4850-8be4-5e9e796dbf17')
- @test.services('network')
+ @utils.services('network')
def test_security_group_rules_list(self):
# Positive test: Created Security Group rules should be
# in the list of all rules
@@ -163,7 +163,7 @@
self.assertNotEmpty([i for i in rules if i['id'] == rule2_id])
@decorators.idempotent_id('fc5c5acf-2091-43a6-a6ae-e42760e9ffaf')
- @test.services('network')
+ @utils.services('network')
def test_security_group_rules_delete_when_peer_group_deleted(self):
# Positive test:rule will delete when peer group deleting
# Creating a Security Group to add rules to it
@@ -178,7 +178,7 @@
ip_protocol=self.ip_protocol,
from_port=self.from_port,
to_port=self.to_port,
- group_id=sg2_id)['security_group_rule']
+ group_id=sg2_id)
# Delete group2
self.security_groups_client.delete_security_group(sg2_id)
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 4efb8b7..f344d84 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
@@ -14,10 +14,10 @@
# under the License.
from tempest.api.compute.security_groups import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class SecurityGroupRulesNegativeTestJSON(base.BaseSecurityGroupsTest):
@@ -29,7 +29,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('1d507e98-7951-469b-82c3-23f1e6b8c254')
- @test.services('network')
+ @utils.services('network')
def test_create_security_group_rule_with_non_existent_id(self):
# Negative test: Creation of Security Group rule should FAIL
# with non existent Parent group id
@@ -46,7 +46,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('2244d7e4-adb7-4ecb-9930-2d77e123ce4f')
- @test.services('network')
+ @utils.services('network')
def test_create_security_group_rule_with_invalid_id(self):
# Negative test: Creation of Security Group rule should FAIL
# with Parent group id which is not integer
@@ -63,7 +63,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('8bd56d02-3ffa-4d67-9933-b6b9a01d6089')
- @test.services('network')
+ @utils.services('network')
def test_create_security_group_rule_duplicate(self):
# Negative test: Create Security Group rule duplicate should fail
# Creating a Security Group to add rule to it
@@ -88,7 +88,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('84c81249-9f6e-439c-9bbf-cbb0d2cddbdf')
- @test.services('network')
+ @utils.services('network')
def test_create_security_group_rule_with_invalid_ip_protocol(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid ip_protocol
@@ -108,7 +108,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('12bbc875-1045-4f7a-be46-751277baedb9')
- @test.services('network')
+ @utils.services('network')
def test_create_security_group_rule_with_invalid_from_port(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid from_port
@@ -127,7 +127,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('ff88804d-144f-45d1-bf59-dd155838a43a')
- @test.services('network')
+ @utils.services('network')
def test_create_security_group_rule_with_invalid_to_port(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid to_port
@@ -146,7 +146,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('00296fa9-0576-496a-ae15-fbab843189e0')
- @test.services('network')
+ @utils.services('network')
def test_create_security_group_rule_with_invalid_port_range(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid port range.
@@ -165,7 +165,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('56fddcca-dbb8-4494-a0db-96e9f869527c')
- @test.services('network')
+ @utils.services('network')
def test_delete_security_group_rule_with_non_existent_id(self):
# Negative test: Deletion of Security Group rule should be FAIL
# with non existent id
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index a101a19..01b19ca 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -14,11 +14,11 @@
# under the License.
from tempest.api.compute.security_groups import base
+from tempest.common import utils
from tempest.common import waiters
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class SecurityGroupsTestJSON(base.BaseSecurityGroupsTest):
@@ -30,7 +30,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('eb2b087d-633d-4d0d-a7bd-9e6ba35b32de')
- @test.services('network')
+ @utils.services('network')
def test_security_groups_create_list_delete(self):
# Positive test:Should return the list of Security Groups
# Create 3 Security Groups
@@ -62,7 +62,7 @@
for m_group in deleted_sgs))
@decorators.idempotent_id('ecc0da4a-2117-48af-91af-993cca39a615')
- @test.services('network')
+ @utils.services('network')
def test_security_group_create_get_delete(self):
# Security Group should be created, fetched and deleted
# with char space between name along with
@@ -83,7 +83,7 @@
self.client.wait_for_resource_deletion(securitygroup['id'])
@decorators.idempotent_id('fe4abc0d-83f5-4c50-ad11-57a1127297a2')
- @test.services('network')
+ @utils.services('network')
def test_server_security_groups(self):
# Checks that security groups may be added and linked to a server
# and not deleted if the server is active.
@@ -125,7 +125,7 @@
self.client.delete_security_group(sg2['id'])
@decorators.idempotent_id('7d4e1d3c-3209-4d6d-b020-986304ebad1f')
- @test.services('network')
+ @utils.services('network')
def test_update_security_groups(self):
# Update security group name and description
# Create a security group
@@ -144,7 +144,7 @@
self.assertEqual(s_new_des, fetched_group['description'])
@decorators.idempotent_id('79517d60-535a-438f-af3d-e6feab1cbea7')
- @test.services('network')
+ @utils.services('network')
def test_list_security_groups_by_server(self):
# Create a couple security groups that we will use
# for the server resource this test creates
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index c4dff15..e727dbb 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -16,11 +16,11 @@
import testtools
from tempest.api.compute.security_groups import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -34,7 +34,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('673eaec1-9b3e-48ed-bdf1-2786c1b9661c')
- @test.services('network')
+ @utils.services('network')
def test_security_group_get_nonexistent_group(self):
# Negative test:Should not be able to GET the details
# of non-existent Security Group
@@ -46,7 +46,7 @@
condition=CONF.service_available.neutron)
@decorators.attr(type=['negative'])
@decorators.idempotent_id('1759c3cb-b0fc-44b7-86ce-c99236be911d')
- @test.services('network')
+ @utils.services('network')
def test_security_group_create_with_invalid_group_name(self):
# Negative test: Security Group should not be created with group name
# as an empty string/with white spaces/chars more than 255
@@ -69,7 +69,7 @@
condition=CONF.service_available.neutron)
@decorators.attr(type=['negative'])
@decorators.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
- @test.services('network')
+ @utils.services('network')
def test_security_group_create_with_invalid_group_description(self):
# Negative test: Security Group should not be created with description
# longer than 255 chars. Empty description is allowed by the API
@@ -85,7 +85,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron allows duplicate names for security groups")
@decorators.attr(type=['negative'])
- @test.services('network')
+ @utils.services('network')
def test_security_group_create_with_duplicate_name(self):
# Negative test:Security Group with duplicate name should not
# be created
@@ -99,7 +99,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('36a1629f-c6da-4a26-b8b8-55e7e5d5cd58')
- @test.services('network')
+ @utils.services('network')
def test_delete_the_default_security_group(self):
# Negative test:Deletion of the "default" Security Group should Fail
default_security_group_id = None
@@ -115,7 +115,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('6727c00b-214c-4f9e-9a52-017ac3e98411')
- @test.services('network')
+ @utils.services('network')
def test_delete_nonexistent_security_group(self):
# Negative test:Deletion of a non-existent Security Group should fail
non_exist_id = self.generate_random_security_group_id()
@@ -124,7 +124,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('1438f330-8fa4-4aeb-8a94-37c250106d7f')
- @test.services('network')
+ @utils.services('network')
def test_delete_security_group_without_passing_id(self):
# Negative test:Deletion of a Security Group with out passing ID
# should Fail
@@ -135,7 +135,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron does not check the security group ID")
@decorators.attr(type=['negative'])
- @test.services('network')
+ @utils.services('network')
def test_update_security_group_with_invalid_sg_id(self):
# Update security_group with invalid sg_id should fail
s_name = data_utils.rand_name('sg')
@@ -150,7 +150,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron does not check the security group name")
@decorators.attr(type=['negative'])
- @test.services('network')
+ @utils.services('network')
def test_update_security_group_with_invalid_sg_name(self):
# Update security_group with invalid sg_name should fail
securitygroup = self.create_security_group()
@@ -165,7 +165,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron does not check the security group description")
@decorators.attr(type=['negative'])
- @test.services('network')
+ @utils.services('network')
def test_update_security_group_with_invalid_sg_des(self):
# Update security_group with invalid sg_des should fail
securitygroup = self.create_security_group()
@@ -178,7 +178,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('27edee9c-873d-4da6-a68a-3c256efebe8f')
- @test.services('network')
+ @utils.services('network')
def test_update_non_existent_security_group(self):
# Update a non-existent Security Group should Fail
non_exist_id = self.generate_random_security_group_id()
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index bfde847..69b6e51 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -19,12 +19,12 @@
from tempest.api.compute import base
from tempest.common import compute
+from tempest.common import utils
from tempest.common.utils import net_utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -185,7 +185,7 @@
self.assertEqual(sorted(list1), sorted(list2))
@decorators.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
- @test.services('network')
+ @utils.services('network')
def test_create_list_show_delete_interfaces(self):
server, ifs = self._create_server_get_interfaces()
interface_count = len(ifs)
@@ -222,7 +222,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
- @test.services('network')
+ @utils.services('network')
def test_add_remove_fixed_ip(self):
# Add and Remove the fixed IP to server.
server, ifs = self._create_server_get_interfaces()
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index b727ddd..d8ce7ea 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -17,12 +17,11 @@
import testtools
from tempest.api.compute import base
-from tempest.common import compute
+from tempest.common import utils
from tempest.common.utils.linux import remote_client
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -133,22 +132,6 @@
'hostname "%s" but got "%s".' % (self.name, hostname))
self.assertEqual(self.name.lower(), hostname, msg)
- @decorators.idempotent_id('ed20d3fb-9d1f-4329-b160-543fbd5d9811')
- @testtools.skipUnless(
- compute.is_scheduler_filter_enabled("ServerGroupAffinityFilter"),
- 'ServerGroupAffinityFilter is not available.')
- def test_create_server_with_scheduler_hint_group(self):
- # Create a server with the scheduler hint "group".
- group_id = self.create_test_server_group()['id']
- hints = {'group': group_id}
- server = self.create_test_server(scheduler_hints=hints,
- wait_until='ACTIVE')
-
- # Check a server is in the group
- server_group = (self.server_groups_client.show_server_group(group_id)
- ['server_group'])
- self.assertIn(server['id'], server_group['members'])
-
class ServersTestManualDisk(ServersTestJSON):
disk_config = 'MANUAL'
@@ -168,6 +151,6 @@
@classmethod
def skip_checks(cls):
super(ServersTestBootFromVolume, cls).skip_checks()
- if not test.get_service_list()['volume']:
+ if not utils.get_service_list()['volume']:
msg = "Volume service not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 2b03b2b..0093752 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -17,10 +17,10 @@
from tempest.api.compute import base
from tempest.common import compute
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -104,7 +104,7 @@
waiters.wait_for_server_termination(self.client, server['id'])
@decorators.idempotent_id('d0f3f0d6-d9b6-4a32-8da4-23015dcab23c')
- @test.services('volume')
+ @utils.services('volume')
def test_delete_server_while_in_attached_volume(self):
# Delete a server while a volume is attached to it
device = '/dev/%s' % CONF.compute.volume_device_name
diff --git a/tempest/api/compute/servers/test_device_tagging.py b/tempest/api/compute/servers/test_device_tagging.py
index 7ee1b02..dbf6713 100644
--- a/tempest/api/compute/servers/test_device_tagging.py
+++ b/tempest/api/compute/servers/test_device_tagging.py
@@ -17,13 +17,13 @@
from oslo_log import log as logging
from tempest.api.compute import base
+from tempest.common import utils
from tempest.common.utils.linux import remote_client
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions
-from tempest import test
CONF = config.CONF
@@ -94,7 +94,7 @@
'other']))
@decorators.idempotent_id('a2e65a6c-66f1-4442-aaa8-498c31778d96')
- @test.services('network', 'volume', 'image')
+ @utils.services('network', 'volume', 'image')
def test_device_tagging(self):
# Create volumes
# The create_volume methods waits for the volumes to be available and
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index a4ed8e1..14aecfd 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -262,7 +262,7 @@
# so as to ensure only one server is returned.
ip_list = {}
self.s1 = self.client.show_server(self.s1['id'])['server']
- # Get first ip address inspite of v4 or v6
+ # Get first ip address in spite of v4 or v6
ip_addr = self.s1['addresses'][self.fixed_network_name][0]['addr']
ip_list[ip_addr] = self.s1['id']
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index 90b0665..d9581e3 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -166,7 +166,7 @@
self._validate_novnc_html(body['url'])
# Do the WebSockify HTTP Request to novncproxy to do the RFB connection
self._websocket = compute.create_websocket(body['url'])
- # Validate that we succesfully connected and upgraded to Web Sockets
+ # Validate that we successfully connected and upgraded to Web Sockets
self._validate_websocket_upgrade()
# Validate the RFB Negotiation to determine if a valid VNC session
self._validate_rfb_negotiation()
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index f41c3fb..4870a3d 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -19,13 +19,13 @@
from tempest.api.compute import base
from tempest.common import compute
+from tempest.common import utils
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -33,8 +33,6 @@
class ServerActionsTestJSON(base.BaseV2ComputeTest):
- run_ssh = CONF.validation.run_validation
-
def setUp(self):
# NOTE(afazekas): Normally we use the same server with all test cases,
# but if it has an issue, we build a new one
@@ -254,7 +252,7 @@
self.client.start_server(self.server_id)
@decorators.idempotent_id('b68bd8d6-855d-4212-b59b-2e704044dace')
- @test.services('volume')
+ @utils.services('volume')
def test_rebuild_server_with_volume_attached(self):
# create a new volume and attach it to the server
volume = self.create_volume()
@@ -335,7 +333,7 @@
@decorators.idempotent_id('b963d4f1-94b3-4c40-9e97-7b583f46e470')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting not available, backup not possible.')
- @test.services('image')
+ @utils.services('image')
def test_create_backup(self):
# Positive test:create backup successfully and rotate backups correctly
# create the first and the second backup
@@ -520,7 +518,7 @@
@decorators.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
- @test.services('image')
+ @utils.services('image')
def test_shelve_unshelve_server(self):
if CONF.image_feature_enabled.api_v2:
glance_client = self.os_primary.image_client_v2
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 022ceba..f79b05f 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -14,8 +14,8 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class ServerAddressesTestJSON(base.BaseV2ComputeTest):
@@ -39,7 +39,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('6eb718c0-02d9-4d5e-acd1-4e0c269cef39')
- @test.services('network')
+ @utils.services('network')
def test_list_server_addresses(self):
# All public and private addresses for
# a server should be returned
@@ -51,13 +51,10 @@
self.assertNotEmpty(addresses)
for network_addresses in addresses.values():
self.assertNotEmpty(network_addresses)
- for address in network_addresses:
- self.assertTrue(address['addr'])
- self.assertTrue(address['version'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('87bbc374-5538-4f64-b673-2b0e4443cc30')
- @test.services('network')
+ @utils.services('network')
def test_list_server_addresses_by_network(self):
# Providing a network type should filter
# the addresses return by that type
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index 76a102b..b2b3cc0 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class ServerAddressesNegativeTestJSON(base.BaseV2ComputeTest):
@@ -38,7 +38,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('02c3f645-2d2e-4417-8525-68c0407d001b')
- @test.services('network')
+ @utils.services('network')
def test_list_server_addresses_invalid_server_id(self):
# List addresses request should fail if server id not in system
self.assertRaises(lib_exc.NotFound, self.client.list_addresses,
@@ -46,7 +46,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('a2ab5144-78c0-4942-a0ed-cc8edccfd9ba')
- @test.services('network')
+ @utils.services('network')
def test_list_server_addresses_by_network_neg(self):
# List addresses by network should fail if network name not valid
self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index 69d7897..5286c8f 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -13,10 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.api.compute import base
+from tempest.common import compute
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class ServerGroupTestJSON(base.BaseV2ComputeTest):
@@ -30,7 +33,7 @@
@classmethod
def skip_checks(cls):
super(ServerGroupTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('os-server-groups', 'compute'):
+ if not utils.is_extension_enabled('os-server-groups', 'compute'):
msg = "os-server-groups extension is not enabled."
raise cls.skipException(msg)
@@ -106,3 +109,19 @@
# List the server-group
body = self.client.list_server_groups()['server_groups']
self.assertIn(self.created_server_group, body)
+
+ @decorators.idempotent_id('ed20d3fb-9d1f-4329-b160-543fbd5d9811')
+ @testtools.skipUnless(
+ compute.is_scheduler_filter_enabled("ServerGroupAffinityFilter"),
+ 'ServerGroupAffinityFilter is not available.')
+ def test_create_server_with_scheduler_hint_group(self):
+ # Create a server with the scheduler hint "group".
+ hints = {'group': self.created_server_group['id']}
+ server = self.create_test_server(scheduler_hints=hints,
+ wait_until='ACTIVE')
+ self.addCleanup(self.delete_server, server['id'])
+
+ # Check a server is in the group
+ server_group = (self.server_groups_client.show_server_group(
+ self.created_server_group['id'])['server_group'])
+ self.assertIn(server['id'], server_group['members'])
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index f77e7d3..fe95018 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -32,7 +32,7 @@
def setUp(self):
super(ServerMetadataTestJSON, self).setUp()
meta = {'key1': 'value1', 'key2': 'value2'}
- self.client.set_server_metadata(self.server['id'], meta)['metadata']
+ self.client.set_server_metadata(self.server['id'], meta)
@decorators.idempotent_id('479da087-92b3-4dcf-aeb3-fd293b2d14ce')
def test_list_server_metadata(self):
@@ -49,8 +49,7 @@
# The server's metadata should be replaced with the provided values
# Create a new set of metadata for the server
req_metadata = {'meta2': 'data2', 'meta3': 'data3'}
- self.client.set_server_metadata(self.server['id'],
- req_metadata)['metadata']
+ self.client.set_server_metadata(self.server['id'], req_metadata)
# Verify the expected values are correct, and that the
# previous values have been removed
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index 5fac433..1260c6b 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -16,12 +16,12 @@
import testtools
from tempest.api.compute import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -109,7 +109,7 @@
self.image_ref_alt)
@decorators.idempotent_id('d0ccac79-0091-4cf4-a1ce-26162d0cc55f')
- @test.services('volume')
+ @utils.services('volume')
@decorators.attr(type=['negative'])
def test_rescued_vm_attach_volume(self):
volume = self.create_volume()
@@ -129,7 +129,7 @@
device='/dev/%s' % self.device)
@decorators.idempotent_id('f56e465b-fe10-48bf-b75d-646cda3a8bc9')
- @test.services('volume')
+ @utils.services('volume')
@decorators.attr(type=['negative'])
def test_rescued_vm_detach_volume(self):
volume = self.create_volume()
diff --git a/tempest/api/compute/servers/test_server_tags.py b/tempest/api/compute/servers/test_server_tags.py
index 0370215..8d0a4e3 100644
--- a/tempest/api/compute/servers/test_server_tags.py
+++ b/tempest/api/compute/servers/test_server_tags.py
@@ -16,9 +16,9 @@
import six
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class ServerTagsTestJSON(base.BaseV2ComputeTest):
@@ -29,7 +29,7 @@
@classmethod
def skip_checks(cls):
super(ServerTagsTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('os-server-tags', 'compute'):
+ if not utils.is_extension_enabled('os-server-tags', 'compute'):
msg = "os-server-tags extension is not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 764767b..8170b28 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -19,12 +19,12 @@
from tempest.api.compute import base
from tempest.common import compute
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -217,7 +217,7 @@
@decorators.attr(type=['negative'])
@decorators.related_bug('1651064', status_code=500)
- @test.services('volume')
+ @utils.services('volume')
@decorators.idempotent_id('12146ac1-d7df-4928-ad25-b1f99e5286cd')
def test_create_server_invalid_bdm_in_2nd_dict(self):
volume = self.create_volume()
@@ -512,7 +512,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('74085be3-a370-4ca2-bc51-2d0e10e0f573')
- @test.services('volume', 'image')
+ @utils.services('volume', 'image')
def test_create_server_from_non_bootable_volume(self):
# Create a volume
volume = self.create_volume()
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index a42b968..90f04ff 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -17,10 +17,10 @@
import testtools
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions
-from tempest import test
CONF = config.CONF
@@ -44,7 +44,7 @@
cls.server = cls.create_test_server(wait_until='ACTIVE')
@decorators.idempotent_id('96c4e2ef-5e4d-4d7f-87f5-fed6dca18016')
- @test.services('network')
+ @utils.services('network')
def test_list_virtual_interfaces(self):
# Positive test:Should be able to GET the virtual interfaces list
# for a given server_id
@@ -56,11 +56,11 @@
self.client.list_virtual_interfaces(self.server['id'])
else:
output = self.client.list_virtual_interfaces(self.server['id'])
- virt_ifaces = output
- self.assertNotEmpty(virt_ifaces['virtual_interfaces'],
+ virt_ifaces = output['virtual_interfaces']
+ self.assertNotEmpty(virt_ifaces,
'Expected virtual interfaces, got 0 '
'interfaces.')
- for virt_iface in virt_ifaces['virtual_interfaces']:
+ for virt_iface in virt_ifaces:
mac_address = virt_iface['mac_address']
self.assertTrue(netaddr.valid_mac(mac_address),
"Invalid mac address detected. mac address: %s"
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index 173784a..20923a8 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -14,10 +14,10 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class VirtualInterfacesNegativeTestJSON(base.BaseV2ComputeTest):
@@ -35,7 +35,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('64ebd03c-1089-4306-93fa-60f5eb5c803c')
- @test.services('network')
+ @utils.services('network')
def test_list_virtual_interfaces_invalid_server_id(self):
# Negative test: Should not be able to GET virtual interfaces
# for an invalid server_id
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index 42e13bd..34faf5f 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -16,9 +16,9 @@
from oslo_log import log as logging
from tempest.api.compute import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -26,7 +26,7 @@
LOG = logging.getLogger(__name__)
-class ExtensionsTestJSON(base.BaseV2ComputeTest):
+class ExtensionsTest(base.BaseV2ComputeTest):
@decorators.idempotent_id('3bb27738-b759-4e0d-a5fa-37d7a6df07d1')
def test_list_extensions(self):
@@ -48,7 +48,7 @@
raise self.skipException('There are not any extensions configured')
@decorators.idempotent_id('05762f39-bdfa-4cdb-9b46-b78f8e78e2fd')
- @test.requires_ext(extension='os-consoles', service='compute')
+ @utils.requires_ext(extension='os-consoles', service='compute')
def test_get_extension(self):
# get the specified extensions
extension = self.extensions_client.show_extension('os-consoles')
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index 9d83ee1..7cf90ae 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -15,8 +15,8 @@
from tempest.api.compute import base
from tempest.common import tempest_fixtures as fixtures
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class QuotasTestJSON(base.BaseV2ComputeTest):
@@ -24,7 +24,7 @@
@classmethod
def skip_checks(cls):
super(QuotasTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('os-quota-sets', 'compute'):
+ if not utils.is_extension_enabled('os-quota-sets', 'compute'):
msg = "quotas extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/compute/test_tenant_networks.py b/tempest/api/compute/test_tenant_networks.py
index 18c5d38..b55e2c0 100644
--- a/tempest/api/compute/test_tenant_networks.py
+++ b/tempest/api/compute/test_tenant_networks.py
@@ -13,8 +13,8 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class ComputeTenantNetworksTest(base.BaseV2ComputeTest):
@@ -31,7 +31,7 @@
super(ComputeTenantNetworksTest, cls).setup_credentials()
@decorators.idempotent_id('edfea98e-bbe3-4c7a-9739-87b986baff26')
- @test.services('network')
+ @utils.services('network')
def test_list_show_tenant_networks(self):
# Fetch all networks that are visible to the tenant: this may include
# shared and external networks
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index c56d140..e0fed58 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
-
from tempest.api.compute import base
from tempest.common import compute
from tempest.common.utils.linux import remote_client
@@ -159,6 +157,12 @@
min_microversion = '2.20'
max_microversion = 'latest'
+ @classmethod
+ def skip_checks(cls):
+ super(AttachVolumeShelveTestJSON, cls).skip_checks()
+ if not CONF.compute_feature_enabled.shelve:
+ raise cls.skipException('Shelve is not available.')
+
def _count_volumes(self, server):
# Count number of volumes on an instance
volumes = 0
@@ -206,8 +210,6 @@
self.assertEqual(number_of_volumes, counted_volumes)
@decorators.idempotent_id('13a940b6-3474-4c3c-b03f-29b89112bfee')
- @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
- 'Shelve is not available.')
def test_attach_volume_shelved_or_offload_server(self):
# Create server, count number of volumes on it, shelve
# server and attach pre-created volume to shelved server
@@ -233,8 +235,6 @@
self.assertIsNotNone(volume_attachment['device'])
@decorators.idempotent_id('b54e86dd-a070-49c4-9c07-59ae6dae15aa')
- @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
- 'Shelve is not available.')
def test_detach_volume_shelved_or_offload_server(self):
# Count number of volumes on instance, shelve
# server and attach pre-created volume to shelved server
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
index 0f436eb..b8ca81d 100644
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
-
from tempest.api.compute import base
from tempest.common import waiters
from tempest import config
@@ -38,6 +36,9 @@
if not CONF.service_available.cinder:
skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
raise cls.skipException(skip_msg)
+ if not CONF.volume_feature_enabled.snapshot:
+ skip_msg = ("Cinder volume snapshots are disabled")
+ raise cls.skipException(skip_msg)
@classmethod
def setup_clients(cls):
@@ -46,8 +47,6 @@
cls.snapshots_client = cls.snapshots_extensions_client
@decorators.idempotent_id('cd4ec87d-7825-450d-8040-6e2068f2da8f')
- @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
- 'Cinder volume snapshots are disabled')
def test_volume_snapshot_create_get_list_delete(self):
volume = self.create_volume()
self.addCleanup(self.delete_volume, volume['id'])
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 1a0b851..56f7d32 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -20,7 +20,6 @@
class DomainsNegativeTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@decorators.attr(type=['negative', 'gate'])
@decorators.idempotent_id('1f3fbff5-4e44-400d-9ca1-d953f05f609b')
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index 49b6585..8b687cd 100644
--- a/tempest/api/identity/admin/v3/test_inherits.py
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -11,22 +11,22 @@
# under the License.
from tempest.api.identity import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
-class BaseInheritsV3Test(base.BaseIdentityV3AdminTest):
+class InheritsV3TestJSON(base.BaseIdentityV3AdminTest):
@classmethod
def skip_checks(cls):
- super(BaseInheritsV3Test, cls).skip_checks()
- if not test.is_extension_enabled('OS-INHERIT', 'identity'):
+ super(InheritsV3TestJSON, cls).skip_checks()
+ if not utils.is_extension_enabled('OS-INHERIT', 'identity'):
raise cls.skipException("Inherits aren't enabled")
@classmethod
def resource_setup(cls):
- super(BaseInheritsV3Test, cls).resource_setup()
+ super(InheritsV3TestJSON, cls).resource_setup()
u_name = data_utils.rand_name('user-')
u_desc = '%s description' % u_name
u_email = '%s@testmail.tm' % u_name
@@ -51,15 +51,12 @@
cls.projects_client.delete_project(cls.project['id'])
cls.domains_client.update_domain(cls.domain['id'], enabled=False)
cls.domains_client.delete_domain(cls.domain['id'])
- super(BaseInheritsV3Test, cls).resource_cleanup()
+ super(InheritsV3TestJSON, cls).resource_cleanup()
def _list_assertions(self, body, fetched_role_ids, role_id):
self.assertEqual(len(body), 1)
self.assertIn(role_id, fetched_role_ids)
-
-class InheritsV3TestJSON(BaseInheritsV3Test):
-
@decorators.idempotent_id('4e6f0366-97c8-423c-b2be-41eae6ac91c8')
def test_inherit_assign_list_check_revoke_roles_on_domains_user(self):
# Create role
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 850e549..2530072 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -26,25 +26,27 @@
CONF = config.CONF
-class BaseTrustsV3Test(base.BaseIdentityV3AdminTest):
+class TrustsV3TestJSON(base.BaseIdentityV3AdminTest):
@classmethod
def skip_checks(cls):
- super(BaseTrustsV3Test, cls).skip_checks()
+ super(TrustsV3TestJSON, cls).skip_checks()
if not CONF.identity_feature_enabled.trust:
raise cls.skipException("Trusts aren't enabled")
def setUp(self):
- super(BaseTrustsV3Test, self).setUp()
+ super(TrustsV3TestJSON, self).setUp()
# Use alt_username as the trustee
self.trust_id = None
+ self.create_trustor_and_roles()
+ self.addCleanup(self.cleanup_user_and_roles)
def tearDown(self):
if self.trust_id:
# Do the delete in tearDown not addCleanup - we want the test to
# fail in the event there is a bug which causes undeletable trusts
self.delete_trust()
- super(BaseTrustsV3Test, self).tearDown()
+ super(TrustsV3TestJSON, self).tearDown()
def create_trustor_and_roles(self):
# create a project that trusts will be granted on
@@ -193,14 +195,6 @@
self.trust_id)
self.trust_id = None
-
-class TrustsV3TestJSON(BaseTrustsV3Test):
-
- def setUp(self):
- super(TrustsV3TestJSON, self).setUp()
- self.create_trustor_and_roles()
- self.addCleanup(self.cleanup_user_and_roles)
-
@decorators.idempotent_id('5a0a91a4-baef-4a14-baba-59bf4d7fcace')
def test_trust_impersonate(self):
# Test case to check we can create, get and delete a trust
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 409d4f8..3813568 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -41,31 +41,26 @@
email=u_email, enabled=False)['user']
# Delete the User at the end of this method
self.addCleanup(self.users_client.delete_user, user['id'])
+
# Creating second project for updation
project = self.setup_test_project()
+
# Updating user details with new values
- u_name2 = data_utils.rand_name('user2')
- u_email2 = u_name2 + '@testmail.tm'
- u_description2 = u_name2 + ' description'
- update_user = self.users_client.update_user(
- user['id'], name=u_name2, description=u_description2,
- project_id=project['id'],
- email=u_email2, enabled=False)['user']
- self.assertEqual(u_name2, update_user['name'])
- self.assertEqual(u_description2, update_user['description'])
- self.assertEqual(project['id'],
- update_user['project_id'])
- self.assertEqual(u_email2, update_user['email'])
- self.assertEqual(False, update_user['enabled'])
- # GET by id after updation
+ update_kwargs = {'name': data_utils.rand_name('user2'),
+ 'description': data_utils.rand_name('desc2'),
+ 'project_id': project['id'],
+ 'email': 'user2@testmail.tm',
+ 'enabled': False}
+ updated_user = self.users_client.update_user(
+ user['id'], **update_kwargs)['user']
+ for field in update_kwargs:
+ self.assertEqual(update_kwargs[field], updated_user[field])
+
+ # GET by id after updating
new_user_get = self.users_client.show_user(user['id'])['user']
# Assert response body of GET after updation
- self.assertEqual(u_name2, new_user_get['name'])
- self.assertEqual(u_description2, new_user_get['description'])
- self.assertEqual(project['id'],
- new_user_get['project_id'])
- self.assertEqual(u_email2, new_user_get['email'])
- self.assertEqual(False, new_user_get['enabled'])
+ for field in update_kwargs:
+ self.assertEqual(update_kwargs[field], new_user_get[field])
@decorators.idempotent_id('2d223a0e-e457-4a70-9fb1-febe027a0ff9')
def test_update_user_password(self):
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
index 599b784..237e728 100644
--- a/tempest/api/identity/v2/test_ec2_credentials.py
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.identity import base
+from tempest.common import utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class EC2CredentialsTest(base.BaseIdentityV2Test):
@@ -24,7 +24,7 @@
@classmethod
def skip_checks(cls):
super(EC2CredentialsTest, cls).skip_checks()
- if not test.is_extension_enabled('OS-EC2', 'identity'):
+ if not utils.is_extension_enabled('OS-EC2', 'identity'):
msg = "OS-EC2 identity extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 2e68efd..c846f88 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -119,7 +119,7 @@
# Update Image
new_image_name = data_utils.rand_name('new-image')
- body = self.client.update_image(image['id'], [
+ self.client.update_image(image['id'], [
dict(replace='/name', value=new_image_name)])
# Verifying updating
diff --git a/tempest/api/network/admin/test_agent_management.py b/tempest/api/network/admin/test_agent_management.py
index 7304db9..5068fc4 100644
--- a/tempest/api/network/admin/test_agent_management.py
+++ b/tempest/api/network/admin/test_agent_management.py
@@ -14,8 +14,8 @@
from tempest.api.network import base
from tempest.common import tempest_fixtures as fixtures
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class AgentManagementTestJSON(base.BaseAdminNetworkTest):
@@ -23,7 +23,7 @@
@classmethod
def skip_checks(cls):
super(AgentManagementTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('agent', 'network'):
+ if not utils.is_extension_enabled('agent', 'network'):
msg = "agent extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index 485c8f5..8315c5d 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -13,8 +13,8 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class DHCPAgentSchedulersTestJSON(base.BaseAdminNetworkTest):
@@ -22,7 +22,7 @@
@classmethod
def skip_checks(cls):
super(DHCPAgentSchedulersTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('dhcp_agent_scheduler', 'network'):
+ if not utils.is_extension_enabled('dhcp_agent_scheduler', 'network'):
msg = "dhcp_agent_scheduler extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
index 7ee819e..5aa337c 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -28,7 +28,7 @@
@classmethod
def skip_checks(cls):
super(FloatingIPAdminTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('router', 'network'):
+ if not utils.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
if not CONF.network.public_network_id:
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index 85b2472..1a7b0ec 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -13,10 +13,10 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions
-from tempest import test
CONF = config.CONF
AGENT_TYPE = 'L3 agent'
@@ -41,7 +41,7 @@
@classmethod
def skip_checks(cls):
super(L3AgentSchedulerTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('l3_agent_scheduler', 'network'):
+ if not utils.is_extension_enabled('l3_agent_scheduler', 'network'):
msg = "L3 Agent Scheduler Extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/admin/test_metering_extensions.py b/tempest/api/network/admin/test_metering_extensions.py
index 21a7ab4..fd86782 100644
--- a/tempest/api/network/admin/test_metering_extensions.py
+++ b/tempest/api/network/admin/test_metering_extensions.py
@@ -13,9 +13,9 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class MeteringTestJSON(base.BaseAdminNetworkTest):
@@ -28,7 +28,7 @@
@classmethod
def skip_checks(cls):
super(MeteringTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('metering', 'network'):
+ if not utils.is_extension_enabled('metering', 'network'):
msg = "metering extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index 21688d2..6849653 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class QuotasNegativeTest(base.BaseAdminNetworkTest):
@@ -35,7 +35,7 @@
@classmethod
def skip_checks(cls):
super(QuotasNegativeTest, cls).skip_checks()
- if not test.is_extension_enabled('quotas', 'network'):
+ if not utils.is_extension_enabled('quotas', 'network'):
msg = "quotas extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index aa8b2dc..f69d7c5 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -14,10 +14,10 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
-from tempest import test
class QuotasTest(base.BaseAdminNetworkTest):
@@ -38,7 +38,7 @@
@classmethod
def skip_checks(cls):
super(QuotasTest, cls).skip_checks()
- if not test.is_extension_enabled('quotas', 'network'):
+ if not utils.is_extension_enabled('quotas', 'network'):
msg = "quotas extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/admin/test_routers.py b/tempest/api/network/admin/test_routers.py
index f180cda..c97efe9 100644
--- a/tempest/api/network/admin/test_routers.py
+++ b/tempest/api/network/admin/test_routers.py
@@ -16,10 +16,10 @@
import testtools
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -57,7 +57,7 @@
@classmethod
def skip_checks(cls):
super(RoutersAdminTest, cls).skip_checks()
- if not test.is_extension_enabled('router', 'network'):
+ if not utils.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
@@ -79,7 +79,7 @@
self.assertEqual(project_id, create_body['router']['tenant_id'])
@decorators.idempotent_id('847257cc-6afd-4154-b8fb-af49f5670ce8')
- @test.requires_ext(extension='ext-gw-mode', service='network')
+ @utils.requires_ext(extension='ext-gw-mode', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_create_router_with_default_snat_value(self):
@@ -91,7 +91,7 @@
'enable_snat': True})
@decorators.idempotent_id('ea74068d-09e9-4fd7-8995-9b6a1ace920f')
- @test.requires_ext(extension='ext-gw-mode', service='network')
+ @utils.requires_ext(extension='ext-gw-mode', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_create_router_with_snat_explicit(self):
@@ -153,7 +153,7 @@
self._verify_gateway_port(router['id'])
@decorators.idempotent_id('b386c111-3b21-466d-880c-5e72b01e1a33')
- @test.requires_ext(extension='ext-gw-mode', service='network')
+ @utils.requires_ext(extension='ext-gw-mode', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_update_router_set_gateway_with_snat_explicit(self):
@@ -170,7 +170,7 @@
self._verify_gateway_port(router['id'])
@decorators.idempotent_id('96536bc7-8262-4fb2-9967-5c46940fa279')
- @test.requires_ext(extension='ext-gw-mode', service='network')
+ @utils.requires_ext(extension='ext-gw-mode', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_update_router_set_gateway_without_snat(self):
@@ -202,7 +202,7 @@
self.assertFalse(list_body['ports'])
@decorators.idempotent_id('f2faf994-97f4-410b-a831-9bc977b64374')
- @test.requires_ext(extension='ext-gw-mode', service='network')
+ @utils.requires_ext(extension='ext-gw-mode', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_update_router_reset_gateway_without_snat(self):
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
index b6772b1..93478e6 100644
--- a/tempest/api/network/admin/test_routers_dvr.py
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -16,9 +16,9 @@
import testtools
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class RoutersTestDVR(base.BaseAdminNetworkTest):
@@ -27,7 +27,7 @@
def skip_checks(cls):
super(RoutersTestDVR, cls).skip_checks()
for ext in ['router', 'dvr']:
- if not test.is_extension_enabled(ext, 'network'):
+ if not utils.is_extension_enabled(ext, 'network'):
msg = "%s extension not enabled." % ext
raise cls.skipException(msg)
# The check above will pass if api_extensions=all, which does
@@ -87,7 +87,7 @@
self.assertFalse(router['router']['distributed'])
@decorators.idempotent_id('acd43596-c1fb-439d-ada8-31ad48ae3c2e')
- @testtools.skipUnless(test.is_extension_enabled('l3-ha', 'network'),
+ @testtools.skipUnless(utils.is_extension_enabled('l3-ha', 'network'),
'HA routers are not available.')
def test_centralized_router_update_to_dvr(self):
"""Test centralized router update
diff --git a/tempest/api/network/admin/test_routers_negative.py b/tempest/api/network/admin/test_routers_negative.py
index f350a15..9356bcc 100644
--- a/tempest/api/network/admin/test_routers_negative.py
+++ b/tempest/api/network/admin/test_routers_negative.py
@@ -16,10 +16,10 @@
import testtools
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -29,13 +29,13 @@
@classmethod
def skip_checks(cls):
super(RoutersAdminNegativeTest, cls).skip_checks()
- if not test.is_extension_enabled('router', 'network'):
+ if not utils.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
@decorators.attr(type=['negative'])
@decorators.idempotent_id('7101cc02-058a-11e7-93e1-fa163e4fa634')
- @test.requires_ext(extension='ext-gw-mode', service='network')
+ @utils.requires_ext(extension='ext-gw-mode', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_router_set_gateway_used_ip_returns_409(self):
diff --git a/tempest/api/network/test_allowed_address_pair.py b/tempest/api/network/test_allowed_address_pair.py
index a90e4bf..a471bd6 100644
--- a/tempest/api/network/test_allowed_address_pair.py
+++ b/tempest/api/network/test_allowed_address_pair.py
@@ -17,9 +17,9 @@
import six
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -41,10 +41,12 @@
api_extensions
"""
+ _project_network_cidr = CONF.network.project_network_cidr
+
@classmethod
def skip_checks(cls):
super(AllowedAddressPairTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('allowed-address-pairs', 'network'):
+ if not utils.is_extension_enabled('allowed-address-pairs', 'network'):
msg = "Allowed Address Pairs extension not enabled."
raise cls.skipException(msg)
@@ -103,7 +105,7 @@
@decorators.idempotent_id('4d6d178f-34f6-4bff-a01c-0a2f8fe909e4')
def test_update_port_with_cidr_address_pair(self):
# Update allowed address pair with cidr
- cidr = str(netaddr.IPNetwork(CONF.network.project_network_cidr))
+ cidr = str(netaddr.IPNetwork(self._project_network_cidr))
self._update_port_with_address(cidr)
@decorators.idempotent_id('b3f20091-6cd5-472b-8487-3516137df933')
@@ -133,3 +135,4 @@
class AllowedAddressPairIpV6TestJSON(AllowedAddressPairTestJSON):
_ip_version = 6
+ _project_network_cidr = CONF.network.project_network_v6_cidr
diff --git a/tempest/api/network/test_extensions.py b/tempest/api/network/test_extensions.py
index 014d064..4804ada 100644
--- a/tempest/api/network/test_extensions.py
+++ b/tempest/api/network/test_extensions.py
@@ -15,8 +15,8 @@
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class ExtensionsTestJSON(base.BaseNetworkTest):
@@ -40,7 +40,7 @@
'allowed-address-pairs', 'extra_dhcp_opt',
'metering', 'dvr']
expected_alias = [ext for ext in expected_alias if
- test.is_extension_enabled(ext, 'network')]
+ utils.is_extension_enabled(ext, 'network')]
actual_alias = list()
extensions = self.network_extensions_client.list_extensions()
list_extensions = extensions['extensions']
@@ -66,5 +66,5 @@
# of extensions returned, but only for those that have been
# enabled via configuration
for e in expected_alias:
- if test.is_extension_enabled(e, 'network'):
+ if utils.is_extension_enabled(e, 'network'):
self.assertIn(e, actual_alias)
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index dc9042e..0d42033 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class ExtraDHCPOptionsTestJSON(base.BaseNetworkTest):
@@ -35,7 +35,7 @@
@classmethod
def skip_checks(cls):
super(ExtraDHCPOptionsTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('extra_dhcp_opt', 'network'):
+ if not utils.is_extension_enabled('extra_dhcp_opt', 'network'):
msg = "Extra DHCP Options extension not enabled."
raise cls.skipException(msg)
@@ -75,7 +75,7 @@
def test_update_show_port_with_extra_dhcp_options(self):
# Update port with extra dhcp options
name = data_utils.rand_name('new-port-name')
- body = self.ports_client.update_port(
+ self.ports_client.update_port(
self.port['id'],
name=name,
extra_dhcp_opts=self.extra_dhcp_opts)
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index c799b15..ef4a23a 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -14,10 +14,10 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest.common.utils import net_utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -43,7 +43,7 @@
@classmethod
def skip_checks(cls):
super(FloatingIPTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('router', 'network'):
+ if not utils.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
if not CONF.network.public_network_id:
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index 5ca17fe..e904a81 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -15,10 +15,10 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -34,7 +34,7 @@
@classmethod
def skip_checks(cls):
super(FloatingIPNegativeTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('router', 'network'):
+ if not utils.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
if not CONF.network.public_network_id:
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 269f2c2..206d1a8 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -18,12 +18,12 @@
from tempest.api.network import base
from tempest.common import custom_matchers
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -209,7 +209,7 @@
def test_show_network_fields(self):
# Verify specific fields of a network
fields = ['id', 'name']
- if test.is_extension_enabled('net-mtu', 'network'):
+ if utils.is_extension_enabled('net-mtu', 'network'):
fields.append('mtu')
body = self.networks_client.show_network(self.network['id'],
fields=fields)
@@ -233,7 +233,7 @@
def test_list_networks_fields(self):
# Verify specific fields of the networks
fields = ['id', 'name']
- if test.is_extension_enabled('net-mtu', 'network'):
+ if utils.is_extension_enabled('net-mtu', 'network'):
fields.append('mtu')
body = self.networks_client.list_networks(fields=fields)
networks = body['networks']
@@ -370,7 +370,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('af774677-42a9-4e4b-bb58-16fe6a5bc1ec')
- @test.requires_ext(extension='external-net', service='network')
+ @utils.requires_ext(extension='external-net', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
def test_external_network_visibility(self):
@@ -392,8 +392,8 @@
self.assertEmpty(body['subnets'], "Public subnets visible")
@decorators.idempotent_id('c72c1c0c-2193-4aca-ccc4-b1442640bbbb')
- @test.requires_ext(extension="standard-attr-description",
- service="network")
+ @utils.requires_ext(extension="standard-attr-description",
+ service="network")
def test_create_update_network_description(self):
body = self.create_network(description='d1')
self.assertEqual('d1', body['description'])
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index f81927d..5c36747 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -18,11 +18,11 @@
from tempest.api.network import base_security_groups as sec_base
from tempest.common import custom_matchers
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions
-from tempest import test
CONF = config.CONF
@@ -307,7 +307,7 @@
@decorators.idempotent_id('58091b66-4ff4-4cc1-a549-05d60c7acd1a')
@testtools.skipUnless(
- test.is_extension_enabled('security-group', 'network'),
+ utils.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(
@@ -315,7 +315,7 @@
@decorators.idempotent_id('edf6766d-3d40-4621-bc6e-2521a44c257d')
@testtools.skipUnless(
- test.is_extension_enabled('security-group', 'network'),
+ utils.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(
@@ -342,7 +342,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('4179dcb9-1382-4ced-84fe-1b91c54f5735')
@testtools.skipUnless(
- test.is_extension_enabled('security-group', 'network'),
+ utils.is_extension_enabled('security-group', 'network'),
'security-group extension not enabled.')
def test_create_port_with_no_securitygroups(self):
network = self.create_network()
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 128544b..3883cc2 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -17,10 +17,10 @@
import testtools
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -55,7 +55,7 @@
@classmethod
def skip_checks(cls):
super(RoutersTest, cls).skip_checks()
- if not test.is_extension_enabled('router', 'network'):
+ if not utils.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
@@ -167,7 +167,7 @@
self.assertIn(subnet_id, public_subnet_ids)
@decorators.idempotent_id('cbe42f84-04c2-11e7-8adb-fa163e4fa634')
- @test.requires_ext(extension='ext-gw-mode', service='network')
+ @utils.requires_ext(extension='ext-gw-mode', service='network')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
@decorators.skip_because(bug='1676207')
@@ -198,7 +198,7 @@
fixed_ip['ip_address'])
@decorators.idempotent_id('c86ac3a8-50bd-4b00-a6b8-62af84a0765c')
- @test.requires_ext(extension='extraroute', service='network')
+ @utils.requires_ext(extension='extraroute', service='network')
def test_update_delete_extra_route(self):
# Create different cidr for each subnet to avoid cidr duplicate
# The cidr starts from project_cidr
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 72face8..60b9de7 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -16,11 +16,11 @@
import netaddr
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -30,7 +30,7 @@
@classmethod
def skip_checks(cls):
super(RoutersNegativeTest, cls).skip_checks()
- if not test.is_extension_enabled('router', 'network'):
+ if not utils.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
@@ -124,17 +124,10 @@
@classmethod
def skip_checks(cls):
super(DvrRoutersNegativeTest, cls).skip_checks()
- if not test.is_extension_enabled('dvr', 'network'):
+ if not utils.is_extension_enabled('dvr', 'network'):
msg = "DVR extension not enabled."
raise cls.skipException(msg)
- @classmethod
- def resource_setup(cls):
- super(DvrRoutersNegativeTest, cls).resource_setup()
- cls.router = cls.create_router()
- cls.network = cls.create_network()
- cls.subnet = cls.create_subnet(cls.network)
-
@decorators.attr(type=['negative'])
@decorators.idempotent_id('4990b055-8fc7-48ab-bba7-aa28beaad0b9')
def test_router_create_tenant_distributed_returns_forbidden(self):
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index a121864..97ccee9 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -14,10 +14,10 @@
# under the License.
from tempest.api.network import base_security_groups as base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -28,7 +28,7 @@
@classmethod
def skip_checks(cls):
super(SecGroupTest, cls).skip_checks()
- if not test.is_extension_enabled('security-group', 'network'):
+ if not utils.is_extension_enabled('security-group', 'network'):
msg = "security-group extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index f51fb33..435673b 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -14,11 +14,11 @@
# under the License.
from tempest.api.network import base_security_groups as base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -29,7 +29,7 @@
@classmethod
def skip_checks(cls):
super(NegativeSecGroupTest, cls).skip_checks()
- if not test.is_extension_enabled('security-group', 'network'):
+ if not utils.is_extension_enabled('security-group', 'network'):
msg = "security-group extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/test_service_providers.py b/tempest/api/network/test_service_providers.py
index b90c81b..9ebcd89 100644
--- a/tempest/api/network/test_service_providers.py
+++ b/tempest/api/network/test_service_providers.py
@@ -13,15 +13,15 @@
import testtools
from tempest.api.network import base
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class ServiceProvidersTest(base.BaseNetworkTest):
@decorators.idempotent_id('2cbbeea9-f010-40f6-8df5-4eaa0c918ea6')
@testtools.skipUnless(
- test.is_extension_enabled('service-type', 'network'),
+ utils.is_extension_enabled('service-type', 'network'),
'service-type extension not enabled.')
def test_service_providers_list(self):
body = self.service_providers_client.list_service_providers()
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
index 01d7db2..bfc2609 100644
--- a/tempest/api/network/test_subnetpools_extensions.py
+++ b/tempest/api/network/test_subnetpools_extensions.py
@@ -13,12 +13,12 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -42,7 +42,7 @@
@classmethod
def skip_checks(cls):
super(SubnetPoolsTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('subnet_allocation', 'network'):
+ if not utils.is_extension_enabled('subnet_allocation', 'network'):
msg = "subnet_allocation extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/network/test_tags.py b/tempest/api/network/test_tags.py
index 567a462..409d556 100644
--- a/tempest/api/network/test_tags.py
+++ b/tempest/api/network/test_tags.py
@@ -14,11 +14,11 @@
# under the License.
from tempest.api.network import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -40,7 +40,7 @@
@classmethod
def skip_checks(cls):
super(TagsTest, cls).skip_checks()
- if not test.is_extension_enabled('tag', 'network'):
+ if not utils.is_extension_enabled('tag', 'network'):
msg = "tag extension not enabled."
raise cls.skipException(msg)
@@ -115,7 +115,7 @@
@classmethod
def skip_checks(cls):
super(TagsExtTest, cls).skip_checks()
- if not test.is_extension_enabled('tag-ext', 'network'):
+ if not utils.is_extension_enabled('tag-ext', 'network'):
msg = "tag-ext extension not enabled."
raise cls.skipException(msg)
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 11273e4..4c49b2a 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -71,9 +71,6 @@
def setup_credentials(cls):
cls.set_network_resources()
super(BaseObjectTest, cls).setup_credentials()
- # credentials may be overwritten by children classes
- if hasattr(cls, 'os_roles_operator'):
- cls.os = cls.os_roles_operator
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index 7c538e8..9abd59e 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -17,8 +17,8 @@
from tempest.api.object_storage import base
from tempest.common import custom_matchers
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class BulkTest(base.BaseObjectTest):
@@ -69,7 +69,7 @@
self.assertNotIn(container_name, body)
@decorators.idempotent_id('a407de51-1983-47cc-9f14-47c2b059413c')
- @test.requires_ext(extension='bulk_upload', service='object')
+ @utils.requires_ext(extension='bulk_upload', service='object')
def test_extract_archive(self):
# Test bulk operation of file upload with an archived file
filepath, container_name, object_name = self._create_archive()
@@ -104,7 +104,7 @@
self.assertIn(object_name, [c['name'] for c in contents_list])
@decorators.idempotent_id('c075e682-0d2a-43b2-808d-4116200d736d')
- @test.requires_ext(extension='bulk_delete', service='object')
+ @utils.requires_ext(extension='bulk_delete', service='object')
def test_bulk_delete(self):
# Test bulk operation of deleting multiple files
filepath, container_name, object_name = self._create_archive()
@@ -129,7 +129,7 @@
self._check_contents_deleted(container_name)
@decorators.idempotent_id('dbea2bcb-efbb-4674-ac8a-a5a0e33d1d79')
- @test.requires_ext(extension='bulk_delete', service='object')
+ @utils.requires_ext(extension='bulk_delete', service='object')
def test_bulk_delete_by_POST(self):
# Test bulk operation of deleting multiple files
filepath, container_name, object_name = self._create_archive()
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 092d369..48f42ec 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -13,10 +13,10 @@
# under the License.
from tempest.api.object_storage import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -29,7 +29,6 @@
@classmethod
def setup_credentials(cls):
super(AccountQuotasTest, cls).setup_credentials()
- cls.os = cls.os_roles_operator
cls.os_reselleradmin = cls.os_roles_reseller
@classmethod
@@ -78,7 +77,7 @@
@decorators.attr(type="smoke")
@decorators.idempotent_id('a22ef352-a342-4587-8f47-3bbdb5b039c4')
- @test.requires_ext(extension='account_quotas', service='object')
+ @utils.requires_ext(extension='account_quotas', service='object')
def test_upload_valid_object(self):
object_name = data_utils.rand_name(name="TestObject")
data = data_utils.arbitrary_string()
@@ -89,7 +88,7 @@
@decorators.attr(type=["smoke"])
@decorators.idempotent_id('63f51f9f-5f1d-4fc6-b5be-d454d70949d6')
- @test.requires_ext(extension='account_quotas', service='object')
+ @utils.requires_ext(extension='account_quotas', service='object')
def test_admin_modify_quota(self):
"""Test ResellerAdmin can modify/remove the quota on a user's account
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 60233b4..798926b 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -13,10 +13,10 @@
# under the License.
from tempest.api.object_storage import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -29,7 +29,6 @@
@classmethod
def setup_credentials(cls):
super(AccountQuotasNegativeTest, cls).setup_credentials()
- cls.os = cls.os_roles_operator
cls.os_reselleradmin = cls.os_roles_reseller
@classmethod
@@ -77,7 +76,7 @@
@decorators.attr(type=["negative"])
@decorators.idempotent_id('d1dc5076-555e-4e6d-9697-28f1fe976324')
- @test.requires_ext(extension='account_quotas', service='object')
+ @utils.requires_ext(extension='account_quotas', service='object')
def test_user_modify_quota(self):
"""Test that a user cannot modify or remove a quota on its account."""
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 2fb676f..0f86540 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -36,14 +36,13 @@
@classmethod
def setup_credentials(cls):
super(AccountTest, cls).setup_credentials()
- cls.os = cls.os_roles_operator
cls.os_operator = cls.os_roles_operator_alt
@classmethod
def resource_setup(cls):
super(AccountTest, cls).resource_setup()
for i in range(ord('a'), ord('f') + 1):
- name = data_utils.rand_name(name='%s-' % chr(i))
+ name = data_utils.rand_name(name='%s-' % six.int2byte(i))
cls.container_client.create_container(name)
cls.containers.append(name)
cls.containers_count = len(cls.containers)
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index e98a4f5..3e664d7 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -28,7 +28,6 @@
@classmethod
def setup_credentials(cls):
super(AccountNegativeTest, cls).setup_credentials()
- cls.os = cls.os_roles_operator
cls.os_operator = cls.os_roles_operator_alt
@decorators.attr(type=['negative'])
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 655626c..e064753 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -29,7 +29,6 @@
@classmethod
def setup_credentials(cls):
super(ObjectACLsNegativeTest, cls).setup_credentials()
- cls.os = cls.os_roles_operator
cls.os_operator = cls.os_roles_operator_alt
@classmethod
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index 8266341..c87bed5 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -14,10 +14,10 @@
# under the License.
from tempest.api.object_storage import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
QUOTA_BYTES = 10
QUOTA_COUNT = 3
@@ -49,7 +49,7 @@
super(ContainerQuotasTest, self).tearDown()
@decorators.idempotent_id('9a0fb034-86af-4df0-86fa-f8bd7db21ae0')
- @test.requires_ext(extension='container_quotas', service='object')
+ @utils.requires_ext(extension='container_quotas', service='object')
@decorators.attr(type="smoke")
def test_upload_valid_object(self):
"""Attempts to uploads an object smaller than the bytes quota."""
@@ -66,7 +66,7 @@
self.assertEqual(nbefore + len(data), nafter)
@decorators.idempotent_id('22eeeb2b-3668-4160-baef-44790f65a5a0')
- @test.requires_ext(extension='container_quotas', service='object')
+ @utils.requires_ext(extension='container_quotas', service='object')
@decorators.attr(type="smoke")
def test_upload_large_object(self):
"""Attempts to upload an object larger than the bytes quota."""
@@ -83,7 +83,7 @@
self.assertEqual(nbefore, nafter)
@decorators.idempotent_id('3a387039-697a-44fc-a9c0-935de31f426b')
- @test.requires_ext(extension='container_quotas', service='object')
+ @utils.requires_ext(extension='container_quotas', service='object')
@decorators.attr(type="smoke")
def test_upload_too_many_objects(self):
"""Attempts to upload many objects that exceeds the count limit."""
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index 943011d..92fa690 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -14,10 +14,10 @@
from tempest.api.object_storage import base
from tempest.common import custom_matchers
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class StaticWebTest(base.BaseObjectTest):
@@ -45,7 +45,7 @@
super(StaticWebTest, cls).resource_cleanup()
@decorators.idempotent_id('c1f055ab-621d-4a6a-831f-846fcb578b8b')
- @test.requires_ext(extension='staticweb', service='object')
+ @utils.requires_ext(extension='staticweb', service='object')
def test_web_index(self):
headers = {'web-index': self.object_name}
@@ -76,7 +76,7 @@
self.assertNotIn('x-container-meta-web-index', body)
@decorators.idempotent_id('941814cf-db9e-4b21-8112-2b6d0af10ee5')
- @test.requires_ext(extension='staticweb', service='object')
+ @utils.requires_ext(extension='staticweb', service='object')
def test_web_listing(self):
headers = {'web-listings': 'true'}
@@ -108,7 +108,7 @@
self.assertNotIn('x-container-meta-web-listings', body)
@decorators.idempotent_id('bc37ec94-43c8-4990-842e-0e5e02fc8926')
- @test.requires_ext(extension='staticweb', service='object')
+ @utils.requires_ext(extension='staticweb', service='object')
def test_web_listing_css(self):
headers = {'web-listings': 'true',
'web-listings-css': 'listings.css'}
@@ -131,7 +131,7 @@
self.assertIn(css, body.decode())
@decorators.idempotent_id('f18b4bef-212e-45e7-b3ca-59af3a465f82')
- @test.requires_ext(extension='staticweb', service='object')
+ @utils.requires_ext(extension='staticweb', service='object')
def test_web_error(self):
headers = {'web-listings': 'true',
'web-error': self.object_name}
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 4cb1914..7665b48 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -41,7 +41,6 @@
@classmethod
def setup_credentials(cls):
super(ContainerSyncTest, cls).setup_credentials()
- cls.os = cls.os_roles_operator
cls.os_alt = cls.os_roles_operator_alt
@classmethod
diff --git a/tempest/api/object_storage/test_container_sync_middleware.py b/tempest/api/object_storage/test_container_sync_middleware.py
index 9eae138..e77b079 100644
--- a/tempest/api/object_storage/test_container_sync_middleware.py
+++ b/tempest/api/object_storage/test_container_sync_middleware.py
@@ -13,9 +13,9 @@
# under the License.
from tempest.api.object_storage import test_container_sync
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -39,7 +39,7 @@
@decorators.attr(type='slow')
@decorators.idempotent_id('ea4645a1-d147-4976-82f7-e5a7a3065f80')
- @test.requires_ext(extension='container_sync', service='object')
+ @utils.requires_ext(extension='container_sync', service='object')
def test_container_synchronization(self):
def make_headers(cont, cont_client):
# tell first container to synchronize to a second
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index c47aa93..f61d9f8 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -14,8 +14,8 @@
from tempest.api.object_storage import base
from tempest.common import custom_matchers
+from tempest.common import utils
from tempest.lib import decorators
-from tempest import test
class CrossdomainTest(base.BaseObjectTest):
@@ -38,7 +38,7 @@
self.account_client.skip_path()
@decorators.idempotent_id('d1b8b031-b622-4010-82f9-ff78a9e915c7')
- @test.requires_ext(extension='crossdomain', service='object')
+ @utils.requires_ext(extension='crossdomain', service='object')
def test_get_crossdomain_policy(self):
resp, body = self.account_client.get("crossdomain.xml", {})
body = body.decode()
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 3a2233a..cd834bf 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -19,9 +19,9 @@
from six.moves.urllib import parse as urlparse
from tempest.api.object_storage import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class ObjectFormPostTest(base.BaseObjectTest):
@@ -108,7 +108,7 @@
return body, content_type
@decorators.idempotent_id('80fac02b-6e54-4f7b-be0d-a965b5cbef76')
- @test.requires_ext(extension='formpost', service='object')
+ @utils.requires_ext(extension='formpost', service='object')
def test_post_object_using_form(self):
body, content_type = self.get_multipart_form()
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index c56d91a..df6a0fd 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -19,10 +19,10 @@
from six.moves.urllib import parse as urlparse
from tempest.api.object_storage import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class ObjectFormPostNegativeTest(base.BaseObjectTest):
@@ -109,7 +109,7 @@
return body, content_type
@decorators.idempotent_id('d3fb3c4d-e627-48ce-9379-a1631f21336d')
- @test.requires_ext(extension='formpost', service='object')
+ @utils.requires_ext(extension='formpost', service='object')
@decorators.attr(type=['negative'])
def test_post_object_using_form_expired(self):
body, content_type = self.get_multipart_form(expires=1)
@@ -126,7 +126,7 @@
self.assertIn('FormPost: Form Expired', str(exc))
@decorators.idempotent_id('b277257f-113c-4499-b8d1-5fead79f7360')
- @test.requires_ext(extension='formpost', service='object')
+ @utils.requires_ext(extension='formpost', service='object')
@decorators.attr(type=['negative'])
def test_post_object_using_form_invalid_signature(self):
self.key = "Wrong"
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index b29a77f..d3cdb72 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -967,13 +967,12 @@
@classmethod
def setup_credentials(cls):
super(PublicObjectTest, cls).setup_credentials()
- cls.os = cls.os_roles_operator
cls.os_alt = cls.os_roles_operator_alt
@classmethod
def setup_clients(cls):
super(PublicObjectTest, cls).setup_clients()
- cls.identity_client_alt = cls.os_alt.identity_client
+ cls.object_client_alt = cls.os_alt.object_client
def setUp(self):
super(PublicObjectTest, self).setUp()
@@ -1047,7 +1046,7 @@
self.assertEqual(resp['x-container-read'], '.r:*,.rlistings')
# get auth token of alternative user
- alt_auth_data = self.identity_client_alt.auth_provider.auth_data
+ alt_auth_data = self.object_client_alt.auth_provider.auth_data
self.object_client.auth_provider.set_alt_auth_data(
request_part='headers',
auth_data=alt_auth_data
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 894e42d..65da63d 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -18,10 +18,10 @@
from tempest.api.object_storage import base
from tempest.common import custom_matchers
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
-from tempest import test
# Each segment, except for the final one, must be at least 1 megabyte
MIN_SEGMENT_SIZE = 1024 * 1024
@@ -107,7 +107,7 @@
self.assertHeaders(resp, 'Object', method)
@decorators.idempotent_id('2c3f24a6-36e8-4711-9aa2-800ee1fc7b5b')
- @test.requires_ext(extension='slo', service='object')
+ @utils.requires_ext(extension='slo', service='object')
def test_upload_manifest(self):
# create static large object from multipart manifest
manifest = self._create_manifest()
@@ -122,7 +122,7 @@
self._assertHeadersSLO(resp, 'PUT')
@decorators.idempotent_id('e69ad766-e1aa-44a2-bdd2-bf62c09c1456')
- @test.requires_ext(extension='slo', service='object')
+ @utils.requires_ext(extension='slo', service='object')
def test_list_large_object_metadata(self):
# list static large object metadata using multipart manifest
object_name = self._create_large_object()
@@ -134,7 +134,7 @@
self._assertHeadersSLO(resp, 'HEAD')
@decorators.idempotent_id('49bc49bc-dd1b-4c0f-904e-d9f10b830ee8')
- @test.requires_ext(extension='slo', service='object')
+ @utils.requires_ext(extension='slo', service='object')
def test_retrieve_large_object(self):
# list static large object using multipart manifest
object_name = self._create_large_object()
@@ -149,7 +149,7 @@
self.assertEqual(body, sum_data)
@decorators.idempotent_id('87b6dfa1-abe9-404d-8bf0-6c3751e6aa77')
- @test.requires_ext(extension='slo', service='object')
+ @utils.requires_ext(extension='slo', service='object')
def test_delete_large_object(self):
# delete static large object using multipart manifest
object_name = self._create_large_object()
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 91bc677..b99f93a 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -19,9 +19,9 @@
from six.moves.urllib import parse as urlparse
from tempest.api.object_storage import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class ObjectTempUrlTest(base.BaseObjectTest):
@@ -88,7 +88,7 @@
return url
@decorators.idempotent_id('f91c96d4-1230-4bba-8eb9-84476d18d991')
- @test.requires_ext(extension='tempurl', service='object')
+ @utils.requires_ext(extension='tempurl', service='object')
def test_get_object_using_temp_url(self):
expires = self._get_expiry_date()
@@ -103,11 +103,11 @@
self.assertEqual(body, self.content)
# Testing a HEAD on this Temp URL
- resp, body = self.object_client.head(url)
+ resp, _ = self.object_client.head(url)
self.assertHeaders(resp, 'Object', 'HEAD')
@decorators.idempotent_id('671f9583-86bd-4128-a034-be282a68c5d8')
- @test.requires_ext(extension='tempurl', service='object')
+ @utils.requires_ext(extension='tempurl', service='object')
def test_get_object_using_temp_url_key_2(self):
key2 = 'Meta2-'
metadata = {'Temp-URL-Key-2': key2}
@@ -132,7 +132,7 @@
self.assertEqual(body, self.content)
@decorators.idempotent_id('9b08dade-3571-4152-8a4f-a4f2a873a735')
- @test.requires_ext(extension='tempurl', service='object')
+ @utils.requires_ext(extension='tempurl', service='object')
def test_put_object_using_temp_url(self):
new_data = data_utils.random_bytes(size=len(self.object_name))
@@ -142,11 +142,11 @@
expires, self.key)
# trying to put random data in the object using temp url
- resp, body = self.object_client.put(url, new_data, None)
+ resp, _ = self.object_client.put(url, new_data, None)
self.assertHeaders(resp, 'Object', 'PUT')
# Testing a HEAD on this Temp URL
- resp, body = self.object_client.head(url)
+ resp, _ = self.object_client.head(url)
self.assertHeaders(resp, 'Object', 'HEAD')
# Validate that the content of the object has been modified
@@ -158,7 +158,7 @@
self.assertEqual(body, new_data)
@decorators.idempotent_id('249a0111-5ad3-4534-86a7-1993d55f9185')
- @test.requires_ext(extension='tempurl', service='object')
+ @utils.requires_ext(extension='tempurl', service='object')
def test_head_object_using_temp_url(self):
expires = self._get_expiry_date()
@@ -172,7 +172,7 @@
self.assertHeaders(resp, 'Object', 'HEAD')
@decorators.idempotent_id('9d9cfd90-708b-465d-802c-e4a8090b823d')
- @test.requires_ext(extension='tempurl', service='object')
+ @utils.requires_ext(extension='tempurl', service='object')
def test_get_object_using_temp_url_with_inline_query_parameter(self):
expires = self._get_expiry_date()
diff --git a/tempest/api/object_storage/test_object_temp_url_negative.py b/tempest/api/object_storage/test_object_temp_url_negative.py
index c7d1fd5..17ae6c1 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -19,10 +19,10 @@
from six.moves.urllib import parse as urlparse
from tempest.api.object_storage import base
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
class ObjectTempUrlNegativeTest(base.BaseObjectTest):
@@ -94,7 +94,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('5a583aca-c804-41ba-9d9a-e7be132bdf0b')
- @test.requires_ext(extension='tempurl', service='object')
+ @utils.requires_ext(extension='tempurl', service='object')
def test_get_object_after_expiration_time(self):
expires = self._get_expiry_date(1)
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index dc0d179..4799053 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -51,7 +51,7 @@
def test_versioned_container(self):
# create container
vers_container_name = data_utils.rand_name(name='TestVersionContainer')
- resp, body = self.container_client.create_container(
+ resp, _ = self.container_client.create_container(
vers_container_name)
self.containers.append(vers_container_name)
self.assertHeaders(resp, 'Container', 'PUT')
@@ -59,7 +59,7 @@
base_container_name = data_utils.rand_name(name='TestBaseContainer')
headers = {'X-versions-Location': vers_container_name}
- resp, body = self.container_client.create_container(
+ resp, _ = self.container_client.create_container(
base_container_name,
metadata=headers,
metadata_prefix='')
@@ -76,20 +76,20 @@
data_2 = data_utils.random_bytes()
resp, _ = self.object_client.create_object(base_container_name,
object_name, data_2)
- resp, body = self.object_client.get_object(base_container_name,
- object_name)
+ _, body = self.object_client.get_object(base_container_name,
+ object_name)
self.assertEqual(body, data_2)
# delete object version 2
resp, _ = self.object_client.delete_object(base_container_name,
object_name)
self.assertContainer(base_container_name, '1', '1024',
vers_container_name)
- resp, body = self.object_client.get_object(base_container_name,
- object_name)
+ _, body = self.object_client.get_object(base_container_name,
+ object_name)
self.assertEqual(body, data_1)
# delete object version 1
- resp, _ = self.object_client.delete_object(base_container_name,
- object_name)
+ self.object_client.delete_object(base_container_name,
+ object_name)
# containers should be empty
self.assertContainer(base_container_name, '0', '0',
vers_container_name)
diff --git a/tempest/api/volume/admin/test_groups.py b/tempest/api/volume/admin/test_groups.py
index 5f01166..baea37b 100644
--- a/tempest/api/volume/admin/test_groups.py
+++ b/tempest/api/volume/admin/test_groups.py
@@ -258,3 +258,65 @@
self.volumes_client, vol['id'], 'available')
waiters.wait_for_volume_resource_status(
self.groups_client, grp2['id'], 'available')
+
+ @decorators.idempotent_id('4a8a6fd2-8b3b-4641-8f54-6a6f99320006')
+ def test_group_update(self):
+ # Create volume type
+ volume_type = self.create_volume_type()
+
+ # Create group type
+ group_type = self.create_group_type()
+
+ # Create Group
+ grp = self._create_group(group_type, volume_type)
+
+ # Create volumes
+ grp_vols = []
+ for _ in range(2):
+ vol = self.create_volume(volume_type=volume_type['id'],
+ group_id=grp['id'])
+ grp_vols.append(vol)
+ vol2 = grp_vols[1]
+
+ # Remove a volume from group and update name and description
+ new_grp_name = 'new_group'
+ new_desc = 'This is a new group'
+ grp_params = {'name': new_grp_name,
+ 'description': new_desc,
+ 'remove_volumes': vol2['id']}
+ self.groups_client.update_group(grp['id'], **grp_params)
+
+ # Wait for group status to become available
+ waiters.wait_for_volume_resource_status(
+ self.groups_client, grp['id'], 'available')
+
+ # Get the updated Group
+ grp = self.groups_client.show_group(grp['id'])['group']
+ self.assertEqual(new_grp_name, grp['name'])
+ self.assertEqual(new_desc, grp['description'])
+
+ # Get volumes in the group
+ vols = self.volumes_client.list_volumes(
+ detail=True)['volumes']
+ grp_vols = []
+ for vol in vols:
+ if vol['group_id'] == grp['id']:
+ grp_vols.append(vol)
+ self.assertEqual(1, len(grp_vols))
+
+ # Add a volume to the group
+ grp_params = {'add_volumes': vol2['id']}
+ self.groups_client.update_group(grp['id'], **grp_params)
+
+ # Wait for group status to become available
+ waiters.wait_for_volume_resource_status(
+ self.groups_client, grp['id'], 'available')
+
+ # Get volumes in the group
+ vols = self.volumes_client.list_volumes(
+ detail=True)['volumes']
+ grp_vols = []
+ for vol in vols:
+ if vol['group_id'] == grp['id']:
+ grp_vols.append(vol)
+ self.assertEqual(2, len(grp_vols))
diff --git a/tempest/api/volume/admin/test_volume_retype_with_migration.py b/tempest/api/volume/admin/test_volume_retype_with_migration.py
index 94d5299..f0b3a4f 100644
--- a/tempest/api/volume/admin/test_volume_retype_with_migration.py
+++ b/tempest/api/volume/admin/test_volume_retype_with_migration.py
@@ -85,9 +85,7 @@
volume_source = self.admin_volume_client.show_volume(
self.src_vol['id'])['volume']
- # TODO(erlon): change this to volumes_client client after Bug
- # #1657806 is fixed
- self.admin_volume_client.retype_volume(
+ self.volumes_client.retype_volume(
self.src_vol['id'],
new_type=self.dst_vol_type['name'],
migration_policy='on-demand')
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index 4fa934e..fe249d6 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -61,7 +61,7 @@
@decorators.idempotent_id('a77dfda2-9100-448e-9076-ed1711f4bdfc')
def test_update_multiple_extra_spec(self):
# Should not update volume type extra specs with multiple specs as
- # body.
+ # body.
extra_spec = {"spec1": "val2", "spec2": "val1"}
self.assertRaises(
lib_exc.BadRequest,
@@ -73,7 +73,7 @@
@decorators.idempotent_id('49d5472c-a53d-4eab-a4d3-450c4db1c545')
def test_create_nonexistent_type_id(self):
# Should not create volume type extra spec for nonexistent volume
- # type id.
+ # type id.
extra_specs = {"spec2": "val1"}
self.assertRaises(
lib_exc.NotFound,
@@ -128,10 +128,10 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('c881797d-12ff-4f1a-b09d-9f6212159753')
- def test_get_nonexistent_extra_spec_id(self):
+ def test_get_nonexistent_extra_spec_name(self):
# Should not get volume type extra spec for nonexistent extra spec
- # id.
+ # name.
self.assertRaises(
lib_exc.NotFound,
self.admin_volume_types_client.show_volume_type_extra_specs,
- self.volume_type['id'], data_utils.rand_uuid())
+ self.volume_type['id'], "nonexistent_extra_spec_name")
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index b81a477..8d09217 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -14,10 +14,10 @@
# under the License.
from tempest.api.volume import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -30,6 +30,8 @@
if status:
self.admin_volume_client.reset_volume_status(
temp_volume['id'], status=status)
+ waiters.wait_for_volume_resource_status(
+ self.volumes_client, temp_volume['id'], status)
self.admin_volume_client.force_delete_volume(temp_volume['id'])
self.volumes_client.wait_for_resource_deletion(temp_volume['id'])
@@ -37,14 +39,15 @@
def test_volume_reset_status(self):
# test volume reset status : available->error->available
volume = self.create_volume()
+ self.addCleanup(waiters.wait_for_volume_resource_status,
+ self.volumes_client, volume['id'], 'available')
self.addCleanup(self.admin_volume_client.reset_volume_status,
volume['id'], status='available')
for status in ['error', 'available', 'maintenance']:
self.admin_volume_client.reset_volume_status(
volume['id'], status=status)
- volume_get = self.admin_volume_client.show_volume(
- volume['id'])['volume']
- self.assertEqual(status, volume_get['status'])
+ waiters.wait_for_volume_resource_status(
+ self.volumes_client, volume['id'], status)
@decorators.idempotent_id('21737d5a-92f2-46d7-b009-a0cc0ee7a570')
def test_volume_force_delete_when_volume_is_creating(self):
@@ -67,7 +70,7 @@
self._create_reset_and_force_delete_temp_volume('maintenance')
@decorators.idempotent_id('d38285d9-929d-478f-96a5-00e66a115b81')
- @test.services('compute')
+ @utils.services('compute')
def test_force_detach_volume(self):
# Create a server and a volume
server_id = self.create_server()['id']
@@ -88,6 +91,8 @@
# Reset volume's status to error
self.admin_volume_client.reset_volume_status(volume_id, status='error')
+ waiters.wait_for_volume_resource_status(self.volumes_client,
+ volume_id, 'error')
# Force detach volume
self.admin_volume_client.force_detach_volume(
diff --git a/tempest/api/volume/test_image_metadata.py b/tempest/api/volume/test_image_metadata.py
index 129981b..53b3acc 100644
--- a/tempest/api/volume/test_image_metadata.py
+++ b/tempest/api/volume/test_image_metadata.py
@@ -16,9 +16,9 @@
from testtools import matchers
from tempest.api.volume import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -39,7 +39,7 @@
cls.volume = cls.create_volume(imageRef=CONF.compute.image_ref)
@decorators.idempotent_id('03efff0b-5c75-4822-8f10-8789ac15b13e')
- @test.services('image')
+ @utils.services('image')
def test_update_show_delete_image_metadata(self):
# Update image metadata
image_metadata = {'image_id': '5137a025-3c5f-43c1-bc64-5f41270040a5',
diff --git a/tempest/api/volume/test_versions.py b/tempest/api/volume/test_versions.py
index 0083a3b..b4d48db 100644
--- a/tempest/api/volume/test_versions.py
+++ b/tempest/api/volume/test_versions.py
@@ -26,4 +26,4 @@
# NOTE: The version data is checked on service client side
# with JSON-Schema validation. It is enough to just call
# the API here.
- self.versions_client.list_versions()['versions']
+ self.versions_client.list_versions()
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index c4d10c3..be5638e 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -14,12 +14,12 @@
# under the License.
from tempest.api.volume import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -35,7 +35,7 @@
@decorators.idempotent_id('fff42874-7db5-4487-a8e1-ddda5fb5288d')
@decorators.attr(type='smoke')
- @test.services('compute')
+ @utils.services('compute')
def test_attach_detach_volume_to_instance(self):
# Create a server
server = self.create_server()
@@ -66,7 +66,7 @@
fetched_volume['bootable'])
@decorators.idempotent_id('9516a2c8-9135-488c-8dd6-5677a7e5f371')
- @test.services('compute')
+ @utils.services('compute')
def test_get_volume_attachment(self):
# Create a server
server = self.create_server()
@@ -94,7 +94,7 @@
self.assertEqual(self.volume['id'], attachment['volume_id'])
@decorators.idempotent_id('d8f1ca95-3d5b-44a3-b8ca-909691c9532d')
- @test.services('image')
+ @utils.services('image')
def test_volume_upload(self):
# NOTE(gfidente): the volume uploaded in Glance comes from setUpClass,
# it is shared with the other tests. After it is uploaded in Glance,
@@ -112,6 +112,10 @@
waiters.wait_for_volume_resource_status(self.volumes_client,
self.volume['id'], 'available')
+ image_info = self.images_client.show_image(image_id)
+ self.assertEqual(image_name, image_info['name'])
+ self.assertEqual(CONF.volume.disk_format, image_info['disk_format'])
+
@decorators.idempotent_id('92c4ef64-51b2-40c0-9f7e-4749fbaaba33')
def test_reserve_unreserve_volume(self):
# Mark volume as reserved.
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 1f91db6..f2d8801 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -17,11 +17,11 @@
from testtools import matchers
from tempest.api.volume import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -97,7 +97,7 @@
matchers.ContainsAll(metadata.items()))
@decorators.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
- @test.services('compute')
+ @utils.services('compute')
def test_backup_create_attached_volume(self):
"""Test backup create using force flag.
@@ -119,7 +119,7 @@
self.assertEqual(backup_name, backup['name'])
@decorators.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
- @test.services('image')
+ @utils.services('image')
def test_bootable_volume_backup_and_restore(self):
# Create volume from image
img_uuid = CONF.compute.image_ref
diff --git a/tempest/api/volume/test_volumes_clone.py b/tempest/api/volume/test_volumes_clone.py
index 927bfa5..ea39a21 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -14,9 +14,9 @@
# under the License.
from tempest.api.volume import base
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -56,7 +56,7 @@
self._verify_volume_clone(src_vol, dst_vol, extra_size=1)
@decorators.idempotent_id('cbbcd7c6-5a6c-481a-97ac-ca55ab715d16')
- @test.services('image')
+ @utils.services('image')
def test_create_from_bootable_volume(self):
# Create volume from image
img_uuid = CONF.compute.image_ref
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index ec9a0dd..71db95c 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -17,11 +17,11 @@
from testtools import matchers
from tempest.api.volume import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
CONF = config.CONF
@@ -122,7 +122,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
- @test.services('image')
+ @utils.services('image')
def test_volume_create_get_update_delete_from_image(self):
image = self.images_client.show_image(CONF.compute.image_ref)
min_disk = image['min_disk']
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 8593d3a..b5f98ea 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -50,7 +50,7 @@
return
def str_vol(vol):
- return "%s:%s" % (vol['id'], vol[self.name])
+ return "%s:%s" % (vol['id'], vol['name'])
raw_msg = "Could not find volumes %s in expected list %s; fetched %s"
self.fail(raw_msg % ([str_vol(v) for v in missing_vols],
@@ -60,7 +60,6 @@
@classmethod
def resource_setup(cls):
super(VolumesListTestJSON, cls).resource_setup()
- cls.name = cls.VOLUME_FIELDS[1]
existing_volumes = cls.volumes_client.list_volumes()['volumes']
cls.volume_id_list = [vol['id'] for vol in existing_volumes]
@@ -117,22 +116,20 @@
@decorators.idempotent_id('a28e8da4-0b56-472f-87a8-0f4d3f819c02')
def test_volume_list_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {self.name: volume[self.name]}
+ params = {'name': volume['name']}
fetched_vol = self.volumes_client.list_volumes(
params=params)['volumes']
self.assertEqual(1, len(fetched_vol), str(fetched_vol))
- self.assertEqual(fetched_vol[0][self.name],
- volume[self.name])
+ self.assertEqual(fetched_vol[0]['name'], volume['name'])
@decorators.idempotent_id('2de3a6d4-12aa-403b-a8f2-fdeb42a89623')
def test_volume_list_details_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {self.name: volume[self.name]}
+ params = {'name': volume['name']}
fetched_vol = self.volumes_client.list_volumes(
detail=True, params=params)['volumes']
self.assertEqual(1, len(fetched_vol), str(fetched_vol))
- self.assertEqual(fetched_vol[0][self.name],
- volume[self.name])
+ self.assertEqual(fetched_vol[0]['name'], volume['name'])
@decorators.idempotent_id('39654e13-734c-4dab-95ce-7613bf8407ce')
def test_volumes_list_by_status(self):
@@ -213,7 +210,7 @@
def test_volume_list_param_display_name_and_status(self):
# Test to list volume when display name and status param is given
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {self.name: volume[self.name],
+ params = {'name': volume['name'],
'status': 'available'}
self._list_by_param_value_and_assert(params)
@@ -221,7 +218,7 @@
def test_volume_list_with_detail_param_display_name_and_status(self):
# Test to list volume when name and status param is given
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {self.name: volume[self.name],
+ params = {'name': volume['name'],
'status': 'available'}
self._list_by_param_value_and_assert(params, with_detail=True)
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 4e19e62..7d745f2 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -16,13 +16,13 @@
import six
from tempest.api.volume import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -168,7 +168,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('f5e56b0a-5d02-43c1-a2a7-c9b792c2e3f6')
- @test.services('compute')
+ @utils.services('compute')
def test_attach_volumes_with_nonexistent_volume_id(self):
server = self.create_server()
@@ -292,7 +292,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('5b810c91-0ad1-47ce-aee8-615f789be78f')
- @test.services('image')
+ @utils.services('image')
def test_create_volume_from_image_with_decreasing_size(self):
# Create image
image = self.create_image()
@@ -307,7 +307,7 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('d15e7f35-2cfc-48c8-9418-c8223a89bcbb')
- @test.services('image')
+ @utils.services('image')
def test_create_volume_from_deactivated_image(self):
# Create image
image = self.create_image()
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index e68ab7e..dcd3518 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -14,11 +14,11 @@
from testtools import matchers
from tempest.api.volume import base
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
-from tempest import test
CONF = config.CONF
@@ -37,7 +37,7 @@
cls.volume_origin = cls.create_volume()
@decorators.idempotent_id('8567b54c-4455-446d-a1cf-651ddeaa3ff2')
- @test.services('compute')
+ @utils.services('compute')
def test_snapshot_create_delete_with_volume_in_use(self):
# Create a test instance
server = self.create_server()
@@ -59,7 +59,7 @@
self.delete_snapshot(snapshot2['id'])
@decorators.idempotent_id('5210a1de-85a0-11e6-bb21-641c676a5d61')
- @test.services('compute')
+ @utils.services('compute')
def test_snapshot_create_offline_delete_online(self):
# Create a snapshot while it is not attached
diff --git a/tempest/clients.py b/tempest/clients.py
index d7a52d1..e617c3c 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -263,6 +263,7 @@
# Set default client for users that don't need explicit version
self.volumes_client_latest = self.volumes_v2_client
+ self.snapshots_client_latest = self.snapshots_v2_client
if CONF.volume_feature_enabled.api_v3:
self.backups_v3_client = self.volume_v3.BackupsClient()
@@ -277,6 +278,7 @@
# Set default client for users that don't need explicit version
self.volumes_client_latest = self.volumes_v3_client
+ self.snapshots_client_latest = self.snapshots_v3_client
def _set_object_storage_clients(self):
# NOTE(andreaf) Load configuration from config. Once object storage
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index ac73cbf..a128b3f 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -104,7 +104,8 @@
def init(self, parsed_args):
cleanup_service.init_conf()
self.options = parsed_args
- self.admin_mgr = credentials.AdminManager()
+ self.admin_mgr = clients.Manager(
+ credentials.get_configured_admin_credentials())
self.dry_run_data = {}
self.json_data = {}
@@ -263,9 +264,10 @@
def _remove_admin_role(self, tenant_id):
LOG.debug("Remove admin user role for tenant: %s", tenant_id)
- # Must initialize AdminManager for each user role
+ # Must initialize Admin Manager for each user role
# Otherwise authentication exception is thrown, weird
- id_cl = credentials.AdminManager().identity_client
+ id_cl = clients.Manager(
+ credentials.get_configured_admin_credentials()).identity_client
if (self._tenant_exists(tenant_id)):
try:
id_cl.delete_role_from_user_on_project(tenant_id,
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 11cd4bb..c75bc85 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -16,11 +16,12 @@
from oslo_log import log as logging
+from tempest import clients
from tempest.common import credentials_factory as credentials
from tempest.common import identity
+from tempest.common import utils
from tempest.common.utils import net_info
from tempest import config
-from tempest import test
LOG = logging.getLogger(__name__)
CONF = config.CONF
@@ -78,7 +79,8 @@
def _get_network_id(net_name, project_name):
- am = credentials.AdminManager()
+ am = clients.Manager(
+ credentials.get_configured_admin_credentials())
net_cl = am.networks_client
tn_cl = am.tenants_client
@@ -962,7 +964,7 @@
tenant_services.append(StackService)
if IS_NEUTRON:
tenant_services.append(NetworkFloatingIpService)
- if test.is_extension_enabled('metering', 'network'):
+ if utils.is_extension_enabled('metering', 'network'):
tenant_services.append(NetworkMeteringLabelRuleService)
tenant_services.append(NetworkMeteringLabelService)
tenant_services.append(NetworkRouterService)
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index 350dd0b..e71032a 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -101,6 +101,7 @@
import six
from testrepository.commands import run_argv
+from tempest import clients
from tempest.cmd import cleanup_service
from tempest.cmd import init
from tempest.cmd import workspace
@@ -216,7 +217,8 @@
print("Initializing saved state.")
data = {}
self.global_services = cleanup_service.get_global_cleanup_services()
- self.admin_mgr = credentials.AdminManager()
+ self.admin_mgr = clients.Manager(
+ credentials.get_configured_admin_credentials())
admin_mgr = self.admin_mgr
kwargs = {'data': data,
'is_dry_run': False,
diff --git a/tempest/cmd/subunit_describe_calls.py b/tempest/cmd/subunit_describe_calls.py
index 8ee3055..f9ebe20 100644
--- a/tempest/cmd/subunit_describe_calls.py
+++ b/tempest/cmd/subunit_describe_calls.py
@@ -102,8 +102,8 @@
response_re = re.compile(r'.* Response - Headers: (?P<headers>.*)')
body_re = re.compile(r'.*Body: (?P<body>.*)')
- # Based on mitaka defaults:
- # http://docs.openstack.org/mitaka/config-reference/
+ # Based on newton defaults:
+ # http://docs.openstack.org/newton/config-reference/
# firewalls-default-ports.html
services = {
"8776": "Block Storage",
@@ -122,7 +122,8 @@
"873": "rsync",
"3260": "iSCSI",
"3306": "MySQL",
- "5672": "AMQP"}
+ "5672": "AMQP",
+ "8082": "murano"}
def __init__(self, services=None):
super(UrlParser, self).__init__()
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 47196ec..df0f5a5 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -198,9 +198,27 @@
body = rest_client.ResponseBody(body.response, body['server'])
servers = [body]
- # The name of the method to associate a floating IP to as server is too
- # long for PEP8 compliance so:
- assoc = clients.compute_floating_ips_client.associate_floating_ip_to_server
+ def _setup_validation_fip():
+ if CONF.service_available.neutron:
+ ifaces = clients.interfaces_client.list_interfaces(server['id'])
+ validation_port = None
+ for iface in ifaces['interfaceAttachments']:
+ if iface['net_id'] == tenant_network['id']:
+ validation_port = iface['port_id']
+ break
+ if not validation_port:
+ # NOTE(artom) This will get caught by the catch-all clause in
+ # the wait_until loop below
+ raise ValueError('Unable to setup floating IP for validation: '
+ 'port not found on tenant network')
+ clients.floating_ips_client.update_floatingip(
+ validation_resources['floating_ip']['id'],
+ port_id=validation_port)
+ else:
+ fip_client = clients.compute_floating_ips_client
+ fip_client.associate_floating_ip_to_server(
+ floating_ip=validation_resources['floating_ip']['ip'],
+ server_id=servers[0]['id'])
if wait_until:
for server in servers:
@@ -212,9 +230,7 @@
# creation will fail with the condition above (l.58).
if CONF.validation.run_validation and validatable:
if CONF.validation.connect_method == 'floating':
- assoc(floating_ip=validation_resources[
- 'floating_ip']['ip'],
- server_id=servers[0]['id'])
+ _setup_validation_fip()
except Exception:
with excutils.save_and_reraise_exception():
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index cecb8e3..a340531 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -44,6 +44,9 @@
identity_uri = CONF.identity.uri_v3
elif identity_version == 'v2':
identity_uri = CONF.identity.uri
+ else:
+ raise exceptions.InvalidIdentityVersion(
+ identity_version=identity_version)
return {
'identity_version': identity_version,
'identity_uri': identity_uri,
diff --git a/tempest/common/utils/__init__.py b/tempest/common/utils/__init__.py
index 84e31d0..5a86caa 100644
--- a/tempest/common/utils/__init__.py
+++ b/tempest/common/utils/__init__.py
@@ -12,10 +12,16 @@
# License for the specific language governing permissions and limitations
# under the License.
+import functools
from functools import partial
+import testtools
+
from tempest import config
+from tempest.exceptions import InvalidServiceTag
from tempest.lib.common.utils import data_utils as lib_data_utils
+from tempest.lib import decorators
+
CONF = config.CONF
@@ -36,3 +42,89 @@
return attr_obj
data_utils = DataUtils()
+
+
+def get_service_list():
+ service_list = {
+ 'compute': CONF.service_available.nova,
+ 'image': CONF.service_available.glance,
+ 'volume': CONF.service_available.cinder,
+ # NOTE(masayukig): We have two network services which are neutron and
+ # nova-network. And we have no way to know whether nova-network is
+ # available or not. After the pending removal of nova-network from
+ # nova, we can treat the network/neutron case in the same manner as
+ # the other services.
+ 'network': True,
+ # NOTE(masayukig): Tempest tests always require the identity service.
+ # So we should set this True here.
+ 'identity': True,
+ 'object_storage': CONF.service_available.swift,
+ }
+ return service_list
+
+
+def services(*args):
+ """A decorator used to set an attr for each service used in a test case
+
+ This decorator applies a testtools attr for each service that gets
+ exercised by a test case.
+ """
+ def decorator(f):
+ known_services = get_service_list()
+
+ for service in args:
+ if service not in known_services:
+ raise InvalidServiceTag('%s is not a valid service' % service)
+ decorators.attr(type=list(args))(f)
+
+ @functools.wraps(f)
+ def wrapper(self, *func_args, **func_kwargs):
+ service_list = get_service_list()
+
+ for service in args:
+ if not service_list[service]:
+ msg = 'Skipped because the %s service is not available' % (
+ service)
+ raise testtools.TestCase.skipException(msg)
+ return f(self, *func_args, **func_kwargs)
+ return wrapper
+ return decorator
+
+
+def requires_ext(**kwargs):
+ """A decorator to skip tests if an extension is not enabled
+
+ @param extension
+ @param service
+ """
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper(*func_args, **func_kwargs):
+ if not is_extension_enabled(kwargs['extension'],
+ kwargs['service']):
+ msg = "Skipped because %s extension: %s is not enabled" % (
+ kwargs['service'], kwargs['extension'])
+ raise testtools.TestCase.skipException(msg)
+ return func(*func_args, **func_kwargs)
+ return wrapper
+ return decorator
+
+
+def is_extension_enabled(extension_name, service):
+ """A function that will check the list of enabled extensions from config
+
+ """
+ config_dict = {
+ 'compute': CONF.compute_feature_enabled.api_extensions,
+ 'volume': CONF.volume_feature_enabled.api_extensions,
+ 'network': CONF.network_feature_enabled.api_extensions,
+ 'object': CONF.object_storage_feature_enabled.discoverable_apis,
+ 'identity': CONF.identity_feature_enabled.api_extensions
+ }
+ if not config_dict[service]:
+ return False
+ if config_dict[service][0] == 'all':
+ return True
+ if extension_name in config_dict[service]:
+ return True
+ return False
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 99a628e..52ccfa9 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -70,7 +70,7 @@
if selected:
return "\n".join(selected)
else:
- msg = "'TYPE' column is requred but the output doesn't have it: "
+ msg = "'TYPE' column is required but the output doesn't have it: "
raise tempest.lib.exceptions.TempestException(msg + output)
def get_boot_time(self):
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index 9e83a07..ae9d584 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -13,45 +13,78 @@
from oslo_log import log as logging
-from tempest import config
-
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
-CONF = config.CONF
LOG = logging.getLogger(__name__)
-def _create_neutron_sec_group_rules(os, sec_group):
- sec_group_rules_client = os.security_group_rules_client
- ethertype = 'IPv4'
- if CONF.validation.ip_version_for_ssh == 6:
- ethertype = 'IPv6'
-
- sec_group_rules_client.create_security_group_rule(
- security_group_id=sec_group['id'],
- protocol='tcp',
- ethertype=ethertype,
- port_range_min=22,
- port_range_max=22,
- direction='ingress')
- sec_group_rules_client.create_security_group_rule(
- security_group_id=sec_group['id'],
- protocol='icmp',
- ethertype=ethertype,
- direction='ingress')
+def _network_service(clients, use_neutron):
+ # Internal helper to select the right network clients
+ if use_neutron:
+ return clients.network
+ else:
+ return clients.compute
-def create_ssh_security_group(os, add_rule=False):
- security_groups_client = os.compute_security_groups_client
- security_group_rules_client = os.compute_security_group_rules_client
+def create_ssh_security_group(clients, add_rule=False, ethertype='IPv4',
+ use_neutron=True):
+ """Create a security group for ping/ssh testing
+
+ Create a security group to be attached to a VM using the nova or neutron
+ clients. If rules are added, the group can be attached to a VM to enable
+ connectivity validation over ICMP and further testing over SSH.
+
+ :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
+ or of a subclass of it. Resources are provisioned using clients from
+ `clients`.
+ :param add_rule: Whether security group rules are provisioned or not.
+ Defaults to `False`.
+ :param ethertype: 'IPv4' or 'IPv6'. Honoured only in case neutron is used.
+ :param use_neutron: When True resources are provisioned via neutron, when
+ False resources are provisioned via nova.
+ :returns: A dictionary with the security group as returned by the API.
+
+ Examples::
+
+ from tempest.common import validation_resources as vr
+ from tempest.lib import auth
+ from tempest.lib.services import clients
+
+ creds = auth.get_credentials('http://mycloud/identity/v3',
+ username='me', project_name='me',
+ password='secret', domain_name='Default')
+ osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
+ # Security group for IPv4 tests
+ sg4 = vr.create_ssh_security_group(osclients, add_rule=True)
+ # Security group for IPv6 tests
+ sg6 = vr.create_ssh_security_group(osclients, ethertype='IPv6',
+ add_rule=True)
+ """
+ network_service = _network_service(clients, use_neutron)
+ security_groups_client = network_service.SecurityGroupsClient()
+ security_group_rules_client = network_service.SecurityGroupRulesClient()
+ # Security Group clients for nova and neutron behave the same
sg_name = data_utils.rand_name('securitygroup-')
sg_description = data_utils.rand_name('description-')
security_group = security_groups_client.create_security_group(
name=sg_name, description=sg_description)['security_group']
+ # Security Group Rules clients require different parameters depending on
+ # the network service in use
if add_rule:
- if CONF.service_available.neutron:
- _create_neutron_sec_group_rules(os, security_group)
+ if use_neutron:
+ security_group_rules_client.create_security_group_rule(
+ security_group_id=security_group['id'],
+ protocol='tcp',
+ ethertype=ethertype,
+ port_range_min=22,
+ port_range_max=22,
+ direction='ingress')
+ security_group_rules_client.create_security_group_rule(
+ security_group_id=security_group['id'],
+ protocol='icmp',
+ ethertype=ethertype,
+ direction='ingress')
else:
security_group_rules_client.create_security_group_rule(
parent_group_id=security_group['id'], ip_protocol='tcp',
@@ -64,91 +97,196 @@
return security_group
-def create_validation_resources(os, validation_resources=None):
+def create_validation_resources(clients, keypair=False, floating_ip=False,
+ security_group=False,
+ security_group_rules=False,
+ ethertype='IPv4', use_neutron=True,
+ floating_network_id=None,
+ floating_network_name=None):
+ """Provision resources for VM ping/ssh testing
+
+ Create resources required to be able to ping / ssh a virtual machine:
+ keypair, security group, security group rules and a floating IP.
+ Which of those resources are required may depend on the cloud setup and on
+ the specific test and it can be controlled via the corresponding
+ arguments.
+
+ Provisioned resources are returned in a dictionary.
+
+ :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
+ or of a subclass of it. Resources are provisioned using clients from
+ `clients`.
+ :param keypair: Whether to provision a keypair. Defaults to False.
+ :param floating_ip: Whether to provision a floating IP. Defaults to False.
+ :param security_group: Whether to provision a security group. Defaults to
+ False.
+ :param security_group_rules: Whether to provision security group rules.
+ Defaults to False.
+ :param ethertype: 'IPv4' or 'IPv6'. Honoured only in case neutron is used.
+ :param use_neutron: When True resources are provisioned via neutron, when
+ False resources are provisioned via nova.
+ :param floating_network_id: The id of the network used to provision a
+ floating IP. Only used if a floating IP is requested and with neutron.
+ :param floating_network_name: The name of the floating IP pool used to
+ provision the floating IP. Only used if a floating IP is requested and
+ with nova-net.
+ :returns: A dictionary with the same keys as the input
+ `validation_resources` and the resources for values in the format
+ they are returned by the API.
+
+ Examples::
+
+ from tempest.common import validation_resources as vr
+ from tempest.lib import auth
+ from tempest.lib.services import clients
+
+ creds = auth.get_credentials('http://mycloud/identity/v3',
+ username='me', project_name='me',
+ password='secret', domain_name='Default')
+ osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
+ # Request keypair and floating IP
+ resources = dict(keypair=True, security_group=False,
+ security_group_rules=False, floating_ip=True)
+ resources = vr.create_validation_resources(
+ osclients, use_neutron=True,
+ floating_network_id='4240E68E-23DA-4C82-AC34-9FEFAA24521C',
+ **resources)
+
+ # The floating IP to be attached to the VM
+ floating_ip = resources['floating_ip']['ip']
+ """
# Create and Return the validation resources required to validate a VM
validation_data = {}
- if validation_resources:
- if validation_resources['keypair']:
- keypair_name = data_utils.rand_name('keypair')
- validation_data.update(os.keypairs_client.create_keypair(
+ if keypair:
+ keypair_name = data_utils.rand_name('keypair')
+ validation_data.update(
+ clients.compute.KeyPairsClient().create_keypair(
name=keypair_name))
- LOG.debug("Validation resource key %s created", keypair_name)
- add_rule = False
- if validation_resources['security_group']:
- if validation_resources['security_group_rules']:
- add_rule = True
- validation_data['security_group'] = \
- create_ssh_security_group(os, add_rule)
- if validation_resources['floating_ip']:
- if CONF.service_available.neutron:
- floatingip = os.floating_ips_client.create_floatingip(
- floating_network_id=CONF.network.public_network_id)
- # validation_resources['floating_ip'] has historically looked
- # like a compute API POST /os-floating-ips response, so we need
- # to mangle it a bit for a Neutron response with different
- # fields.
- validation_data['floating_ip'] = floatingip['floatingip']
- validation_data['floating_ip']['ip'] = (
- floatingip['floatingip']['floating_ip_address'])
- else:
- # NOTE(mriedem): The os-floating-ips compute API was deprecated
- # in the 2.36 microversion. Any tests for CRUD operations on
- # floating IPs using the compute API should be capped at 2.35.
- validation_data.update(
- os.compute_floating_ips_client.create_floating_ip(
- pool=CONF.network.floating_network_name))
+ LOG.debug("Validation resource key %s created", keypair_name)
+ if security_group:
+ validation_data['security_group'] = create_ssh_security_group(
+ clients, add_rule=security_group_rules,
+ use_neutron=use_neutron, ethertype=ethertype)
+ if floating_ip:
+ floating_ip_client = _network_service(
+ clients, use_neutron).FloatingIPsClient()
+ if use_neutron:
+ floatingip = floating_ip_client.create_floatingip(
+ floating_network_id=floating_network_id)
+ # validation_resources['floating_ip'] has historically looked
+ # like a compute API POST /os-floating-ips response, so we need
+ # to mangle it a bit for a Neutron response with different
+ # fields.
+ validation_data['floating_ip'] = floatingip['floatingip']
+ validation_data['floating_ip']['ip'] = (
+ floatingip['floatingip']['floating_ip_address'])
+ else:
+ # NOTE(mriedem): The os-floating-ips compute API was deprecated
+ # in the 2.36 microversion. Any tests for CRUD operations on
+ # floating IPs using the compute API should be capped at 2.35.
+ validation_data.update(floating_ip_client.create_floating_ip(
+ pool=floating_network_name))
return validation_data
-def clear_validation_resources(os, validation_data=None):
- # Cleanup the vm validation resources
+def clear_validation_resources(clients, keypair=None, floating_ip=None,
+ security_group=None, use_neutron=True):
+ """Cleanup resources for VM ping/ssh testing
+
+ Cleanup a set of resources provisioned via `create_validation_resources`.
+ In case of errors during cleanup, the exception is logged and the cleanup
+ process is continued. The first exception that was raised is re-raised
+ after the cleanup is complete.
+
+ :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
+ or of a subclass of it. Resources are provisioned using clients from
+ `clients`.
+ :param keypair: A dictionary with the keypair to be deleted. Defaults to
+ None.
+ :param floating_ip: A dictionary with the floating_ip to be deleted.
+ Defaults to None.
+ :param security_group: A dictionary with the security_group to be deleted.
+ Defaults to None.
+ :param use_neutron: When True resources are provisioned via neutron, when
+ False resources are provisioned via nova.
+ :returns: A dictionary with the same keys as the input
+ `validation_resources` and the resources for values in the format
+ they are returned by the API.
+
+ Examples::
+
+ from tempest.common import validation_resources as vr
+ from tempest.lib import auth
+ from tempest.lib.services import clients
+
+ creds = auth.get_credentials('http://mycloud/identity/v3',
+ username='me', project_name='me',
+ password='secret', domain_name='Default')
+ osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
+ # Request keypair and floating IP
+ resources = dict(keypair=True, security_group=False,
+ security_group_rules=False, floating_ip=True)
+ resources = vr.create_validation_resources(
+ osclients, validation_resources=resources, use_neutron=True,
+ floating_network_id='4240E68E-23DA-4C82-AC34-9FEFAA24521C')
+
+ # Now cleanup the resources
+ try:
+ vr.clear_validation_resources(osclients, use_neutron=True,
+ **resources)
+ except Exception as e:
+ LOG.exception('Something went wrong during cleanup, ignoring')
+ """
has_exception = None
- if validation_data:
- if 'keypair' in validation_data:
- keypair_client = os.keypairs_client
- keypair_name = validation_data['keypair']['name']
- try:
- keypair_client.delete_keypair(keypair_name)
- except lib_exc.NotFound:
- LOG.warning(
- "Keypair %s is not found when attempting to delete",
- keypair_name
- )
- except Exception as exc:
- LOG.exception('Exception raised while deleting key %s',
- keypair_name)
- if not has_exception:
- has_exception = exc
- if 'security_group' in validation_data:
- security_group_client = os.compute_security_groups_client
- sec_id = validation_data['security_group']['id']
- try:
- security_group_client.delete_security_group(sec_id)
- security_group_client.wait_for_resource_deletion(sec_id)
- except lib_exc.NotFound:
- LOG.warning("Security group %s is not found when attempting "
- "to delete", sec_id)
- except lib_exc.Conflict as exc:
- LOG.exception('Conflict while deleting security '
- 'group %s VM might not be deleted', sec_id)
- if not has_exception:
- has_exception = exc
- except Exception as exc:
- LOG.exception('Exception raised while deleting security '
- 'group %s', sec_id)
- if not has_exception:
- has_exception = exc
- if 'floating_ip' in validation_data:
- floating_client = os.compute_floating_ips_client
- fip_id = validation_data['floating_ip']['id']
- try:
- floating_client.delete_floating_ip(fip_id)
- except lib_exc.NotFound:
- LOG.warning('Floating ip %s not found while attempting to '
- 'delete', fip_id)
- except Exception as exc:
- LOG.exception('Exception raised while deleting ip %s', fip_id)
- if not has_exception:
- has_exception = exc
+ if keypair:
+ keypair_client = clients.compute.KeyPairsClient()
+ keypair_name = keypair['name']
+ try:
+ keypair_client.delete_keypair(keypair_name)
+ except lib_exc.NotFound:
+ LOG.warning(
+ "Keypair %s is not found when attempting to delete",
+ keypair_name
+ )
+ except Exception as exc:
+ LOG.exception('Exception raised while deleting key %s',
+ keypair_name)
+ if not has_exception:
+ has_exception = exc
+ network_service = _network_service(clients, use_neutron)
+ if security_group:
+ security_group_client = network_service.SecurityGroupsClient()
+ sec_id = security_group['id']
+ try:
+ security_group_client.delete_security_group(sec_id)
+ security_group_client.wait_for_resource_deletion(sec_id)
+ except lib_exc.NotFound:
+ LOG.warning("Security group %s is not found when attempting "
+ "to delete", sec_id)
+ except lib_exc.Conflict as exc:
+ LOG.exception('Conflict while deleting security '
+ 'group %s VM might not be deleted', sec_id)
+ if not has_exception:
+ has_exception = exc
+ except Exception as exc:
+ LOG.exception('Exception raised while deleting security '
+ 'group %s', sec_id)
+ if not has_exception:
+ has_exception = exc
+ if floating_ip:
+ floating_ip_client = network_service.FloatingIPsClient()
+ fip_id = floating_ip['id']
+ try:
+ if use_neutron:
+ floating_ip_client.delete_floatingip(fip_id)
+ else:
+ floating_ip_client.delete_floating_ip(fip_id)
+ except lib_exc.NotFound:
+ LOG.warning('Floating ip %s not found while attempting to '
+ 'delete', fip_id)
+ except Exception as exc:
+ LOG.exception('Exception raised while deleting ip %s', fip_id)
+ if not has_exception:
+ has_exception = exc
if has_exception:
raise has_exception
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index b5b2d71..a8a6ff0 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -54,3 +54,7 @@
class RFCViolation(exceptions.RestClientException):
message = "RFC Violation"
+
+
+class InvalidServiceTag(exceptions.TempestException):
+ message = "Invalid service tag"
diff --git a/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py b/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py
index a3c9099..28ed816 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py
@@ -65,7 +65,7 @@
'items': {
'type': 'object',
'properties': {
- 'version': {'type': 'integer'},
+ 'version': {'enum': [4, 6]},
'addr': {
'type': 'string',
'oneOf': [
diff --git a/tempest/lib/common/dynamic_creds.py b/tempest/lib/common/dynamic_creds.py
index 90e67b4..9a6c8f5 100644
--- a/tempest/lib/common/dynamic_creds.py
+++ b/tempest/lib/common/dynamic_creds.py
@@ -451,7 +451,7 @@
creds.username)
# NOTE(zhufl): Only when neutron's security_group ext is
# enabled, _cleanup_default_secgroup will not raise error. But
- # here cannot use test.is_extension_enabled for it will cause
+ # here cannot use test_utils.is_extension_enabled for it will cause
# "circular dependency". So here just use try...except to
# ensure tenant deletion without big changes.
try:
diff --git a/tempest/lib/common/http.py b/tempest/lib/common/http.py
index 8a47d44..b4b1fc9 100644
--- a/tempest/lib/common/http.py
+++ b/tempest/lib/common/http.py
@@ -25,8 +25,7 @@
if disable_ssl_certificate_validation:
urllib3.disable_warnings()
kwargs['cert_reqs'] = 'CERT_NONE'
-
- if ca_certs:
+ elif ca_certs:
kwargs['cert_reqs'] = 'CERT_REQUIRED'
kwargs['ca_certs'] = ca_certs
diff --git a/tempest/lib/common/utils/linux/remote_client.py b/tempest/lib/common/utils/linux/remote_client.py
index aef2ff3..cd4092b 100644
--- a/tempest/lib/common/utils/linux/remote_client.py
+++ b/tempest/lib/common/utils/linux/remote_client.py
@@ -67,7 +67,7 @@
def __init__(self, ip_address, username, password=None, pkey=None,
server=None, servers_client=None, ssh_timeout=300,
connect_timeout=60, console_output_enabled=True,
- ssh_shell_prologue="set -eu -o pipefail; PATH=$$PATH:/sbin;",
+ ssh_shell_prologue="set -eu -o pipefail; PATH=$PATH:/sbin;",
ping_count=1, ping_size=56):
"""Executes commands in a VM over ssh
diff --git a/tempest/lib/services/network/security_groups_client.py b/tempest/lib/services/network/security_groups_client.py
index 1f30216..d3ebf20 100644
--- a/tempest/lib/services/network/security_groups_client.py
+++ b/tempest/lib/services/network/security_groups_client.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import exceptions as lib_exc
from tempest.lib.services.network import base
@@ -66,3 +67,10 @@
"""
uri = '/security-groups'
return self.list_resources(uri, **filters)
+
+ def is_resource_deleted(self, id):
+ try:
+ self.show_security_group(id)
+ except lib_exc.NotFound:
+ return True
+ return False
diff --git a/tempest/lib/services/volume/v2/volumes_client.py b/tempest/lib/services/volume/v2/volumes_client.py
index e932adc..d13e449 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -197,10 +197,18 @@
return rest_client.ResponseBody(resp, body)
def is_resource_deleted(self, id):
+ """Check the specified resource is deleted or not.
+
+ :param id: A checked resource id
+ :raises lib_exc.DeleteErrorException: If the specified resource is on
+ the status the delete was failed.
+ """
try:
- self.show_volume(id)
+ volume = self.show_volume(id)
except lib_exc.NotFound:
return True
+ if volume["volume"]["status"] == "error_deleting":
+ raise lib_exc.DeleteErrorException(resource_id=id)
return False
@property
diff --git a/tempest/lib/services/volume/v3/groups_client.py b/tempest/lib/services/volume/v3/groups_client.py
index e261e8e..b463fdf 100644
--- a/tempest/lib/services/volume/v3/groups_client.py
+++ b/tempest/lib/services/volume/v3/groups_client.py
@@ -97,6 +97,18 @@
self.expected_success(202, resp.status)
return rest_client.ResponseBody(resp, body)
+ def update_group(self, group_id, **kwargs):
+ """Updates the specified group.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/block-storage/v3/#update-group
+ """
+ put_body = json.dumps({'group': kwargs})
+ resp, body = self.put('groups/%s' % group_id, put_body)
+ self.expected_success(202, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
def is_resource_deleted(self, id):
try:
self.show_group(id)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 9b8c7a0..2843222 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -79,8 +79,10 @@
cls.security_groups_client = cls.os_primary.security_groups_client
cls.security_group_rules_client = (
cls.os_primary.security_group_rules_client)
- cls.volumes_client = cls.os_primary.volumes_v2_client
- cls.snapshots_client = cls.os_primary.snapshots_v2_client
+ # Use the latest available volume clients
+ if CONF.service_available.cinder:
+ cls.volumes_client = cls.os_primary.volumes_client_latest
+ cls.snapshots_client = cls.os_primary.snapshots_client_latest
# ## Test functions library
#
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 25227be..9ff6227 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -14,10 +14,10 @@
# under the License.
from tempest.common import tempest_fixtures as fixtures
+from tempest.common import utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
class TestAggregatesBasicOps(manager.ScenarioTest):
@@ -97,7 +97,7 @@
@decorators.idempotent_id('cb2b4c4f-0c7c-4164-bdde-6285b302a081')
@decorators.attr(type='slow')
- @test.services('compute')
+ @utils.services('compute')
def test_aggregate_basic_ops(self):
self.useFixture(fixtures.LockFixture('availability_zone'))
az = 'foo_zone'
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index cbdf307..b5220e9 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -13,10 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -54,7 +54,7 @@
@decorators.idempotent_id('79165fb4-5534-4b9d-8429-97ccffb8f86e')
@decorators.attr(type='slow')
- @test.services('compute', 'volume', 'image')
+ @utils.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_luks(self):
server = self.launch_instance()
volume = self.create_encrypted_volume('nova.volume.encryptors.'
@@ -64,7 +64,7 @@
@decorators.idempotent_id('cbc752ed-b716-4717-910f-956cce965722')
@decorators.attr(type='slow')
- @test.services('compute', 'volume', 'image')
+ @utils.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_cryptsetup(self):
server = self.launch_instance()
volume = self.create_encrypted_volume('nova.volume.encryptors.'
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 26a834b..29f1743 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -16,13 +16,13 @@
import testtools
from tempest.common import custom_matchers
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -105,7 +105,7 @@
'The public_network_id option must be specified.')
@testtools.skipUnless(CONF.network_feature_enabled.floating_ips,
'Floating ips are not available')
- @test.services('compute', 'volume', 'image', 'network')
+ @utils.services('compute', 'volume', 'image', 'network')
def test_minimum_basic_scenario(self):
image = self.glance_image_create()
keypair = self.create_keypair()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index c8add8b..340c3c9 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -15,11 +15,11 @@
import testtools
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -59,7 +59,7 @@
def _setup_server(self, keypair):
security_groups = []
- if test.is_extension_enabled('security-group', 'network'):
+ if utils.is_extension_enabled('security-group', 'network'):
security_group = self._create_security_group()
security_groups = [{'name': security_group['name']}]
network, _, _ = self.create_networks()
@@ -107,7 +107,7 @@
@decorators.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_stop_start(self):
keypair = self.create_keypair()
server = self._setup_server(keypair)
@@ -122,7 +122,7 @@
server, keypair, floating_ip)
@decorators.idempotent_id('7b6860c2-afa3-4846-9522-adeb38dfbe08')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_reboot(self):
keypair = self.create_keypair()
server = self._setup_server(keypair)
@@ -133,7 +133,7 @@
@decorators.idempotent_id('88a529c2-1daa-4c85-9aec-d541ba3eb699')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_rebuild(self):
keypair = self.create_keypair()
server = self._setup_server(keypair)
@@ -148,7 +148,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_pause_unpause(self):
keypair = self.create_keypair()
server = self._setup_server(keypair)
@@ -166,7 +166,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_suspend_resume(self):
keypair = self.create_keypair()
server = self._setup_server(keypair)
@@ -184,7 +184,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize is not available.')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_resize(self):
resize_flavor = CONF.compute.flavor_ref_alt
keypair = self.create_keypair()
@@ -205,7 +205,7 @@
'Less than 2 compute nodes, skipping multinode '
'tests.')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_cold_migration(self):
keypair = self.create_keypair()
server = self._setup_server(keypair)
@@ -231,7 +231,7 @@
'Less than 2 compute nodes, skipping multinode '
'tests.')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_connectivity_cold_migration_revert(self):
keypair = self.create_keypair()
server = self._setup_server(keypair)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 48ddac6..2d38b06 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -19,13 +19,13 @@
from oslo_log import log as logging
import testtools
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -87,7 +87,7 @@
'public_network_id must be defined.')
raise cls.skipException(msg)
for ext in ['router', 'security-group']:
- if not test.is_extension_enabled(ext, 'network'):
+ if not utils.is_extension_enabled(ext, 'network'):
msg = "%s extension not enabled." % ext
raise cls.skipException(msg)
if not CONF.network_feature_enabled.floating_ips:
@@ -357,7 +357,7 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_network_basic_ops(self):
"""Basic network operation test
@@ -409,10 +409,10 @@
"floating ip")
@decorators.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
- @testtools.skipUnless(test.is_extension_enabled('net-mtu', 'network'),
+ @testtools.skipUnless(utils.is_extension_enabled('net-mtu', 'network'),
'No way to calculate MTU for networks')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_mtu_sized_frames(self):
"""Validate that network MTU sized frames fit through."""
self._setup_network_and_servers()
@@ -425,7 +425,7 @@
'multitenant network environment')
@decorators.skip_because(bug="1610994")
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_connectivity_between_vms_on_different_networks(self):
"""Test connectivity between VMs on different networks
@@ -479,7 +479,7 @@
@testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
'NIC hotplug not supported for '
'vnic_type direct or macvtap')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_hotplug_nic(self):
"""Test hotplug network interface
@@ -501,7 +501,7 @@
'Router state can be altered only with multitenant '
'networks capabilities')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_update_router_admin_state(self):
"""Test to update admin state up of router
@@ -535,7 +535,7 @@
@testtools.skipUnless(CONF.scenario.dhcp_client,
"DHCP client is not available.")
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_subnet_details(self):
"""Tests that subnet's extra configuration details are affecting VMs.
@@ -619,7 +619,7 @@
"Changing a port's admin state is not supported "
"by the test environment")
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_update_instance_port_admin_state(self):
"""Test to update admin_state_up attribute of instance port
@@ -666,7 +666,7 @@
@decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_preserve_preexisting_port(self):
"""Test preserve pre-existing port
@@ -715,10 +715,10 @@
'server %s.' % server['id'])
self.assertEqual(port['id'], port_list[0]['id'])
- @test.requires_ext(service='network', extension='l3_agent_scheduler')
+ @utils.requires_ext(service='network', extension='l3_agent_scheduler')
@decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_router_rescheduling(self):
"""Tests that router can be removed from agent and add to a new agent.
@@ -793,12 +793,12 @@
should_connect=True,
msg='After router rescheduling')
- @test.requires_ext(service='network', extension='port-security')
+ @utils.requires_ext(service='network', extension='port-security')
@testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
'NIC hotplug not available')
@decorators.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_port_security_macspoofing_port(self):
"""Tests port_security extension enforces mac spoofing
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index bf26c2e..b687aa0 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -14,11 +14,11 @@
# under the License.
import functools
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -210,49 +210,49 @@
@decorators.attr(type='slow')
@decorators.idempotent_id('2c92df61-29f0-4eaa-bee3-7c65bef62a43')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_slaac_from_os(self):
self._prepare_and_test(address6_mode='slaac')
@decorators.attr(type='slow')
@decorators.idempotent_id('d7e1f858-187c-45a6-89c9-bdafde619a9f')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_dhcp6_stateless_from_os(self):
self._prepare_and_test(address6_mode='dhcpv6-stateless')
@decorators.attr(type='slow')
@decorators.idempotent_id('7ab23f41-833b-4a16-a7c9-5b42fe6d4123')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_multi_prefix_dhcpv6_stateless(self):
self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2)
@decorators.attr(type='slow')
@decorators.idempotent_id('dec222b1-180c-4098-b8c5-cc1b8342d611')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_multi_prefix_slaac(self):
self._prepare_and_test(address6_mode='slaac', n_subnets6=2)
@decorators.attr(type='slow')
@decorators.idempotent_id('b6399d76-4438-4658-bcf5-0d6c8584fde2')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_dualnet_slaac_from_os(self):
self._prepare_and_test(address6_mode='slaac', dualnet=True)
@decorators.attr(type='slow')
@decorators.idempotent_id('76f26acd-9688-42b4-bc3e-cd134c4cb09e')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_dualnet_dhcp6_stateless_from_os(self):
self._prepare_and_test(address6_mode='dhcpv6-stateless', dualnet=True)
@decorators.attr(type='slow')
@decorators.idempotent_id('cf1c4425-766b-45b8-be35-e2959728eb00')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_dualnet_multi_prefix_dhcpv6_stateless(self):
self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2,
dualnet=True)
@decorators.idempotent_id('9178ad42-10e4-47e9-8987-e02b170cc5cd')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_dualnet_multi_prefix_slaac(self):
self._prepare_and_test(address6_mode='slaac', n_subnets6=2,
dualnet=True)
diff --git a/tempest/scenario/test_object_storage_basic_ops.py b/tempest/scenario/test_object_storage_basic_ops.py
index 25e9f5c..da0b1e8 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -13,14 +13,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.common import utils
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
class TestObjectStorageBasicOps(manager.ObjectStorageScenarioTest):
@decorators.idempotent_id('b920faf1-7b8a-4657-b9fe-9c4512bfb381')
- @test.services('object_storage')
+ @utils.services('object_storage')
def test_swift_basic_ops(self):
"""Test swift basic ops.
@@ -47,7 +47,7 @@
@decorators.idempotent_id('916c7111-cb1f-44b2-816d-8f760e4ea910')
@decorators.attr(type='slow')
- @test.services('object_storage')
+ @utils.services('object_storage')
def test_swift_acl_anonymous_download(self):
"""This test will cover below steps:
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 51716e8..e39afe0 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -16,12 +16,12 @@
import testtools
from tempest.common import compute
+from tempest.common import utils
from tempest.common.utils import net_info
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
LOG = log.getLogger(__name__)
@@ -142,7 +142,7 @@
msg = ('Either project_networks_reachable must be "true", or '
'public_network_id must be defined.')
raise cls.skipException(msg)
- if not test.is_extension_enabled('security-group', 'network'):
+ if not utils.is_extension_enabled('security-group', 'network'):
msg = "security-group extension not enabled."
raise cls.skipException(msg)
if CONF.network.shared_physical_network:
@@ -471,7 +471,7 @@
servers=[tenant.access_point], client=client)
@decorators.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_cross_tenant_traffic(self):
if not self.credentials_provider.is_multi_tenant():
raise self.skipException("No secondary tenant defined")
@@ -491,7 +491,7 @@
raise
@decorators.idempotent_id('63163892-bbf6-4249-aa12-d5ea1f8f421b')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_in_tenant_traffic(self):
try:
self._create_tenant_servers(self.primary_tenant, num=1)
@@ -505,7 +505,7 @@
@decorators.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_port_update_new_security_group(self):
"""Verifies the traffic after updating the vm port
@@ -559,7 +559,7 @@
@decorators.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
@decorators.attr(type='slow')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_multiple_security_groups(self):
"""Verify multiple security groups and checks that rules
@@ -591,9 +591,9 @@
should_connect=True)
@decorators.attr(type='slow')
- @test.requires_ext(service='network', extension='port-security')
+ @utils.requires_ext(service='network', extension='port-security')
@decorators.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_port_security_disable_security_group(self):
"""Verify the default security group rules is disabled."""
new_tenant = self.primary_tenant
@@ -631,7 +631,7 @@
raise
@decorators.attr(type='slow')
- @test.requires_ext(service='network', extension='port-security')
+ @utils.requires_ext(service='network', extension='port-security')
@decorators.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
# TODO(mriedem): We shouldn't actually need to check this since neutron
# disables the port_security extension by default, but the problem is nova
@@ -641,7 +641,7 @@
@testtools.skipUnless(
CONF.network_feature_enabled.port_security,
'Port security must be enabled.')
- @test.services('compute', 'network')
+ @utils.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)
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 6d6318c..d4f29ad 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -16,11 +16,11 @@
from oslo_log import log as logging
import testtools
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -45,7 +45,7 @@
@decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize is not available.')
- @test.services('compute', 'volume')
+ @utils.services('compute', 'volume')
def test_resize_volume_backed_server_confirm(self):
# We create an instance for use in this test
instance = self.create_server(volume_backed=True)
@@ -67,7 +67,7 @@
@decorators.idempotent_id('949da7d5-72c8-4808-8802-e3d70df98e2c')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
- @test.services('compute')
+ @utils.services('compute')
def test_server_sequence_suspend_resume(self):
# We create an instance for use in this test
instance_id = self.create_server()['id']
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 0c441ab..d5c378e 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -16,6 +16,7 @@
import json
import re
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
@@ -23,7 +24,6 @@
from tempest.lib import decorators
from tempest.lib import exceptions
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -132,7 +132,7 @@
@decorators.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
@decorators.attr(type='smoke')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_server_basic_ops(self):
keypair = self.create_keypair()
security_group = self._create_security_group()
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index 552ab27..fdf875c 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -13,11 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -36,7 +36,7 @@
@decorators.idempotent_id('9cecbe35-b9d4-48da-a37e-7ce70aa43d30')
@decorators.attr(type='smoke')
- @test.services('compute', 'network')
+ @utils.services('compute', 'network')
def test_schedule_to_all_nodes(self):
available_zone = \
self.os_admin.availability_zone_client.list_availability_zones(
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index fc04b44..68f18d1 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -16,11 +16,11 @@
import testtools
from tempest.common import compute
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -78,7 +78,7 @@
@decorators.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
- @test.services('compute', 'network', 'image')
+ @utils.services('compute', 'network', 'image')
def test_shelve_instance(self):
self._create_server_then_shelve_and_unshelve()
@@ -86,6 +86,6 @@
@decorators.idempotent_id('c1b6318c-b9da-490b-9c67-9339b627271f')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
- @test.services('compute', 'volume', 'network', 'image')
+ @utils.services('compute', 'volume', 'network', 'image')
def test_shelve_volume_backed_instance(self):
self._create_server_then_shelve_and_unshelve(boot_from_volume=True)
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 52767dc..b51a781 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -15,10 +15,10 @@
import testtools
+from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
@@ -44,7 +44,7 @@
@decorators.attr(type='slow')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
- @test.services('compute', 'network', 'image')
+ @utils.services('compute', 'network', 'image')
def test_snapshot_pattern(self):
# prepare for booting an instance
keypair = self.create_keypair()
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 3632648..ef369d6 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -16,12 +16,12 @@
from oslo_log import log as logging
import testtools
+from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -76,7 +76,7 @@
'Snapshotting is not available.')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
- @test.services('compute', 'network', 'volume', 'image')
+ @utils.services('compute', 'network', 'volume', 'image')
def test_stamp_pattern(self):
# prepare for booting an instance
keypair = self.create_keypair()
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index b6f3b38..64ea8f6 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -13,12 +13,12 @@
from oslo_log import log as logging
import testtools
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -76,7 +76,7 @@
@decorators.idempotent_id('557cd2c2-4eb8-4dce-98be-f86765ff311b')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
- @test.services('compute', 'volume', 'image')
+ @utils.services('compute', 'volume', 'image')
def test_volume_boot_pattern(self):
"""This test case attempts to reproduce the following steps:
@@ -156,7 +156,7 @@
@decorators.idempotent_id('05795fb2-b2a7-4c9f-8fac-ff25aedb1489')
@decorators.attr(type='slow')
- @test.services('compute', 'image', 'volume')
+ @utils.services('compute', 'image', 'volume')
def test_create_server_from_volume_snapshot(self):
# Create a volume from an image
boot_volume = self._create_volume_from_image()
@@ -192,7 +192,7 @@
created_volume_info['attachments'][0]['volume_id'])
@decorators.idempotent_id('36c34c67-7b54-4b59-b188-02a2f458a63b')
- @test.services('compute', 'volume', 'image')
+ @utils.services('compute', 'volume', 'image')
def test_create_ebs_image_and_check_boot(self):
# create an instance from volume
volume_origin = self._create_volume_from_image()
@@ -216,7 +216,7 @@
@decorators.idempotent_id('cb78919a-e553-4bab-b73b-10cf4d2eb125')
@testtools.skipUnless(CONF.compute_feature_enabled.attach_encrypted_volume,
'Encrypted volume attach is not supported')
- @test.services('compute', 'volume')
+ @utils.services('compute', 'volume')
def test_boot_server_from_encrypted_volume_luks(self):
# Create an encrypted volume
volume = self.create_encrypted_volume('nova.volume.encryptors.'
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index 5667fbb..cd10bbd 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -12,11 +12,11 @@
from oslo_log import log as logging
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
from tempest.scenario import manager
-from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -38,11 +38,6 @@
credentials = ['primary', 'admin']
@classmethod
- def setup_clients(cls):
- super(TestVolumeMigrateRetypeAttached, cls).setup_clients()
- cls.admin_volumes_client = cls.os_admin.volumes_v2_client
-
- @classmethod
def skip_checks(cls):
super(TestVolumeMigrateRetypeAttached, cls).skip_checks()
if not CONF.volume_feature_enabled.multi_backend:
@@ -82,7 +77,7 @@
def _volume_retype_with_migration(self, volume_id, new_volume_type):
migration_policy = 'on-demand'
- self.admin_volumes_client.retype_volume(
+ self.volumes_client.retype_volume(
volume_id, new_type=new_volume_type,
migration_policy=migration_policy)
waiters.wait_for_volume_retype(self.volumes_client,
@@ -90,7 +85,7 @@
@decorators.attr(type='slow')
@decorators.idempotent_id('deadd2c2-beef-4dce-98be-f86765ff311b')
- @test.services('compute', 'volume')
+ @utils.services('compute', 'volume')
def test_volume_migrate_attached(self):
LOG.info("Creating keypair and security group")
keypair = self.create_keypair()
diff --git a/tempest/test.py b/tempest/test.py
index 3c1b5d0..f390ae4 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -14,7 +14,6 @@
# under the License.
import atexit
-import functools
import os
import sys
@@ -26,6 +25,7 @@
from tempest import clients
from tempest.common import credentials_factory as credentials
+from tempest.common import utils
import tempest.common.validation_resources as vresources
from tempest import config
from tempest.lib.common import cred_client
@@ -44,105 +44,24 @@
version='Mitaka', removal_version='?')
-related_bug = debtcollector.moves.moved_function(
- decorators.related_bug, 'related_bug', __name__,
- version='Pike', removal_version='?')
-
-
attr = debtcollector.moves.moved_function(
decorators.attr, 'attr', __name__,
version='Pike', removal_version='?')
-class InvalidServiceTag(lib_exc.TempestException):
- message = "Invalid service tag"
+services = debtcollector.moves.moved_function(
+ utils.services, 'services', __name__,
+ version='Pike', removal_version='?')
-def get_service_list():
- service_list = {
- 'compute': CONF.service_available.nova,
- 'image': CONF.service_available.glance,
- 'volume': CONF.service_available.cinder,
- # NOTE(masayukig): We have two network services which are neutron and
- # nova-network. And we have no way to know whether nova-network is
- # available or not. After the pending removal of nova-network from
- # nova, we can treat the network/neutron case in the same manner as
- # the other services.
- 'network': True,
- # NOTE(masayukig): Tempest tests always require the identity service.
- # So we should set this True here.
- 'identity': True,
- 'object_storage': CONF.service_available.swift,
- }
- return service_list
+requires_ext = debtcollector.moves.moved_function(
+ utils.requires_ext, 'requires_ext', __name__,
+ version='Pike', removal_version='?')
-def services(*args):
- """A decorator used to set an attr for each service used in a test case
-
- This decorator applies a testtools attr for each service that gets
- exercised by a test case.
- """
- def decorator(f):
- known_services = get_service_list()
-
- for service in args:
- if service not in known_services:
- raise InvalidServiceTag('%s is not a valid service' % service)
- decorators.attr(type=list(args))(f)
-
- @functools.wraps(f)
- def wrapper(self, *func_args, **func_kwargs):
- service_list = get_service_list()
-
- for service in args:
- if not service_list[service]:
- msg = 'Skipped because the %s service is not available' % (
- service)
- raise testtools.TestCase.skipException(msg)
- return f(self, *func_args, **func_kwargs)
- return wrapper
- return decorator
-
-
-def requires_ext(**kwargs):
- """A decorator to skip tests if an extension is not enabled
-
- @param extension
- @param service
- """
- def decorator(func):
- @functools.wraps(func)
- def wrapper(*func_args, **func_kwargs):
- if not is_extension_enabled(kwargs['extension'],
- kwargs['service']):
- msg = "Skipped because %s extension: %s is not enabled" % (
- kwargs['service'], kwargs['extension'])
- raise testtools.TestCase.skipException(msg)
- return func(*func_args, **func_kwargs)
- return wrapper
- return decorator
-
-
-def is_extension_enabled(extension_name, service):
- """A function that will check the list of enabled extensions from config
-
- """
- config_dict = {
- 'compute': CONF.compute_feature_enabled.api_extensions,
- 'volume': CONF.volume_feature_enabled.api_extensions,
- 'network': CONF.network_feature_enabled.api_extensions,
- 'object': CONF.object_storage_feature_enabled.discoverable_apis,
- 'identity': CONF.identity_feature_enabled.api_extensions
- }
- if not config_dict[service]:
- return False
- if config_dict[service][0] == 'all':
- return True
- if extension_name in config_dict[service]:
- return True
- return False
-
+is_extension_enabled = debtcollector.moves.moved_function(
+ utils.is_extension_enabled, 'is_extension_enabled', __name__,
+ version='Pike', removal_version='?')
at_exit_set = set()
@@ -378,9 +297,20 @@
@classmethod
def resource_setup(cls):
"""Class level resource setup for test cases."""
+ if (CONF.validation.ip_version_for_ssh not in (4, 6) and
+ CONF.service_available.neutron):
+ msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
+ raise lib_exc.InvalidConfiguration(
+ msg % CONF.validation.ip_version_for_ssh)
if hasattr(cls, "os_primary"):
+ vr = cls.validation_resources
cls.validation_resources = vresources.create_validation_resources(
- cls.os_primary, cls.validation_resources)
+ cls.os_primary,
+ use_neutron=CONF.service_available.neutron,
+ ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
+ floating_network_id=CONF.network.public_network_id,
+ floating_network_name=CONF.network.floating_network_name,
+ **vr)
else:
LOG.warning("Client manager not found, validation resources not"
" created")
@@ -394,8 +324,10 @@
"""
if cls.validation_resources:
if hasattr(cls, "os_primary"):
- vresources.clear_validation_resources(cls.os_primary,
- cls.validation_resources)
+ vr = cls.validation_resources
+ vresources.clear_validation_resources(
+ cls.os_primary,
+ use_neutron=CONF.service_available.neutron, **vr)
cls.validation_resources = {}
else:
LOG.warning("Client manager not found, validation resources "
diff --git a/tempest/tests/cmd/test_run.py b/tempest/tests/cmd/test_run.py
index 7ac347d..6e1250f 100644
--- a/tempest/tests/cmd/test_run.py
+++ b/tempest/tests/cmd/test_run.py
@@ -13,6 +13,7 @@
# under the License.
import argparse
+import atexit
import os
import shutil
import subprocess
@@ -25,6 +26,7 @@
from tempest.tests import base
DEVNULL = open(os.devnull, 'wb')
+atexit.register(DEVNULL.close)
class TestTempestRun(base.TestCase):
@@ -68,6 +70,34 @@
self.assertEqual('i_am_a_fun_little_regex',
self.run_cmd._build_regex(args))
+ def test__build_whitelist_file(self):
+ args = mock.Mock(spec=argparse.Namespace)
+ setattr(args, 'smoke', False)
+ setattr(args, 'regex', None)
+ self.tests = tempfile.NamedTemporaryFile(
+ prefix='whitelist', delete=False)
+ self.tests.write(b"volume \n compute")
+ self.tests.close()
+ setattr(args, 'whitelist_file', self.tests.name)
+ setattr(args, 'blacklist_file', None)
+ self.assertEqual("volume|compute",
+ self.run_cmd._build_regex(args))
+ os.unlink(self.tests.name)
+
+ def test__build_blacklist_file(self):
+ args = mock.Mock(spec=argparse.Namespace)
+ setattr(args, 'smoke', False)
+ setattr(args, 'regex', None)
+ self.tests = tempfile.NamedTemporaryFile(
+ prefix='blacklist', delete=False)
+ self.tests.write(b"volume \n compute")
+ self.tests.close()
+ setattr(args, 'whitelist_file', None)
+ setattr(args, 'blacklist_file', self.tests.name)
+ self.assertEqual("^((?!compute|volume).)*$",
+ self.run_cmd._build_regex(args))
+ os.unlink(self.tests.name)
+
class TestRunReturnCode(base.TestCase):
def setUp(self):
diff --git a/tempest/tests/common/test_credentials_factory.py b/tempest/tests/common/test_credentials_factory.py
new file mode 100644
index 0000000..020818e
--- /dev/null
+++ b/tempest/tests/common/test_credentials_factory.py
@@ -0,0 +1,279 @@
+# Copyright 2017 IBM Corp.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import mock
+from oslo_config import cfg
+import testtools
+
+from tempest.common import credentials_factory as cf
+from tempest import config
+from tempest.lib.common import dynamic_creds
+from tempest.lib.common import preprov_creds
+from tempest.lib import exceptions
+from tempest.tests import base
+from tempest.tests import fake_config
+from tempest.tests.lib import fake_credentials
+
+
+class TestCredentialsFactory(base.TestCase):
+
+ def setUp(self):
+ super(TestCredentialsFactory, self).setUp()
+ self.useFixture(fake_config.ConfigFixture())
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
+
+ def test_get_dynamic_provider_params_creds_v2(self):
+ expected_uri = 'EXPECTED_V2_URI'
+ cfg.CONF.set_default('uri', expected_uri, group='identity')
+ admin_creds = fake_credentials.FakeCredentials()
+ params = cf.get_dynamic_provider_params('v2', admin_creds=admin_creds)
+ expected_params = dict(identity_uri=expected_uri,
+ admin_creds=admin_creds)
+ for key in expected_params:
+ self.assertIn(key, params)
+ self.assertEqual(expected_params[key], params[key])
+
+ def test_get_dynamic_provider_params_creds_v3(self):
+ expected_uri = 'EXPECTED_V3_URI'
+ cfg.CONF.set_default('uri_v3', expected_uri, group='identity')
+ admin_creds = fake_credentials.FakeCredentials()
+ params = cf.get_dynamic_provider_params('v3', admin_creds=admin_creds)
+ expected_params = dict(identity_uri=expected_uri,
+ admin_creds=admin_creds)
+ for key in expected_params:
+ self.assertIn(key, params)
+ self.assertEqual(expected_params[key], params[key])
+
+ def test_get_dynamic_provider_params_creds_vx(self):
+ admin_creds = fake_credentials.FakeCredentials()
+ invalid_version = 'invalid_version_x'
+ with testtools.ExpectedException(
+ exc_type=exceptions.InvalidIdentityVersion,
+ value_re='Invalid version ' + invalid_version):
+ cf.get_dynamic_provider_params(invalid_version,
+ admin_creds=admin_creds)
+
+ def test_get_dynamic_provider_params_no_creds(self):
+ expected_identity_version = 'v3'
+ with mock.patch.object(
+ cf, 'get_configured_admin_credentials') as admin_creds_mock:
+ cf.get_dynamic_provider_params(expected_identity_version)
+ admin_creds_mock.assert_called_once_with(
+ fill_in=True, identity_version=expected_identity_version)
+
+ def test_get_preprov_provider_params_creds_v2(self):
+ expected_uri = 'EXPECTED_V2_URI'
+ cfg.CONF.set_default('uri', expected_uri, group='identity')
+ params = cf.get_preprov_provider_params('v2')
+ self.assertIn('identity_uri', params)
+ self.assertEqual(expected_uri, params['identity_uri'])
+
+ def test_get_preprov_provider_params_creds_v3(self):
+ expected_uri = 'EXPECTED_V3_URI'
+ cfg.CONF.set_default('uri_v3', expected_uri, group='identity')
+ params = cf.get_preprov_provider_params('v3')
+ self.assertIn('identity_uri', params)
+ self.assertEqual(expected_uri, params['identity_uri'])
+
+ def test_get_preprov_provider_params_creds_vx(self):
+ invalid_version = 'invalid_version_x'
+ with testtools.ExpectedException(
+ exc_type=exceptions.InvalidIdentityVersion,
+ value_re='Invalid version ' + invalid_version):
+ cf.get_dynamic_provider_params(invalid_version)
+
+ @mock.patch.object(dynamic_creds, 'DynamicCredentialProvider')
+ @mock.patch.object(cf, 'get_dynamic_provider_params')
+ def test_get_credentials_provider_dynamic(
+ self, mock_dynamic_provider_params,
+ mock_dynamic_credentials_provider_class):
+ cfg.CONF.set_default('use_dynamic_credentials', True, group='auth')
+ expected_params = {'foo': 'bar'}
+ mock_dynamic_provider_params.return_value = expected_params
+ expected_name = 'my_name'
+ expected_network_resources = {'network': 'resources'}
+ expected_identity_version = 'identity_version'
+ cf.get_credentials_provider(
+ expected_name,
+ network_resources=expected_network_resources,
+ force_tenant_isolation=False,
+ identity_version=expected_identity_version)
+ mock_dynamic_provider_params.assert_called_once_with(
+ expected_identity_version)
+ mock_dynamic_credentials_provider_class.assert_called_once_with(
+ name=expected_name, network_resources=expected_network_resources,
+ **expected_params)
+
+ @mock.patch.object(preprov_creds, 'PreProvisionedCredentialProvider')
+ @mock.patch.object(cf, 'get_preprov_provider_params')
+ def test_get_credentials_provider_preprov(
+ self, mock_preprov_provider_params,
+ mock_preprov_credentials_provider_class):
+ cfg.CONF.set_default('use_dynamic_credentials', False, group='auth')
+ cfg.CONF.set_default('test_accounts_file', '/some/file', group='auth')
+ expected_params = {'foo': 'bar'}
+ mock_preprov_provider_params.return_value = expected_params
+ expected_name = 'my_name'
+ expected_identity_version = 'identity_version'
+ cf.get_credentials_provider(
+ expected_name,
+ force_tenant_isolation=False,
+ identity_version=expected_identity_version)
+ mock_preprov_provider_params.assert_called_once_with(
+ expected_identity_version)
+ mock_preprov_credentials_provider_class.assert_called_once_with(
+ name=expected_name, **expected_params)
+
+ def test_get_credentials_provider_preprov_no_file(self):
+ cfg.CONF.set_default('use_dynamic_credentials', False, group='auth')
+ cfg.CONF.set_default('test_accounts_file', None, group='auth')
+ with testtools.ExpectedException(
+ exc_type=exceptions.InvalidConfiguration):
+ cf.get_credentials_provider(
+ 'some_name',
+ force_tenant_isolation=False,
+ identity_version='some_version')
+
+ @mock.patch.object(dynamic_creds, 'DynamicCredentialProvider')
+ @mock.patch.object(cf, 'get_dynamic_provider_params')
+ def test_get_credentials_provider_force_dynamic(
+ self, mock_dynamic_provider_params,
+ mock_dynamic_credentials_provider_class):
+ cfg.CONF.set_default('use_dynamic_credentials', False, group='auth')
+ expected_params = {'foo': 'bar'}
+ mock_dynamic_provider_params.return_value = expected_params
+ expected_name = 'my_name'
+ expected_network_resources = {'network': 'resources'}
+ expected_identity_version = 'identity_version'
+ cf.get_credentials_provider(
+ expected_name,
+ network_resources=expected_network_resources,
+ force_tenant_isolation=True,
+ identity_version=expected_identity_version)
+ mock_dynamic_provider_params.assert_called_once_with(
+ expected_identity_version)
+ mock_dynamic_credentials_provider_class.assert_called_once_with(
+ name=expected_name, network_resources=expected_network_resources,
+ **expected_params)
+
+ @mock.patch.object(cf, 'get_credentials')
+ def test_get_configured_admin_credentials(self, mock_get_credentials):
+ cfg.CONF.set_default('auth_version', 'v3', 'identity')
+ all_params = [('admin_username', 'username', 'my_name'),
+ ('admin_password', 'password', 'secret'),
+ ('admin_project_name', 'project_name', 'my_pname'),
+ ('admin_domain_name', 'domain_name', 'my_dname')]
+ expected_result = 'my_admin_credentials'
+ mock_get_credentials.return_value = expected_result
+ for config_item, _, value in all_params:
+ cfg.CONF.set_default(config_item, value, 'auth')
+ # Build the expected params
+ expected_params = dict(
+ [(field, value) for _, field, value in all_params])
+ expected_params.update(cf.DEFAULT_PARAMS)
+ admin_creds = cf.get_configured_admin_credentials()
+ mock_get_credentials.assert_called_once_with(
+ fill_in=True, identity_version='v3', **expected_params)
+ self.assertEqual(expected_result, admin_creds)
+
+ @mock.patch.object(cf, 'get_credentials')
+ def test_get_configured_admin_credentials_not_fill_valid(
+ self, mock_get_credentials):
+ cfg.CONF.set_default('auth_version', 'v2', 'identity')
+ all_params = [('admin_username', 'username', 'my_name'),
+ ('admin_password', 'password', 'secret'),
+ ('admin_project_name', 'project_name', 'my_pname'),
+ ('admin_domain_name', 'domain_name', 'my_dname')]
+ expected_result = mock.Mock()
+ expected_result.is_valid.return_value = True
+ mock_get_credentials.return_value = expected_result
+ for config_item, _, value in all_params:
+ cfg.CONF.set_default(config_item, value, 'auth')
+ # Build the expected params
+ expected_params = dict(
+ [(field, value) for _, field, value in all_params])
+ expected_params.update(cf.DEFAULT_PARAMS)
+ admin_creds = cf.get_configured_admin_credentials(
+ fill_in=False, identity_version='v3')
+ mock_get_credentials.assert_called_once_with(
+ fill_in=False, identity_version='v3', **expected_params)
+ self.assertEqual(expected_result, admin_creds)
+ expected_result.is_valid.assert_called_once()
+
+ @mock.patch.object(cf, 'get_credentials')
+ def test_get_configured_admin_credentials_not_fill_not_valid(
+ self, mock_get_credentials):
+ cfg.CONF.set_default('auth_version', 'v2', 'identity')
+ expected_result = mock.Mock()
+ expected_result.is_valid.return_value = False
+ mock_get_credentials.return_value = expected_result
+ with testtools.ExpectedException(exceptions.InvalidConfiguration,
+ value_re='.*\n.*identity version v2'):
+ cf.get_configured_admin_credentials(fill_in=False)
+
+ @mock.patch('tempest.lib.auth.get_credentials')
+ def test_get_credentials_v2(self, mock_auth_get_credentials):
+ expected_uri = 'V2_URI'
+ expected_result = 'my_creds'
+ mock_auth_get_credentials.return_value = expected_result
+ cfg.CONF.set_default('uri', expected_uri, 'identity')
+ params = {'foo': 'bar'}
+ expected_params = params.copy()
+ expected_params.update(cf.DEFAULT_PARAMS)
+ result = cf.get_credentials(identity_version='v2', **params)
+ self.assertEqual(expected_result, result)
+ mock_auth_get_credentials.assert_called_once_with(
+ expected_uri, fill_in=True, identity_version='v2',
+ **expected_params)
+
+ @mock.patch('tempest.lib.auth.get_credentials')
+ def test_get_credentials_v3_no_domain(self, mock_auth_get_credentials):
+ expected_uri = 'V3_URI'
+ expected_result = 'my_creds'
+ expected_domain = 'my_domain'
+ mock_auth_get_credentials.return_value = expected_result
+ cfg.CONF.set_default('uri_v3', expected_uri, 'identity')
+ cfg.CONF.set_default('default_credentials_domain_name',
+ expected_domain, 'auth')
+ params = {'foo': 'bar'}
+ expected_params = params.copy()
+ expected_params['domain_name'] = expected_domain
+ expected_params.update(cf.DEFAULT_PARAMS)
+ result = cf.get_credentials(fill_in=False, identity_version='v3',
+ **params)
+ self.assertEqual(expected_result, result)
+ mock_auth_get_credentials.assert_called_once_with(
+ expected_uri, fill_in=False, identity_version='v3',
+ **expected_params)
+
+ @mock.patch('tempest.lib.auth.get_credentials')
+ def test_get_credentials_v3_domain(self, mock_auth_get_credentials):
+ expected_uri = 'V3_URI'
+ expected_result = 'my_creds'
+ expected_domain = 'my_domain'
+ mock_auth_get_credentials.return_value = expected_result
+ cfg.CONF.set_default('uri_v3', expected_uri, 'identity')
+ cfg.CONF.set_default('default_credentials_domain_name',
+ expected_domain, 'auth')
+ params = {'foo': 'bar', 'user_domain_name': expected_domain}
+ expected_params = params.copy()
+ expected_params.update(cf.DEFAULT_PARAMS)
+ result = cf.get_credentials(fill_in=False, identity_version='v3',
+ **params)
+ self.assertEqual(expected_result, result)
+ mock_auth_get_credentials.assert_called_once_with(
+ expected_uri, fill_in=False, identity_version='v3',
+ **expected_params)
diff --git a/tempest/tests/lib/common/test_http.py b/tempest/tests/lib/common/test_http.py
new file mode 100644
index 0000000..a292209
--- /dev/null
+++ b/tempest/tests/lib/common/test_http.py
@@ -0,0 +1,68 @@
+# 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.common import http
+from tempest.tests import base
+
+
+class TestClosingHttp(base.TestCase):
+ def setUp(self):
+ super(TestClosingHttp, self).setUp()
+ self.cert_none = "CERT_NONE"
+ self.cert_location = "/etc/ssl/certs/ca-certificates.crt"
+
+ def test_constructor_invalid_ca_certs_and_timeout(self):
+ connection = http.ClosingHttp(
+ disable_ssl_certificate_validation=False,
+ ca_certs=None,
+ timeout=None)
+ for attr in ('cert_reqs', 'ca_certs', 'timeout'):
+ self.assertNotIn(attr, connection.connection_pool_kw)
+
+ def test_constructor_valid_ca_certs(self):
+ cert_required = 'CERT_REQUIRED'
+ connection = http.ClosingHttp(
+ disable_ssl_certificate_validation=False,
+ ca_certs=self.cert_location,
+ timeout=None)
+ self.assertEqual(cert_required,
+ connection.connection_pool_kw['cert_reqs'])
+ self.assertEqual(self.cert_location,
+ connection.connection_pool_kw['ca_certs'])
+ self.assertNotIn('timeout',
+ connection.connection_pool_kw)
+
+ def test_constructor_ssl_cert_validation_disabled(self):
+ connection = http.ClosingHttp(
+ disable_ssl_certificate_validation=True,
+ ca_certs=None,
+ timeout=30)
+ self.assertEqual(self.cert_none,
+ connection.connection_pool_kw['cert_reqs'])
+ self.assertEqual(30,
+ connection.connection_pool_kw['timeout'])
+ self.assertNotIn('ca_certs',
+ connection.connection_pool_kw)
+
+ def test_constructor_ssl_cert_validation_disabled_and_ca_certs(self):
+ connection = http.ClosingHttp(
+ disable_ssl_certificate_validation=True,
+ ca_certs=self.cert_location,
+ timeout=None)
+ self.assertNotIn('timeout',
+ connection.connection_pool_kw)
+ self.assertEqual(self.cert_none,
+ connection.connection_pool_kw['cert_reqs'])
+ self.assertNotIn('ca_certs',
+ connection.connection_pool_kw)
diff --git a/tempest/tests/lib/common/utils/linux/test_remote_client.py b/tempest/tests/lib/common/utils/linux/test_remote_client.py
index cf312f4..7a21a5f 100644
--- a/tempest/tests/lib/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/lib/common/utils/linux/test_remote_client.py
@@ -34,7 +34,7 @@
client = remote_client.RemoteClient('192.168.1.10', 'username')
client.exec_command('ls')
mock_ssh_exec_command.assert_called_once_with(
- 'set -eu -o pipefail; PATH=$$PATH:/sbin; ls')
+ 'set -eu -o pipefail; PATH=$PATH:/sbin; ls')
@mock.patch.object(ssh.Client, 'test_connection_auth')
def test_validate_authentication(self, mock_test_connection_auth):
diff --git a/tempest/tests/lib/services/volume/v3/test_groups_client.py b/tempest/tests/lib/services/volume/v3/test_groups_client.py
index 4d0d860..0884e5a 100644
--- a/tempest/tests/lib/services/volume/v3/test_groups_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_groups_client.py
@@ -44,6 +44,17 @@
}
}
+ FAKE_UPDATE_GROUP = {
+ "group": {
+ "name": "new-group",
+ "description": "New test group",
+ "add_volumes": "27d45037-ade3-4a87-b729-dba3293c06f3,"
+ "6e7cd916-d961-41cc-b3bd-0601ca0c701f",
+ "remove_volumes": "4d580519-6467-448e-95e9-5b25c94d83c7,"
+ "ea22464c-f095-4a87-a31f-c5d34e0c6fc9"
+ }
+ }
+
FAKE_INFO_GROUP = {
"group": {
"id": "0e701ab8-1bec-4b9f-b026-a7ba4af13578",
@@ -164,3 +175,12 @@
'tempest.lib.common.rest_client.RestClient.post',
self.FAKE_CREATE_GROUP_FROM_GROUP,
status=202)
+
+ def test_update_group(self):
+ self.check_service_client_function(
+ self.client.update_group,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ group_id='0e701ab8-1bec-4b9f-b026-a7ba4af13578',
+ status=202,
+ **self.FAKE_UPDATE_GROUP['group'])
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index a16da1c..37fe646 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -12,11 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-from io import StringIO
import socket
import mock
import six
+from six import StringIO
import testtools
from tempest.lib.common import ssh
diff --git a/tempest/tests/test_base_test.py b/tempest/tests/test_base_test.py
index 6c6f612..3ece11d 100644
--- a/tempest/tests/test_base_test.py
+++ b/tempest/tests/test_base_test.py
@@ -13,10 +13,10 @@
# under the License.
import mock
+from oslo_config import cfg
from tempest import clients
from tempest.common import credentials_factory as credentials
-from tempest import config
from tempest.lib.common import fixed_network
from tempest import test
from tempest.tests import base
@@ -28,8 +28,9 @@
super(TestBaseTestCase, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.fixed_network_name = 'fixed-net'
- config.CONF.compute.fixed_network_name = self.fixed_network_name
- config.CONF.service_available.neutron = True
+ cfg.CONF.set_default('fixed_network_name', self.fixed_network_name,
+ 'compute')
+ cfg.CONF.set_default('neutron', True, 'service_available')
@mock.patch.object(test.BaseTestCase, 'get_client_manager')
@mock.patch.object(test.BaseTestCase, '_get_credentials_provider')
@@ -56,7 +57,7 @@
def test_get_tenant_network_with_nova_net(self, mock_man, mock_iaa,
mock_giv, mock_gtn, mock_gcp,
mock_gcm):
- config.CONF.service_available.neutron = False
+ cfg.CONF.set_default('neutron', False, 'service_available')
mock_prov = mock.Mock()
mock_admin_man = mock.Mock()
mock_iaa.return_value = True
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index 2fc84dc..bf04280 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -16,7 +16,9 @@
from oslo_config import cfg
import testtools
+from tempest.common import utils
from tempest import config
+from tempest import exceptions
from tempest.lib.common.utils import data_utils
from tempest import test
from tempest.tests import base
@@ -31,6 +33,10 @@
fake_config.FakePrivate)
+# NOTE: The test module is for tempest.test.idempotent_id.
+# After all projects switch to use decorators.idempotent_id,
+# we can remove tempest.test.idempotent_id as well as this
+# test module
class TestIdempotentIdDecorator(BaseDecoratorsTest):
def _test_helper(self, _id, **decorator_args):
@@ -71,7 +77,7 @@
class TestServicesDecorator(BaseDecoratorsTest):
def _test_services_helper(self, *decorator_args):
class TestFoo(test.BaseTestCase):
- @test.services(*decorator_args)
+ @utils.services(*decorator_args)
def test_bar(self):
return 0
@@ -90,7 +96,7 @@
self._test_services_helper('compute', 'compute')
def test_services_decorator_with_invalid_service(self):
- self.assertRaises(test.InvalidServiceTag,
+ self.assertRaises(exceptions.InvalidServiceTag,
self._test_services_helper, 'compute',
'bad_service')
@@ -102,11 +108,11 @@
'volume')
def test_services_list(self):
- service_list = test.get_service_list()
+ service_list = utils.get_service_list()
for service in service_list:
try:
self._test_services_helper(service)
- except test.InvalidServiceTag:
+ except exceptions.InvalidServiceTag:
self.fail('%s is not listed in the valid service tag list'
% service)
except KeyError:
@@ -133,7 +139,7 @@
def _test_requires_ext_helper(self, expected_to_skip=True,
**decorator_args):
class TestFoo(test.BaseTestCase):
- @test.requires_ext(**decorator_args)
+ @utils.requires_ext(**decorator_args)
def test_bar(self):
return 0
diff --git a/tempest/tests/test_hacking.py b/tempest/tests/test_hacking.py
index c04d933..bc3a753 100644
--- a/tempest/tests/test_hacking.py
+++ b/tempest/tests/test_hacking.py
@@ -86,13 +86,13 @@
def test_scenario_tests_need_service_tags(self):
self.assertFalse(checks.scenario_tests_need_service_tags(
'def test_fake:', './tempest/scenario/test_fake.py',
- "@test.services('compute')"))
+ "@utils.services('compute')"))
self.assertFalse(checks.scenario_tests_need_service_tags(
'def test_fake_test:', './tempest/api/compute/test_fake.py',
- "@test.services('image')"))
+ "@utils.services('image')"))
self.assertFalse(checks.scenario_tests_need_service_tags(
'def test_fake:', './tempest/scenario/orchestration/test_fake.py',
- "@test.services('compute')"))
+ "@utils.services('compute')"))
self.assertTrue(checks.scenario_tests_need_service_tags(
'def test_fake_test:', './tempest/scenario/test_fake.py',
'\n'))
@@ -113,12 +113,13 @@
def test_service_tags_not_in_module_path(self):
self.assertTrue(checks.service_tags_not_in_module_path(
- "@test.services('compute')", './tempest/api/compute/fake_test.py'))
+ "@utils.services('compute')",
+ './tempest/api/compute/fake_test.py'))
self.assertFalse(checks.service_tags_not_in_module_path(
- "@test.services('compute')",
+ "@utils.services('compute')",
'./tempest/scenario/compute/fake_test.py'))
self.assertFalse(checks.service_tags_not_in_module_path(
- "@test.services('compute')", './tempest/api/image/fake_test.py'))
+ "@utils.services('compute')", './tempest/api/image/fake_test.py'))
def test_no_hyphen_at_end_of_rand_name(self):
self.assertIsNone(checks.no_hyphen_at_end_of_rand_name(
diff --git a/test-requirements.txt b/test-requirements.txt
index 09c7685..29f0865 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -5,8 +5,8 @@
# needed for doc build
sphinx>=1.6.2 # BSD
openstackdocstheme>=1.16.0 # Apache-2.0
-reno!=2.3.1,>=1.8.0 # Apache-2.0
-mock>=2.0 # BSD
+reno>=2.5.0 # Apache-2.0
+mock>=2.0.0 # BSD
coverage!=4.4,>=4.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
flake8-import-order==0.11 # LGPLv3
diff --git a/tox.ini b/tox.ini
index 6f37d00..24e3b5d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -138,6 +138,7 @@
[testenv:docs]
commands =
+ rm -rf doc/build
python setup.py build_sphinx {posargs}
[testenv:pep8]
@@ -159,12 +160,14 @@
# E129 skipped because it is too limiting when combined with other rules
ignore = E125,E123,E129
show-source = True
-exclude = .git,.venv,.tox,dist,doc,*egg
+exclude = .git,.venv,.tox,dist,doc,*egg,build
enable-extensions = H106,H203,H904
import-order-style = pep8
[testenv:releasenotes]
-commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
+commands =
+ rm -rf releasenotes/build
+ 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