Merge "Add admin_servers_client in BaseV2ComputeAdminTest"
diff --git a/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml b/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
index 484d543..d07448a 100644
--- a/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
+++ b/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
@@ -4,7 +4,7 @@
plugins to declare and automatically register any service client defined
in the plugin.
- tempest.lib exposes a new stable interface, the clients module and
- ServiceClients class, which provides a convinient way for plugin tests to
+ ServiceClients class, which provides a convenient way for plugin tests to
access service clients defined in Tempest as well as service clients
defined in all loaded plugins.
The new ServiceClients class only exposes for now the service clients
diff --git a/releasenotes/notes/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml b/releasenotes/notes/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
index 543cf7b..52c04af 100644
--- a/releasenotes/notes/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
+++ b/releasenotes/notes/13.0.0-move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
@@ -2,4 +2,4 @@
deprecations:
- The ``call_until_true`` function is moved from the ``tempest.test`` module
to the ``tempest.lib.common.utils.test_utils`` module. Backward
- compatibilty is preserved until Ocata.
+ compatibility is preserved until Ocata.
diff --git a/releasenotes/notes/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml b/releasenotes/notes/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
index 20f310d..813e47f 100644
--- a/releasenotes/notes/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
+++ b/releasenotes/notes/13.0.0-tempest-cleanup-nostandalone-39df2aafb2545d35.yaml
@@ -1,5 +1,5 @@
---
upgrade:
- - the already depreacted tempest-cleanup standalone command has been
+ - the already deprecated tempest-cleanup standalone command has been
removed. The corresponding functionalities can be accessed through
the unified `tempest` command (`tempest cleanup`).
diff --git a/releasenotes/notes/add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml b/releasenotes/notes/add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml
new file mode 100644
index 0000000..67f9541
--- /dev/null
+++ b/releasenotes/notes/add-list-security-groups-by-servers-to-servers-client-library-088df48f6d81f4be.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Add the list security groups by server API to the servers_client
+ library. This feature enables the possibility to list security
+ groups for a server instance.
diff --git a/releasenotes/notes/remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml b/releasenotes/notes/remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml
new file mode 100644
index 0000000..b1c0c62
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-compute-microversion-config-options-eaee6a7d2f8390a8.yaml
@@ -0,0 +1,9 @@
+---
+upgrade:
+ - The deprecated compute microversion config options from
+ 'compute-feature-enabled' group have been removed. Those config options
+ are available under 'compute' group to configure the min and max
+ microversion for compute service.
+
+ * CONF.compute.min_microversion
+ * CONF.compute.max_microversion
diff --git a/releasenotes/notes/remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml b/releasenotes/notes/remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
new file mode 100644
index 0000000..8665b8b
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
@@ -0,0 +1,14 @@
+---
+upgrade:
+ - |
+ Below deprecated config options from compute group have been removed.
+ Corresponding config options already been available in validation group.
+
+ - ``compute.use_floatingip_for_ssh`` (available as ``validation.connect_method``)
+ - ``compute.ssh_auth_method`` (available as ``validation.auth_method``)
+ - ``compute.image_ssh_password`` (available as ``validation.image_ssh_password``)
+ - ``compute.ssh_shell_prologue`` (available as ``validation.ssh_shell_prologue``)
+ - ``compute.ping_size `` (available as ``validation.ping_size``)
+ - ``compute.ping_count `` (available as ``validation.ping_count``)
+ - ``compute.floating_ip_range `` (available as ``validation.floating_ip_range``)
+
diff --git a/releasenotes/notes/remove-deprecated-network-config-options-f9ce276231578fe6.yaml b/releasenotes/notes/remove-deprecated-network-config-options-f9ce276231578fe6.yaml
new file mode 100644
index 0000000..e445fb3
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-network-config-options-f9ce276231578fe6.yaml
@@ -0,0 +1,11 @@
+---
+upgrade:
+ - |
+ Below deprecated network config options have been removed.
+ Those config options already been renamed to below meaningful names.
+
+ - ``tenant_network_cidr`` (removed) -> ``project_network_cidr``
+ - ``tenant_network_mask_bits`` (removed) -> ``project_network_mask_bits``
+ - ``tenant_network_v6_cidr`` (removed) -> ``project_network_v6_cidr``
+ - ``tenant_network_v6_mask_bits`` (removed) -> ``project_network_v6_mask_bits``
+ - ``tenant_networks_reachable`` (removed) -> ``project_networks_reachable``
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 242d133..cea76b4 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
:maxdepth: 1
unreleased
+ v15.0.0
v14.0.0
v13.0.0
v12.0.0
diff --git a/releasenotes/source/v15.0.0.rst b/releasenotes/source/v15.0.0.rst
new file mode 100644
index 0000000..2ee1894
--- /dev/null
+++ b/releasenotes/source/v15.0.0.rst
@@ -0,0 +1,6 @@
+=====================
+v15.0.0 Release Notes
+=====================
+
+.. release-notes:: 15.0.0 Release Notes
+ :version: 15.0.0
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index deded73..00107cd 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -34,7 +34,6 @@
def resource_setup(cls):
super(AggregatesAdminNegativeTestJSON, cls).resource_setup()
cls.aggregate_name_prefix = 'test_aggregate'
- cls.az_name_prefix = 'test_az'
hosts_all = cls.os_adm.hosts_client.list_hosts()['hosts']
hosts = ([host['host_name']
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index f3a5e01..0a9db46 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -80,20 +80,17 @@
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
# Create the flavor
- flavor = self.create_flavor(name=flavor_name,
- ram=self.ram, vcpus=self.vcpus,
- disk=self.disk,
- ephemeral=self.ephemeral,
- swap=self.swap,
- rxtx_factor=self.rxtx)
- flag = False
- # Verify flavor is retrieved
- flavors = self.admin_flavors_client.list_flavors(
+ self.create_flavor(name=flavor_name,
+ ram=self.ram, vcpus=self.vcpus,
+ disk=self.disk,
+ ephemeral=self.ephemeral,
+ swap=self.swap,
+ rxtx_factor=self.rxtx)
+
+ # Check if flavor is present in list
+ flavors_list = self.admin_flavors_client.list_flavors(
detail=True)['flavors']
- for flavor in flavors:
- if flavor['name'] == flavor_name:
- flag = True
- self.assertTrue(flag)
+ self.assertIn(flavor_name, [f['name'] for f in flavors_list])
@decorators.idempotent_id('63dc64e6-2e79-4fdf-868f-85500d308d66')
def test_create_list_flavor_without_extra_data(self):
@@ -128,13 +125,12 @@
verify_flavor_response_extension(flavor)
# Check if flavor is present in list
- flag = False
- flavors = self.flavors_client.list_flavors(detail=True)['flavors']
- for flavor in flavors:
- if flavor['name'] == flavor_name:
- verify_flavor_response_extension(flavor)
- flag = True
- self.assertTrue(flag)
+ flavors_list = [
+ f for f in self.flavors_client.list_flavors(detail=True)['flavors']
+ if f['name'] == flavor_name
+ ]
+ self.assertNotEmpty(flavors_list)
+ verify_flavor_response_extension(flavors_list[0])
@decorators.idempotent_id('be6cc18c-7c5d-48c0-ac16-17eaf03c54eb')
def test_list_non_public_flavor(self):
@@ -145,26 +141,18 @@
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
# Create the flavor
- flavor = self.create_flavor(name=flavor_name,
- ram=self.ram, vcpus=self.vcpus,
- disk=self.disk,
- is_public="False")
- # Verify flavor is retrieved
- flag = False
- flavors = self.admin_flavors_client.list_flavors(
+ self.create_flavor(name=flavor_name,
+ ram=self.ram, vcpus=self.vcpus,
+ disk=self.disk,
+ is_public="False")
+ # Verify flavor is not retrieved
+ flavors_list = self.admin_flavors_client.list_flavors(
detail=True)['flavors']
- for flavor in flavors:
- if flavor['name'] == flavor_name:
- flag = True
- self.assertFalse(flag)
+ self.assertNotIn(flavor_name, [f['name'] for f in flavors_list])
# Verify flavor is not retrieved with other user
- flag = False
- flavors = self.flavors_client.list_flavors(detail=True)['flavors']
- for flavor in flavors:
- if flavor['name'] == flavor_name:
- flag = True
- self.assertFalse(flag)
+ flavors_list = self.flavors_client.list_flavors(detail=True)['flavors']
+ self.assertNotIn(flavor_name, [f['name'] for f in flavors_list])
@decorators.idempotent_id('bcc418ef-799b-47cc-baa1-ce01368b8987')
def test_create_server_with_non_public_flavor(self):
@@ -186,17 +174,13 @@
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
# Create the flavor
- flavor = self.create_flavor(name=flavor_name,
- ram=self.ram, vcpus=self.vcpus,
- disk=self.disk,
- is_public="True")
- flag = False
+ self.create_flavor(name=flavor_name,
+ ram=self.ram, vcpus=self.vcpus,
+ disk=self.disk,
+ is_public="True")
# Verify flavor is retrieved with new user
- flavors = self.flavors_client.list_flavors(detail=True)['flavors']
- for flavor in flavors:
- if flavor['name'] == flavor_name:
- flag = True
- self.assertTrue(flag)
+ flavors_list = self.flavors_client.list_flavors(detail=True)['flavors']
+ self.assertIn(flavor_name, [f['name'] for f in flavors_list])
@decorators.idempotent_id('fb9cbde6-3a0e-41f2-a983-bdb0a823c44e')
def test_is_public_string_variations(self):
@@ -215,20 +199,13 @@
disk=self.disk,
is_public="True")
- def _flavor_lookup(flavors, flavor_name):
- for flavor in flavors:
- if flavor['name'] == flavor_name:
- return flavor
- return None
-
def _test_string_variations(variations, flavor_name):
for string in variations:
params = {'is_public': string}
flavors = (self.admin_flavors_client.list_flavors(detail=True,
**params)
['flavors'])
- flavor = _flavor_lookup(flavors, flavor_name)
- self.assertIsNotNone(flavor)
+ self.assertIn(flavor_name, [f['name'] for f in flavors])
_test_string_variations(['f', 'false', 'no', '0'],
flavor_name_not_public)
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 8ec6400..ee1e3a0 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -41,7 +41,7 @@
vcpus = 1
disk = 10
ephemeral = 10
- cls.new_flavor_id = data_utils.rand_int_id(start=1000)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
swap = 1024
rxtx = 1
# Create a flavor so as to set/get/unset extra specs
@@ -49,7 +49,7 @@
name=flavor_name,
ram=ram, vcpus=vcpus,
disk=disk,
- id=cls.new_flavor_id,
+ id=new_flavor_id,
ephemeral=ephemeral,
swap=swap,
rxtx_factor=rxtx)['flavor']
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 79a9068..dab83e5 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -43,7 +43,7 @@
vcpus = 1
disk = 10
ephemeral = 10
- cls.new_flavor_id = data_utils.rand_int_id(start=1000)
+ new_flavor_id = data_utils.rand_int_id(start=1000)
swap = 1024
rxtx = 1
# Create a flavor
@@ -51,7 +51,7 @@
name=flavor_name,
ram=ram, vcpus=vcpus,
disk=disk,
- id=cls.new_flavor_id,
+ id=new_flavor_id,
ephemeral=ephemeral,
swap=swap,
rxtx_factor=rxtx)['flavor']
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 1283629..b53ced9 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -42,9 +42,7 @@
super(ServersAdminNegativeTestJSON, cls).resource_setup()
cls.tenant_id = cls.client.tenant_id
- cls.s1_name = data_utils.rand_name(cls.__name__ + '-server')
- server = cls.create_test_server(name=cls.s1_name,
- wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.s1_id = server['id']
def _get_unused_flavor_id(self):
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
new file mode 100644
index 0000000..a70c0a9
--- /dev/null
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -0,0 +1,89 @@
+# Copyright 2017 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import random
+
+import six
+
+from tempest.api.compute import base
+from tempest.common import image as common_image
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest.lib import exceptions as lib_exc
+from tempest import test
+
+CONF = config.CONF
+
+
+class FlavorsV2NegativeTest(base.BaseV2ComputeTest):
+
+ @classmethod
+ def setup_clients(cls):
+ super(FlavorsV2NegativeTest, cls).setup_clients()
+ if CONF.image_feature_enabled.api_v1:
+ cls.images_client = cls.os.image_client
+ elif CONF.image_feature_enabled.api_v2:
+ cls.images_client = cls.os.image_client_v2
+ else:
+ raise lib_exc.InvalidConfiguration(
+ 'Either api_v1 or api_v2 must be True in '
+ '[image-feature-enabled].')
+
+ @test.attr(type=['negative'])
+ @test.services('image')
+ @test.idempotent_id('90f0d93a-91c1-450c-91e6-07d18172cefe')
+ def test_boot_with_low_ram(self):
+ """Try boot a vm with lower than min ram
+
+ Create an image with min_ram value
+ Try to create server with flavor of insufficient ram size from
+ that image
+ """
+ flavor = self.flavors_client.show_flavor(
+ CONF.compute.flavor_ref)['flavor']
+ min_img_ram = flavor['ram'] + 1
+ size = random.randint(1024, 4096)
+ image_file = six.BytesIO(data_utils.random_bytes(size))
+ params = {
+ 'name': data_utils.rand_name('image'),
+ 'container_format': CONF.image.container_formats[0],
+ 'disk_format': CONF.image.disk_formats[0],
+ 'min_ram': min_img_ram
+ }
+
+ if CONF.image_feature_enabled.api_v1:
+ params.update({'is_public': False})
+ params = {'headers': common_image.image_meta_to_headers(**params)}
+ else:
+ params.update({'visibility': 'private'})
+
+ image = self.images_client.create_image(**params)
+ image = image['image'] if 'image' in image else image
+ self.addCleanup(self.images_client.delete_image, image['id'])
+
+ if CONF.image_feature_enabled.api_v1:
+ self.images_client.update_image(image['id'], data=image_file)
+ else:
+ self.images_client.store_image_file(image['id'], data=image_file)
+
+ self.assertEqual(min_img_ram, image['min_ram'])
+
+ # Try to create server with flavor of insufficient ram size
+ self.assertRaisesRegexp(lib_exc.BadRequest,
+ "Flavor's memory is too small for "
+ "requested image",
+ self.create_test_server,
+ image_id=image['id'],
+ flavor=flavor['id'])
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 4d8416f..2769245 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.api.compute.floating_ips import base
from tempest import config
from tempest.lib.common.utils import test_utils
@@ -86,6 +88,8 @@
@decorators.idempotent_id('307efa27-dc6f-48a0-8cd2-162ce3ef0b52')
@test.services('network')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
def test_associate_disassociate_floating_ip(self):
# Positive test:Associate and disassociate the provided floating IP
# to a specific server should be successful
@@ -107,6 +111,8 @@
@decorators.idempotent_id('6edef4b2-aaf1-4abc-bbe3-993e2561e0fe')
@test.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):
# positive test:Association of an already associated floating IP
# to specific server should change the association of the Floating IP
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 7658848..b82fa3b 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -31,7 +31,6 @@
@classmethod
def resource_setup(cls):
super(SecurityGroupRulesTestJSON, cls).resource_setup()
- cls.neutron_available = CONF.service_available.neutron
cls.ip_protocol = 'tcp'
cls.from_port = 22
cls.to_port = 22
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index e070336..349bfda 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -144,3 +144,31 @@
['security_group'])
self.assertEqual(s_new_name, fetched_group['name'])
self.assertEqual(s_new_des, fetched_group['description'])
+
+ @test.idempotent_id('79517d60-535a-438f-af3d-e6feab1cbea7')
+ @test.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
+ sg = self.create_security_group()
+ sg2 = self.create_security_group()
+ assigned_security_groups_ids = [sg['id'], sg2['id']]
+ # Create server and add the security group created
+ # above to the server we just created
+ server_id = self.create_test_server(wait_until='ACTIVE')['id']
+ # add security groups to server
+ self.servers_client.add_security_group(server_id, name=sg['name'])
+ self.servers_client.add_security_group(server_id, name=sg2['name'])
+
+ # list security groups for a server
+ fetched_groups = (
+ self.servers_client.list_security_groups_by_server(
+ server_id)['security_groups'])
+ fetched_security_groups_ids = [i['id'] for i in fetched_groups]
+ # verifying the security groups ids in list
+ missing_security_groups =\
+ [p for p in assigned_security_groups_ids
+ if p not in fetched_security_groups_ids]
+ self.assertEmpty(missing_security_groups,
+ "Failed to find security_groups %s in fetched list" %
+ ', '.join(missing_security_groups))
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 ad18861..48bb1b6 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -32,11 +32,6 @@
super(SecurityGroupsNegativeTestJSON, cls).setup_clients()
cls.client = cls.security_groups_client
- @classmethod
- def resource_setup(cls):
- super(SecurityGroupsNegativeTestJSON, cls).resource_setup()
- cls.neutron_available = CONF.service_available.neutron
-
@test.attr(type=['negative'])
@decorators.idempotent_id('673eaec1-9b3e-48ed-bdf1-2786c1b9661c')
@test.services('network')
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 5ddae5e..a94c20b 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -51,7 +51,7 @@
cls.name = data_utils.rand_name(cls.__name__ + '-server')
cls.password = data_utils.rand_password()
disk_config = cls.disk_config
- cls.server_initial = cls.create_test_server(
+ server_initial = cls.create_test_server(
validatable=True,
wait_until='ACTIVE',
name=cls.name,
@@ -60,7 +60,7 @@
accessIPv6=cls.accessIPv6,
disk_config=disk_config,
adminPass=cls.password)
- cls.server = (cls.client.show_server(cls.server_initial['id'])
+ cls.server = (cls.client.show_server(server_initial['id'])
['server'])
def _create_net_subnet_ret_net_from_cidr(self, cidr):
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 594c5c9..3010caf 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -35,11 +35,9 @@
# by the test methods in this class. These
# servers are cleaned up automatically in the
# tearDownClass method of the super-class.
- cls.existing_fixtures = []
cls.deleted_fixtures = []
for _ in range(2):
srv = cls.create_test_server(wait_until='ACTIVE')
- cls.existing_fixtures.append(srv)
srv = cls.create_test_server(wait_until='ACTIVE')
cls.client.delete_server(srv['id'])
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index 04fe11f..3f6abab 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -1,4 +1,4 @@
-# Copyright 2016 OpenStack Foundation
+# Copyright 2016-2017 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -26,6 +26,11 @@
CONF = config.CONF
+if six.PY2:
+ ord_func = ord
+else:
+ ord_func = int
+
class NoVNCConsoleTestJSON(base.BaseV2ComputeTest):
@@ -60,14 +65,19 @@
resp = urllib3.PoolManager().request('GET', vnc_url)
# Make sure that the GET request was accepted by the novncproxy
self.assertEqual(resp.status, 200, 'Got a Bad HTTP Response on the '
- 'initial call: ' + str(resp.status))
+ 'initial call: ' + six.text_type(resp.status))
# Do some basic validation to make sure it is an expected HTML document
- self.assertTrue('<html>' in resp.data and '</html>' in resp.data,
- 'Not a valid html document in the response.')
+ resp_data = resp.data.decode()
+ self.assertIn('<html>', resp_data,
+ 'Not a valid html document in the response.')
+ self.assertIn('</html>', resp_data,
+ 'Not a valid html document in the response.')
# Just try to make sure we got JavaScript back for noVNC, since we
# won't actually use it since not inside of a browser
- self.assertTrue('noVNC' in resp.data and '<script' in resp.data,
- 'Not a valid noVNC javascript html document.')
+ self.assertIn('noVNC', resp_data,
+ 'Not a valid noVNC javascript html document.')
+ self.assertIn('<script', resp_data,
+ 'Not a valid noVNC javascript html document.')
def _validate_rfb_negotiation(self):
"""Verify we can connect to novnc and do the websocket connection."""
@@ -82,14 +92,14 @@
int(data[8:11], base=10)))
self.assertTrue(version >= 3.3, 'Bad RFB Version: ' + str(version))
# Send our RFB version to the server, which we will just go with 3.3
- self._websocket.send_frame(str(data))
+ self._websocket.send_frame(data)
# Get the sever authentication type and make sure None is supported
data = self._websocket.receive_frame()
self.assertIsNotNone(data, 'Expected authentication type None.')
self.assertGreaterEqual(
len(data), 2, 'Expected authentication type None.')
self.assertIn(
- 1, [ord(data[i + 1]) for i in range(ord(data[0]))],
+ 1, [ord_func(data[i + 1]) for i in range(ord_func(data[0]))],
'Expected authentication type None.')
# Send to the server that we only support authentication type None
self._websocket.send_frame(six.int2byte(1))
@@ -98,7 +108,7 @@
self.assertEqual(
len(data), 4, 'Server did not think security was successful.')
self.assertEqual(
- [ord(i) for i in data], [0, 0, 0, 0],
+ [ord_func(i) for i in data], [0, 0, 0, 0],
'Server did not think security was successful.')
# Say to leave the desktop as shared as part of client initialization
self._websocket.send_frame(six.int2byte(1))
@@ -121,12 +131,12 @@
def _validate_websocket_upgrade(self):
self.assertTrue(
- self._websocket.response.startswith('HTTP/1.1 101 Switching '
- 'Protocols\r\n'),
+ self._websocket.response.startswith(b'HTTP/1.1 101 Switching '
+ b'Protocols\r\n'),
'Did not get the expected 101 on the websockify call: '
- + str(len(self._websocket.response)))
+ + six.text_type(self._websocket.response))
self.assertTrue(
- self._websocket.response.find('Server: WebSockify') > 0,
+ self._websocket.response.find(b'Server: WebSockify') > 0,
'Did not get the expected WebSocket HTTP Response.')
def _create_websocket(self, url):
@@ -187,8 +197,8 @@
# frames less than 125 bytes here (for the negotiation) and
# that only the 2nd byte contains the length, and since the
# server doesn't do masking, we can just read the data length
- if ord(header[1]) & 127 > 0:
- return self._socket.recv(ord(header[1]) & 127)
+ if ord_func(header[1]) & 127 > 0:
+ return self._socket.recv(ord_func(header[1]) & 127)
def send_frame(self, data):
"""Wrapper for sending data to add in the WebSocket frame format."""
@@ -205,7 +215,7 @@
frame_bytes.append(mask[i])
# Mask each of the actual data bytes that we are going to send
for i in range(len(data)):
- frame_bytes.append(ord(data[i]) ^ mask[i % 4])
+ frame_bytes.append(ord_func(data[i]) ^ mask[i % 4])
# Convert our integer list to a binary array of bytes
frame_bytes = struct.pack('!%iB' % len(frame_bytes), * frame_bytes)
self._socket.sendall(frame_bytes)
@@ -233,9 +243,9 @@
# We are choosing to use binary even though browser may do Base64
reqdata += 'Sec-WebSocket-Protocol: binary\r\n\r\n'
# Send the HTTP GET request and get the response back
- self._socket.sendall(reqdata)
+ self._socket.sendall(reqdata.encode('utf8'))
self.response = data = self._socket.recv(4096)
# Loop through & concatenate all of the data in the response body
- while len(data) > 0 and self.response.find('\r\n\r\n') < 0:
+ while len(data) > 0 and self.response.find(b'\r\n\r\n') < 0:
data = self._socket.recv(4096)
self.response += data
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 5db7f4f..209ab38 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest.common import waiters
@@ -48,9 +50,9 @@
# Security group creation
cls.sg_name = data_utils.rand_name('sg')
- cls.sg_desc = data_utils.rand_name('sg-desc')
+ sg_desc = data_utils.rand_name('sg-desc')
cls.sg = cls.security_groups_client.create_security_group(
- name=cls.sg_name, description=cls.sg_desc)['security_group']
+ name=cls.sg_name, description=sg_desc)['security_group']
cls.sg_id = cls.sg['id']
cls.password = data_utils.rand_password()
@@ -85,6 +87,8 @@
'ACTIVE')
@decorators.idempotent_id('4842e0cf-e87d-4d9d-b61f-f4791da3cacc')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
def test_rescued_vm_associate_dissociate_floating_ip(self):
# Rescue the server
self.servers_client.rescue_server(
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index dd9d408..0d8214f 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -44,13 +44,11 @@
super(VolumesTestJSON, cls).resource_setup()
# Create 3 Volumes
cls.volume_list = []
- cls.volume_id_list = []
for _ in range(3):
metadata = {'Type': 'work'}
volume = cls.create_volume(metadata=metadata)
volume = cls.client.show_volume(volume['id'])['volume']
cls.volume_list.append(volume)
- cls.volume_id_list.append(volume['id'])
@decorators.idempotent_id('bc2dd1a0-15af-48e5-9990-f2e75a48325d')
def test_volume_list(self):
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 9515788..3bbe47a 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -67,7 +67,7 @@
return role[0]
def _create_test_user(self, **kwargs):
- if kwargs['password'] is None:
+ if kwargs.get('password', None) is None:
user_password = data_utils.rand_password()
kwargs['password'] = user_password
user = self.users_client.create_user(**kwargs)['user']
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index a79c18c..756c78c 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -145,24 +145,24 @@
a_formats = ['ami', 'ari', 'aki']
(cls.container_format,
- cls.container_format_alt) = CONF.image.container_formats[:2]
+ container_format_alt) = CONF.image.container_formats[:2]
cls.disk_format, cls.disk_format_alt = CONF.image.disk_formats[:2]
if cls.container_format in a_formats:
cls.disk_format = cls.container_format
- if cls.container_format_alt in a_formats:
- cls.disk_format_alt = cls.container_format_alt
+ if container_format_alt in a_formats:
+ cls.disk_format_alt = container_format_alt
img1 = cls._create_remote_image('one', cls.container_format,
cls.disk_format)
- img2 = cls._create_remote_image('two', cls.container_format_alt,
+ img2 = cls._create_remote_image('two', container_format_alt,
cls.disk_format_alt)
img3 = cls._create_remote_image('dup', cls.container_format,
cls.disk_format)
img4 = cls._create_remote_image('dup', cls.container_format,
cls.disk_format)
- img5 = cls._create_standard_image('1', cls.container_format_alt,
+ img5 = cls._create_standard_image('1', container_format_alt,
cls.disk_format_alt, 42)
- img6 = cls._create_standard_image('2', cls.container_format_alt,
+ img6 = cls._create_standard_image('2', container_format_alt,
cls.disk_format_alt, 142)
img7 = cls._create_standard_image('33', cls.container_format,
cls.disk_format, 142)
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index 868771f..485c8f5 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -32,7 +32,7 @@
# Create a network and make sure it will be hosted by a
# dhcp agent: this is done by creating a regular port
cls.network = cls.create_network()
- cls.subnet = cls.create_subnet(cls.network)
+ cls.create_subnet(cls.network)
cls.port = cls.create_port(cls.network)
@decorators.idempotent_id('5032b1fe-eb42-4a64-8f3b-6e189d8b5c7d')
diff --git a/tempest/api/network/admin/test_external_networks_negative.py b/tempest/api/network/admin/test_external_networks_negative.py
index 743089a..770d91f 100644
--- a/tempest/api/network/admin/test_external_networks_negative.py
+++ b/tempest/api/network/admin/test_external_networks_negative.py
@@ -12,6 +12,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
from tempest.api.network import base
from tempest import config
@@ -27,6 +28,8 @@
@test.attr(type=['negative'])
@decorators.idempotent_id('d402ae6c-0be0-4d8e-833b-a738895d98d0')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
def test_create_port_with_precreated_floatingip_as_fixed_ip(self):
# NOTE: External networks can be used to create both floating-ip as
# well as instance-ip. So, creating an instance-ip with a value of a
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 c36323a..9a17817 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -31,6 +31,9 @@
if not test.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
+ if not CONF.network.public_network_id:
+ msg = "The public_network_id option must be specified."
+ raise cls.skipException(msg)
@classmethod
def setup_clients(cls):
@@ -43,9 +46,9 @@
cls.ext_net_id = CONF.network.public_network_id
cls.floating_ip = cls.create_floatingip(cls.ext_net_id)
cls.network = cls.create_network()
- cls.subnet = cls.create_subnet(cls.network)
- cls.router = cls.create_router(external_network_id=cls.ext_net_id)
- cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+ subnet = cls.create_subnet(cls.network)
+ router = cls.create_router(external_network_id=cls.ext_net_id)
+ cls.create_router_interface(router['id'], subnet['id'])
cls.port = cls.create_port(cls.network)
@decorators.idempotent_id('64f2100b-5471-4ded-b46c-ddeeeb4f231b')
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index 5a54ae0..e1970b9 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -79,7 +79,7 @@
cls.router['id'])['router'].get('distributed', False)
if cls.is_dvr_router:
cls.network = cls.create_network()
- cls.subnet = cls.create_subnet(cls.network)
+ cls.create_subnet(cls.network)
cls.port = cls.create_port(cls.network)
cls.routers_client.add_router_interface(
cls.router['id'], port_id=cls.port['id'])
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index fa4010d..136f9e6 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import netaddr
import random
+import netaddr
+
from tempest.api.network import base
from tempest.common.utils import data_utils
from tempest.common.utils import net_info
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index 52507f9..1156275 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -43,16 +43,16 @@
def resource_setup(cls):
super(ExtraDHCPOptionsTestJSON, cls).resource_setup()
cls.network = cls.create_network()
- cls.subnet = cls.create_subnet(cls.network)
+ cls.create_subnet(cls.network)
cls.port = cls.create_port(cls.network)
- cls.ip_tftp = ('123.123.123.123' if cls._ip_version == 4
- else '2015::dead')
- cls.ip_server = ('123.123.123.45' if cls._ip_version == 4
- else '2015::badd')
+ ip_tftp = ('123.123.123.123' if cls._ip_version == 4
+ else '2015::dead')
+ ip_server = ('123.123.123.45' if cls._ip_version == 4
+ else '2015::badd')
cls.extra_dhcp_opts = [
{'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
- {'opt_value': cls.ip_tftp, 'opt_name': 'tftp-server'},
- {'opt_value': cls.ip_server, 'opt_name': 'server-ip-address'}
+ {'opt_value': ip_tftp, 'opt_name': 'tftp-server'},
+ {'opt_value': ip_server, 'opt_name': 'server-ip-address'}
]
@decorators.idempotent_id('d2c17063-3767-4a24-be4f-a23dbfa133c9')
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 23614d6..1dc574b 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -46,6 +46,9 @@
if not test.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
+ if not CONF.network.public_network_id:
+ msg = "The public_network_id option must be specified."
+ raise cls.skipException(msg)
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index 9ccda05..cb29d3d 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -37,6 +37,9 @@
if not test.is_extension_enabled('router', 'network'):
msg = "router extension not enabled."
raise cls.skipException(msg)
+ if not CONF.network.public_network_id:
+ msg = "The public_network_id option must be specified."
+ raise cls.skipException(msg)
@classmethod
def resource_setup(cls):
@@ -44,9 +47,9 @@
cls.ext_net_id = CONF.network.public_network_id
# Create a network with a subnet connected to a router.
cls.network = cls.create_network()
- cls.subnet = cls.create_subnet(cls.network)
- cls.router = cls.create_router()
- cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+ subnet = cls.create_subnet(cls.network)
+ router = cls.create_router()
+ cls.create_router_interface(router['id'], subnet['id'])
cls.port = cls.create_port(cls.network)
@test.attr(type=['negative'])
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 1426798..69d4ebe 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -34,7 +34,6 @@
def resource_setup(cls):
super(BaseNetworkTestResources, cls).resource_setup()
cls.network = cls.create_network()
- cls.name = cls.network['name']
cls.subnet = cls._create_subnet_with_last_subnet_block(cls.network,
cls._ip_version)
cls._subnet_data = {6: {'gateway':
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 524ab9e..694b86b 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -14,6 +14,7 @@
# under the License.
import netaddr
+import testtools
from tempest.api.network import base_routers as base
from tempest.common.utils import data_utils
@@ -42,6 +43,8 @@
@test.attr(type='smoke')
@decorators.idempotent_id('f64403e2-8483-4b34-8ccd-b09a87bcc68c')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
def test_create_show_list_update_delete_router(self):
# Create a router
router = self._create_router(
@@ -89,6 +92,8 @@
@decorators.idempotent_id('847257cc-6afd-4154-b8fb-af49f5670ce8')
@test.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):
# Create a router with default snat rule
router = self._create_router(
@@ -99,6 +104,8 @@
@decorators.idempotent_id('ea74068d-09e9-4fd7-8995-9b6a1ace920f')
@test.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):
name = data_utils.rand_name('snat-router')
# Create a router enabling snat attributes
@@ -184,6 +191,8 @@
self.assertIn(subnet_id, public_subnet_ids)
@decorators.idempotent_id('6cc285d8-46bf-4f36-9b1a-783e3008ba79')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
def test_update_router_set_gateway(self):
router = self._create_router()
self.routers_client.update_router(
@@ -198,6 +207,8 @@
@decorators.idempotent_id('b386c111-3b21-466d-880c-5e72b01e1a33')
@test.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):
router = self._create_router()
self.admin_routers_client.update_router(
@@ -213,6 +224,8 @@
@decorators.idempotent_id('96536bc7-8262-4fb2-9967-5c46940fa279')
@test.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):
router = self._create_router()
self.admin_routers_client.update_router(
@@ -227,6 +240,8 @@
self._verify_gateway_port(router['id'])
@decorators.idempotent_id('ad81b7ee-4f81-407b-a19c-17e623f763e8')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
def test_update_router_unset_gateway(self):
router = self._create_router(
external_network_id=CONF.network.public_network_id)
@@ -241,6 +256,8 @@
@decorators.idempotent_id('f2faf994-97f4-410b-a831-9bc977b64374')
@test.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):
router = self._create_router(
external_network_id=CONF.network.public_network_id)
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index d779d42..cf7dbe8 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -253,6 +253,18 @@
self.assertEqual(True, container.decode(
'utf-8').startswith(prefix))
+ @decorators.idempotent_id('b1811cff-d1ed-4c15-a52e-efd8de41cf34')
+ def test_list_containers_reverse_order(self):
+ # list containers in reverse order
+ _, orig_container_list = self.account_client.list_account_containers()
+
+ params = {'reverse': True}
+ resp, container_list = self.account_client.list_account_containers(
+ params=params)
+ self.assertHeaders(resp, 'Account', 'GET')
+ self.assertEqual(sorted(orig_container_list, reverse=True),
+ container_list)
+
@test.attr(type='smoke')
@decorators.idempotent_id('4894c312-6056-4587-8d6f-86ffbf861f80')
def test_list_account_metadata(self):
@@ -291,7 +303,7 @@
self.account_client.delete_account_metadata(metadata)
@decorators.idempotent_id('9f60348d-c46f-4465-ae06-d51dbd470953')
- def test_update_account_metadata_with_delete_matadata(self):
+ def test_update_account_metadata_with_delete_metadata(self):
# delete metadata from account
metadata = {'test-account-meta1': 'Meta1'}
self.account_client.create_account_metadata(metadata)
@@ -302,7 +314,7 @@
self.assertNotIn('x-account-meta-test-account-meta1', resp)
@decorators.idempotent_id('64fd53f3-adbd-4639-af54-436e4982dbfb')
- def test_update_account_metadata_with_create_matadata_key(self):
+ def test_update_account_metadata_with_create_metadata_key(self):
# if the value of metadata is not set, the metadata is not
# registered at a server
metadata = {'test-account-meta1': ''}
@@ -313,7 +325,7 @@
self.assertNotIn('x-account-meta-test-account-meta1', resp)
@decorators.idempotent_id('d4d884d3-4696-4b85-bc98-4f57c4dd2bf1')
- def test_update_account_metadata_with_delete_matadata_key(self):
+ def test_update_account_metadata_with_delete_metadata_key(self):
# Although the value of metadata is not set, the feature of
# deleting metadata is valid
metadata_1 = {'test-account-meta1': 'Meta1'}
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 72d71c7..1b97e4a 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -34,19 +34,18 @@
super(VolumeMultiBackendV2Test, cls).resource_setup()
# read backend name from a list .
- cls.backend_names = set(CONF.volume.backend_names)
+ backend_names = set(CONF.volume.backend_names)
cls.name_field = cls.special_fields['name_field']
- cls.volume_type_id_list = []
cls.volume_id_list_with_prefix = []
cls.volume_id_list_without_prefix = []
# Volume/Type creation (uses volume_backend_name)
# It is not allowed to create the same backend name twice
- if len(cls.backend_names) < 2:
+ if len(backend_names) < 2:
raise cls.skipException("Requires at least two different "
"backend names")
- for backend_name in cls.backend_names:
+ for backend_name in backend_names:
# Volume/Type creation (uses backend_name)
cls._create_type_and_volume(backend_name, False)
# Volume/Type creation (uses capabilities:volume_backend_name)
@@ -63,8 +62,8 @@
extra_specs = {spec_key_with_prefix: backend_name_key}
else:
extra_specs = {spec_key_without_prefix: backend_name_key}
- cls.type = cls.create_volume_type(name=type_name,
- extra_specs=extra_specs)
+ cls.create_volume_type(name=type_name,
+ extra_specs=extra_specs)
params = {cls.name_field: vol_name, 'volume_type': type_name,
'size': CONF.volume.volume_size}
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 dc509de..4d32fdd 100644
--- a/tempest/api/volume/admin/test_volume_retype_with_migration.py
+++ b/tempest/api/volume/admin/test_volume_retype_with_migration.py
@@ -40,16 +40,16 @@
def resource_setup(cls):
super(VolumeRetypeWithMigrationV2Test, cls).resource_setup()
# read backend name from a list.
- cls.backend_src = CONF.volume.backend_names[0]
- cls.backend_dst = CONF.volume.backend_names[1]
+ backend_src = CONF.volume.backend_names[0]
+ backend_dst = CONF.volume.backend_names[1]
- extra_specs_src = {"volume_backend_name": cls.backend_src}
- extra_specs_dst = {"volume_backend_name": cls.backend_dst}
+ extra_specs_src = {"volume_backend_name": backend_src}
+ extra_specs_dst = {"volume_backend_name": backend_dst}
- cls.src_vol_type = cls.create_volume_type(extra_specs=extra_specs_src)
+ src_vol_type = cls.create_volume_type(extra_specs=extra_specs_src)
cls.dst_vol_type = cls.create_volume_type(extra_specs=extra_specs_dst)
- cls.src_vol = cls.create_volume(volume_type=cls.src_vol_type['name'])
+ cls.src_vol = cls.create_volume(volume_type=src_vol_type['name'])
@classmethod
def resource_cleanup(cls):
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 7938604..213723c 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -36,7 +36,7 @@
# Create/update/get/delete volume with volume_type and extra spec.
volume_types = list()
vol_name = data_utils.rand_name(self.__class__.__name__ + '-volume')
- self.name_field = self.special_fields['name_field']
+ name_field = self.special_fields['name_field']
proto = CONF.volume.storage_protocol
vendor = CONF.volume.vendor_name
extra_specs = {"storage_protocol": proto,
@@ -46,14 +46,14 @@
vol_type = self.create_volume_type(
extra_specs=extra_specs)
volume_types.append(vol_type)
- params = {self.name_field: vol_name,
+ params = {name_field: vol_name,
'volume_type': volume_types[0]['id'],
'size': CONF.volume.volume_size}
# Create volume
volume = self.create_volume(**params)
self.assertEqual(volume_types[0]['name'], volume["volume_type"])
- self.assertEqual(volume[self.name_field], vol_name,
+ self.assertEqual(volume[name_field], vol_name,
"The created volume name is not equal "
"to the requested name")
self.assertIsNotNone(volume['id'],
@@ -74,7 +74,7 @@
fetched_volume['volume_type'],
'The fetched Volume type is different '
'from updated volume type')
- self.assertEqual(vol_name, fetched_volume[self.name_field],
+ self.assertEqual(vol_name, fetched_volume[name_field],
'The fetched Volume is different '
'from the created Volume')
self.assertEqual(volume['id'], fetched_volume['id'],
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index 933b6ad..1dce7e0 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
@@ -24,8 +24,8 @@
@classmethod
def resource_setup(cls):
super(ExtraSpecsNegativeV2Test, cls).resource_setup()
- cls.extra_specs = {"spec1": "val1"}
- cls.volume_type = cls.create_volume_type(extra_specs=cls.extra_specs)
+ extra_specs = {"spec1": "val1"}
+ cls.volume_type = cls.create_volume_type(extra_specs=extra_specs)
@decorators.idempotent_id('08961d20-5cbb-4910-ac0f-89ad6dbb2da1')
def test_update_no_body(self):
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index b278127..e8694b2 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -24,8 +24,8 @@
@decorators.idempotent_id('b48c98f2-e662-4885-9b71-032256906314')
def test_create_with_nonexistent_volume_type(self):
# Should not be able to create volume with nonexistent volume_type.
- self.name_field = self.special_fields['name_field']
- params = {self.name_field: data_utils.rand_uuid(),
+ name_field = self.special_fields['name_field']
+ params = {name_field: data_utils.rand_uuid(),
'volume_type': data_utils.rand_uuid()}
self.assertRaises(lib_exc.NotFound,
self.volumes_client.create_volume, **params)
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index 8d94cd2..5477770 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -30,7 +30,6 @@
cls.client = cls.volumes_client
cls.alt_client = cls.os_alt.volumes_client
- cls.alt_tenant_id = cls.alt_client.tenant_id
cls.adm_client = cls.os_adm.volumes_client
@decorators.idempotent_id('4d75b645-a478-48b1-97c8-503f64242f1a')
diff --git a/tempest/api/volume/test_volumes_clone.py b/tempest/api/volume/test_volumes_clone.py
index 79a1a0a..d653808 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -43,7 +43,7 @@
volume = self.volumes_client.show_volume(dst_vol['id'])['volume']
# Should allow
self.assertEqual(volume['source_volid'], src_vol['id'])
- self.assertEqual(int(volume['size']), src_size + 1)
+ self.assertEqual(volume['size'], src_size + 1)
@decorators.idempotent_id('cbbcd7c6-5a6c-481a-97ac-ca55ab715d16')
def test_create_from_bootable_volume(self):
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 20118df..2378790 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -23,14 +23,14 @@
@decorators.idempotent_id('9a36df71-a257-43a5-9555-dc7c88e66e0e')
def test_volume_extend(self):
# Extend Volume Test.
- self.volume = self.create_volume()
- extend_size = int(self.volume['size']) + 1
- self.volumes_client.extend_volume(self.volume['id'],
+ volume = self.create_volume()
+ extend_size = volume['size'] + 1
+ self.volumes_client.extend_volume(volume['id'],
new_size=extend_size)
waiters.wait_for_volume_status(self.volumes_client,
- self.volume['id'], 'available')
- volume = self.volumes_client.show_volume(self.volume['id'])['volume']
- self.assertEqual(int(volume['size']), extend_size)
+ volume['id'], 'available')
+ volume = self.volumes_client.show_volume(volume['id'])['volume']
+ self.assertEqual(volume['size'], extend_size)
class VolumesV1ExtendTest(VolumesV2ExtendTest):
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 0a095a9..28e65ed 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -221,7 +221,7 @@
@decorators.idempotent_id('8f05a943-013c-4063-ac71-7baf561e82eb')
def test_volume_extend_with_nonexistent_volume_id(self):
# Extend volume size when volume is nonexistent.
- extend_size = int(self.volume['size']) + 1
+ extend_size = self.volume['size'] + 1
self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
data_utils.rand_uuid(), new_size=extend_size)
@@ -229,7 +229,7 @@
@decorators.idempotent_id('aff8ba64-6d6f-4f2e-bc33-41a08ee9f115')
def test_volume_extend_without_passing_volume_id(self):
# Extend volume size when passing volume id is None.
- extend_size = int(self.volume['size']) + 1
+ extend_size = self.volume['size'] + 1
self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
None, new_size=extend_size)
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index f1ca722..9f4ce95 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -153,7 +153,7 @@
volume = self.volumes_client.show_volume(dst_vol['id'])['volume']
# Should allow
self.assertEqual(volume['snapshot_id'], src_snap['id'])
- self.assertEqual(int(volume['size']), src_size + 1)
+ self.assertEqual(volume['size'], src_size + 1)
class VolumesV1SnapshotTestJSON(VolumesV2SnapshotTestJSON):
diff --git a/tempest/api/volume/test_volumes_snapshots_list.py b/tempest/api/volume/test_volumes_snapshots_list.py
index ff390ea..a0eaa00 100644
--- a/tempest/api/volume/test_volumes_snapshots_list.py
+++ b/tempest/api/volume/test_volumes_snapshots_list.py
@@ -28,11 +28,11 @@
@classmethod
def resource_setup(cls):
super(VolumesV2SnapshotListTestJSON, cls).resource_setup()
- cls.volume_origin = cls.create_volume()
+ volume_origin = cls.create_volume()
cls.name_field = cls.special_fields['name_field']
# Create snapshots with params
for _ in range(2):
- cls.snapshot = cls.create_snapshot(cls.volume_origin['id'])
+ cls.snapshot = cls.create_snapshot(volume_origin['id'])
def _list_by_param_values_and_assert(self, with_detail=False, **params):
"""list or list_details with given params and validates result."""
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 9b17515..8b51e64 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -15,6 +15,7 @@
# under the License.
import random
+
from six.moves.urllib import parse
from tempest.api.volume import base
@@ -36,13 +37,13 @@
super(VolumesV2ListTestJSON, cls).resource_setup()
# Create 3 test volumes
- cls.metadata = {'Type': 'work'}
+ metadata = {'Type': 'work'}
# NOTE(zhufl): When using pre-provisioned credentials, the project
# may have volumes other than those created below.
existing_volumes = cls.volumes_client.list_volumes()['volumes']
cls.volume_id_list = [vol['id'] for vol in existing_volumes]
for _ in range(3):
- volume = cls.create_volume(metadata=cls.metadata)
+ volume = cls.create_volume(metadata=metadata)
cls.volume_id_list.append(volume['id'])
@decorators.idempotent_id('2a7064eb-b9c3-429b-b888-33928fc5edd3')
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_list.py b/tempest/api/volume/v2/test_volumes_snapshots_list.py
index 3deb437..d385f65 100644
--- a/tempest/api/volume/v2/test_volumes_snapshots_list.py
+++ b/tempest/api/volume/v2/test_volumes_snapshots_list.py
@@ -33,11 +33,10 @@
super(VolumesV2SnapshotListTestJSON, cls).resource_setup()
cls.snapshot_id_list = []
# Create a volume
- cls.volume_origin = cls.create_volume()
- cls.name_field = cls.special_fields['name_field']
+ volume_origin = cls.create_volume()
# Create 3 snapshots
for _ in range(3):
- snapshot = cls.create_snapshot(cls.volume_origin['id'])
+ snapshot = cls.create_snapshot(volume_origin['id'])
cls.snapshot_id_list.append(snapshot['id'])
def _list_snapshots_param_sort(self, sort_key, sort_dir):
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 632a876..88fe26c 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -293,12 +293,12 @@
return resp_body['subnet']
def _create_router(self, router_name, tenant_id):
- external_net_id = dict(
- network_id=self.public_network_id)
- resp_body = self.routers_admin_client.create_router(
- name=router_name,
- external_gateway_info=external_net_id,
- tenant_id=tenant_id)
+ kwargs = {'name': router_name,
+ 'tenant_id': tenant_id}
+ if self.public_network_id:
+ kwargs['external_gateway_info'] = dict(
+ network_id=self.public_network_id)
+ resp_body = self.routers_admin_client.create_router(**kwargs)
return resp_body['router']
def _add_router_interface(self, router_id, subnet_id):
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index f50edbd..4032c90 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -11,6 +11,7 @@
# under the License.
import copy
+
from oslo_log import log as logging
from tempest import exceptions
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 009812e..1487c1d 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -10,12 +10,13 @@
# License for the specific language governing permissions and limitations
# under the License.
-import netaddr
import re
-import six
import sys
import time
+import netaddr
+import six
+
from oslo_log import log as logging
from tempest import config
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 865db39..15619f4 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -121,7 +121,7 @@
'/'.join((server_status, str(task_state))),
time.time() - start_time)
if server_status == 'ERROR' and not ignore_error:
- raise exceptions.BuildErrorException(server_id=server_id)
+ raise lib_exc.DeleteErrorException(resource_id=server_id)
if int(time.time()) - start_time >= client.build_timeout:
raise lib_exc.TimeoutException
@@ -218,7 +218,7 @@
'within the required time (%s s).' %
(volume_id, new_volume_type, current_volume_type,
client.build_timeout))
- raise exceptions.TimeoutException(message)
+ raise lib_exc.TimeoutException(message)
def wait_for_snapshot_status(client, snapshot_id, status):
diff --git a/tempest/config.py b/tempest/config.py
index 75ec46a..b4d88c5 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -15,14 +15,12 @@
from __future__ import print_function
-import functools
import os
import tempfile
from oslo_concurrency import lockutils
from oslo_config import cfg
from oslo_log import log as logging
-import testtools
from tempest.lib import exceptions
from tempest.lib.services import clients
@@ -310,8 +308,7 @@
"min_microversion and max_microversion. "
"If both values are not specified, Tempest avoids tests "
"which require a microversion. Valid values are string "
- "with format 'X.Y' or string 'latest'",
- deprecated_group='compute-feature-enabled'),
+ "with format 'X.Y' or string 'latest'"),
cfg.StrOpt('max_microversion',
default=None,
help="Upper version of the test target microversion range. "
@@ -320,8 +317,7 @@
"min_microversion and max_microversion. "
"If both values are not specified, Tempest avoids tests "
"which require a microversion. Valid values are string "
- "with format 'X.Y' or string 'latest'",
- deprecated_group='compute-feature-enabled'),
+ "with format 'X.Y' or string 'latest'"),
]
compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
@@ -537,23 +533,18 @@
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the network service."),
cfg.StrOpt('project_network_cidr',
- deprecated_name='tenant_network_cidr',
default="10.100.0.0/16",
help="The cidr block to allocate project ipv4 subnets from"),
cfg.IntOpt('project_network_mask_bits',
- deprecated_name='tenant_network_mask_bits',
default=28,
help="The mask bits for project ipv4 subnets"),
cfg.StrOpt('project_network_v6_cidr',
- deprecated_name='tenant_network_v6_cidr',
default="2003::/48",
help="The cidr block to allocate project ipv6 subnets from"),
cfg.IntOpt('project_network_v6_mask_bits',
- deprecated_name='tenant_network_v6_mask_bits',
default=64,
help="The mask bits for project ipv6 subnets"),
cfg.BoolOpt('project_networks_reachable',
- deprecated_name='tenant_networks_reachable',
default=False,
help="Whether project networks can be reached directly from "
"the test client. This must be set to True when the "
@@ -655,17 +646,13 @@
choices=['fixed', 'floating'],
help='Default IP type used for validation: '
'-fixed: uses the first IP belonging to the fixed network '
- '-floating: creates and uses a floating IP',
- deprecated_opts=[cfg.DeprecatedOpt('use_floatingip_for_ssh',
- group='compute')]),
+ '-floating: creates and uses a floating IP'),
cfg.StrOpt('auth_method',
default='keypair',
choices=['keypair'],
help='Default authentication method to the instance. '
'Only ssh via keypair is supported for now. '
- 'Additional methods will be handled in a separate spec.',
- deprecated_opts=[cfg.DeprecatedOpt('ssh_auth_method',
- group='compute')]),
+ 'Additional methods will be handled in a separate spec.'),
cfg.IntOpt('ip_version_for_ssh',
default=4,
help='Default IP version for ssh connections.'),
@@ -692,35 +679,25 @@
group='scenario')]),
cfg.StrOpt('image_ssh_password',
default="password",
- help="Password used to authenticate to an instance.",
- deprecated_opts=[cfg.DeprecatedOpt('image_ssh_password',
- group='compute')]),
+ help="Password used to authenticate to an instance."),
cfg.StrOpt('ssh_shell_prologue',
default="set -eu -o pipefail; PATH=$$PATH:/sbin;",
help="Shell fragments to use before executing a command "
- "when sshing to a guest.",
- deprecated_opts=[cfg.DeprecatedOpt('ssh_shell_prologue',
- group='compute')]),
+ "when sshing to a guest."),
cfg.IntOpt('ping_size',
default=56,
help="The packet size for ping packets originating "
- "from remote linux hosts",
- deprecated_opts=[cfg.DeprecatedOpt('ping_size',
- group='compute')]),
+ "from remote linux hosts"),
cfg.IntOpt('ping_count',
default=1,
help="The number of ping packets originating from remote "
- "linux hosts",
- deprecated_opts=[cfg.DeprecatedOpt('ping_count',
- group='compute')]),
+ "linux hosts"),
cfg.StrOpt('floating_ip_range',
default='10.0.0.0/29',
help='Unallocated floating IP range, which will be used to '
'test the floating IP bulk feature for CRUD operation. '
'This block must not overlap an existing floating IP '
- 'pool.',
- deprecated_opts=[cfg.DeprecatedOpt('floating_ip_range',
- group='compute')]),
+ 'pool.'),
cfg.StrOpt('network_for_ssh',
default='public',
help="Network used for SSH connections. Ignored if "
@@ -1212,75 +1189,6 @@
CONF = TempestConfigProxy()
-def skip_unless_config(*args):
- """Decorator to raise a skip if a config opt doesn't exist or is False
-
- :param str group: The first arg, the option group to check
- :param str name: The second arg, the option name to check
- :param str msg: Optional third arg, the skip msg to use if a skip is raised
- :raises testtools.TestCaseskipException: If the specified config option
- doesn't exist or it exists and evaluates to False
- """
- def decorator(f):
- group = args[0]
- name = args[1]
-
- @functools.wraps(f)
- def wrapper(self, *func_args, **func_kwargs):
- if not hasattr(CONF, group):
- msg = "Config group %s doesn't exist" % group
- raise testtools.TestCase.skipException(msg)
-
- conf_group = getattr(CONF, group)
- if not hasattr(conf_group, name):
- msg = "Config option %s.%s doesn't exist" % (group,
- name)
- raise testtools.TestCase.skipException(msg)
-
- value = getattr(conf_group, name)
- if not value:
- if len(args) == 3:
- msg = args[2]
- else:
- msg = "Config option %s.%s is false" % (group,
- name)
- raise testtools.TestCase.skipException(msg)
- return f(self, *func_args, **func_kwargs)
- return wrapper
- return decorator
-
-
-def skip_if_config(*args):
- """Raise a skipException if a config exists and is True
-
- :param str group: The first arg, the option group to check
- :param str name: The second arg, the option name to check
- :param str msg: Optional third arg, the skip msg to use if a skip is raised
- :raises testtools.TestCase.skipException: If the specified config option
- exists and evaluates to True
- """
- def decorator(f):
- group = args[0]
- name = args[1]
-
- @functools.wraps(f)
- def wrapper(self, *func_args, **func_kwargs):
- if hasattr(CONF, group):
- conf_group = getattr(CONF, group)
- if hasattr(conf_group, name):
- value = getattr(conf_group, name)
- if value:
- if len(args) == 3:
- msg = args[2]
- else:
- msg = "Config option %s.%s is false" % (group,
- name)
- raise testtools.TestCase.skipException(msg)
- return f(self, *func_args, **func_kwargs)
- return wrapper
- return decorator
-
-
def service_client_config(service_client_name=None):
"""Return a dict with the parameters to init service clients
diff --git a/tempest/lib/common/utils/data_utils.py b/tempest/lib/common/utils/data_utils.py
index 75c2e51..642514b 100644
--- a/tempest/lib/common/utils/data_utils.py
+++ b/tempest/lib/common/utils/data_utils.py
@@ -14,12 +14,12 @@
# under the License.
import itertools
-import netaddr
import random
import string
import uuid
from debtcollector import removals
+import netaddr
from oslo_utils import netutils
from oslo_utils import uuidutils
import six.moves
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index af3acbf..dea3289 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -264,3 +264,8 @@
class VolumeBackupException(TempestException):
message = "Volume backup %(backup_id)s failed and is in ERROR status"
+
+
+class DeleteErrorException(TempestException):
+ message = ("Resource %(resource_id)s failed to delete "
+ "and is in ERROR status")
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index f16ef88..adff244 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -19,6 +19,8 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
+from tempest.lib.api_schema.response.compute.v2_1 import \
+ security_groups as security_groups_schema
from tempest.lib.api_schema.response.compute.v2_1 import servers as schema
from tempest.lib.api_schema.response.compute.v2_16 import servers as schemav216
from tempest.lib.api_schema.response.compute.v2_19 import servers as schemav219
@@ -717,3 +719,16 @@
http://developer.openstack.org/api-ref-compute-v2.1.html#removeFixedIp
"""
return self.action(server_id, 'removeFixedIp', **kwargs)
+
+ def list_security_groups_by_server(self, server_id):
+ """Lists security groups for a server.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref-compute-v2.1.html#listSecurityGroupsByServer
+ """
+ resp, body = self.get("servers/%s/os-security-groups" % server_id)
+ body = json.loads(body)
+ self.validate_response(security_groups_schema.list_security_groups,
+ resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 50fe9c8..95c2d32 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -36,9 +36,8 @@
def setup_clients(cls):
super(TestAggregatesBasicOps, cls).setup_clients()
# Use admin client by default
- cls.manager = cls.admin_manager
- cls.aggregates_client = cls.manager.aggregates_client
- cls.hosts_client = cls.manager.hosts_client
+ cls.aggregates_client = cls.admin_manager.aggregates_client
+ cls.hosts_client = cls.admin_manager.hosts_client
def _create_aggregate(self, **kwargs):
aggregate = (self.aggregates_client.create_aggregate(**kwargs)
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 738ed61..27c45cb 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.common import custom_matchers
from tempest.common import waiters
from tempest import config
@@ -99,6 +101,8 @@
return address
@decorators.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
@test.services('compute', 'volume', 'image', 'network')
def test_minimum_basic_scenario(self):
image = self.glance_image_create()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index f8e7742..1196659 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -39,7 +39,6 @@
def setup_clients(cls):
super(TestNetworkAdvancedServerOps, cls).setup_clients()
cls.admin_servers_client = cls.os_adm.servers_client
- cls.admin_hosts_client = cls.os_adm.hosts_client
@classmethod
def skip_checks(cls):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index e6a5f51..4dae564 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -109,13 +109,13 @@
self.check_networks()
self.ports = []
- self.port_id = None
+ port_id = None
if boot_with_port:
# create a port on the network and boot with that
- self.port_id = self._create_port(self.network['id'])['id']
- self.ports.append({'port': self.port_id})
+ port_id = self._create_port(self.network['id'])['id']
+ self.ports.append({'port': port_id})
- server = self._create_server(self.network, self.port_id)
+ server = self._create_server(self.network, port_id)
self._check_tenant_network_connectivity()
floating_ip = self.create_floating_ip(server)
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index d88a639..75cef88 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.common import compute
from tempest.common import waiters
from tempest import config
@@ -73,11 +75,15 @@
self.assertEqual(timestamp, timestamp2)
@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')
def test_shelve_instance(self):
self._create_server_then_shelve_and_unshelve()
@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')
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 2ce8532..6dedd1d 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest import config
from tempest.lib import decorators
from tempest.scenario import manager
@@ -39,6 +41,8 @@
raise cls.skipException("Snapshotting is not available.")
@decorators.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
@test.services('compute', 'network', 'image')
def test_snapshot_pattern(self):
# prepare for booting an instance
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index f00270d..8661217 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -91,6 +91,8 @@
@decorators.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'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')
def test_stamp_pattern(self):
# prepare for booting an instance
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 5254082..43dcf96 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -11,6 +11,7 @@
# under the License.
from oslo_log import log as logging
+import testtools
from tempest.common.utils import data_utils
from tempest.common import waiters
@@ -98,6 +99,8 @@
@decorators.idempotent_id('557cd2c2-4eb8-4dce-98be-f86765ff311b')
@test.attr(type='smoke')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
@test.services('compute', 'volume', 'image')
def test_volume_boot_pattern(self):
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index 9932b4a..4859e75 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -128,6 +128,13 @@
than the specified marker.
DEFAULT: No Marker
+ prefix=[string value Y]
+ Given string value Y, return object names starting with that prefix
+
+ reverse=[boolean value Z]
+ Reverse the result order based on the boolean value Z
+ DEFAULT: False
+
format=[string value, either 'json' or 'xml']
Specify either json or xml to return the respective serialized
response.
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/common/test_preprov_creds.py
index 1c9982c..2fd375d 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -14,14 +14,15 @@
import hashlib
import os
-import testtools
+import shutil
import mock
+import six
+import testtools
+
from oslo_concurrency.fixture import lockutils as lockutils_fixtures
from oslo_config import cfg
from oslotest import mockpatch
-import shutil
-import six
from tempest.common import preprov_creds
from tempest import config
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index e4f4c04..5be6229 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -12,9 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import fixtures
import time
+import fixtures
from oslo_config import cfg
from oslotest import mockpatch
diff --git a/tempest/tests/lib/cli/test_execute.py b/tempest/tests/lib/cli/test_execute.py
index aaeb6f4..0130454 100644
--- a/tempest/tests/lib/cli/test_execute.py
+++ b/tempest/tests/lib/cli/test_execute.py
@@ -11,9 +11,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
import subprocess
+import mock
+
from tempest.lib.cli import base as cli_base
from tempest.lib import exceptions
from tempest.tests import base
diff --git a/tempest/tests/lib/services/compute/test_servers_client.py b/tempest/tests/lib/services/compute/test_servers_client.py
index adfaaf2..b563ab2 100644
--- a/tempest/tests/lib/services/compute/test_servers_client.py
+++ b/tempest/tests/lib/services/compute/test_servers_client.py
@@ -172,6 +172,14 @@
"traceback": "fake-trace-back"
}
+ FAKE_SECURITY_GROUPS = [{
+ "description": "default",
+ "id": "3fb26eb3-581b-4420-9963-b0879a026506",
+ "name": "default",
+ "rules": [],
+ "tenant_id": "openstack"
+ }]
+
FAKE_INSTANCE_WITH_EVENTS = copy.deepcopy(FAKE_INSTANCE_ACTIONS)
FAKE_INSTANCE_WITH_EVENTS['events'] = [FAKE_INSTANCE_ACTION_EVENTS]
@@ -1009,3 +1017,17 @@
server_id=self.server_id,
type='fake-console-type'
)
+
+ def test_list_security_groups_by_server_with_str_body(self):
+ self._test_list_security_groups_by_server()
+
+ def test_list_security_groups_by_server_with_bytes_body(self):
+ self._test_list_security_groups_by_server(True)
+
+ def _test_list_security_groups_by_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_security_groups_by_server,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ {'security_groups': self.FAKE_SECURITY_GROUPS},
+ server_id=self.server_id,
+ )
diff --git a/tempest/tests/lib/services/compute/test_versions_client.py b/tempest/tests/lib/services/compute/test_versions_client.py
index 06ecdc3..255a0a3 100644
--- a/tempest/tests/lib/services/compute/test_versions_client.py
+++ b/tempest/tests/lib/services/compute/test_versions_client.py
@@ -13,6 +13,7 @@
# under the License.
import copy
+
from oslotest import mockpatch
from tempest.lib.services.compute import versions_client
diff --git a/tempest/tests/lib/services/test_clients.py b/tempest/tests/lib/services/test_clients.py
index 5db932c..a3b390e 100644
--- a/tempest/tests/lib/services/test_clients.py
+++ b/tempest/tests/lib/services/test_clients.py
@@ -12,10 +12,11 @@
# License for the specific language governing permissions and limitations under
# the License.
+import types
+
import fixtures
import mock
import testtools
-import types
from tempest.lib import auth
from tempest.lib import exceptions
diff --git a/tempest/tests/lib/test_auth.py b/tempest/tests/lib/test_auth.py
index 2f975d2..ac13a13 100644
--- a/tempest/tests/lib/test_auth.py
+++ b/tempest/tests/lib/test_auth.py
@@ -15,9 +15,9 @@
import copy
import datetime
-import testtools
from oslotest import mockpatch
+import testtools
from tempest.lib import auth
from tempest.lib import exceptions
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index ae2f2a3..a069a81 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -199,96 +199,3 @@
self._test_requires_ext_helper,
extension='enabled_ext',
service='bad_service')
-
-
-class TestConfigDecorators(BaseDecoratorsTest):
- def setUp(self):
- super(TestConfigDecorators, self).setUp()
- cfg.CONF.set_default('nova', True, 'service_available')
- cfg.CONF.set_default('glance', False, 'service_available')
-
- def _assert_skip_message(self, func, skip_msg):
- try:
- func()
- self.fail()
- except testtools.TestCase.skipException as skip_exc:
- self.assertEqual(skip_exc.args[0], skip_msg)
-
- def _test_skip_unless_config(self, expected_to_skip=True, *decorator_args):
-
- class TestFoo(test.BaseTestCase):
- @config.skip_unless_config(*decorator_args)
- def test_bar(self):
- return 0
-
- t = TestFoo('test_bar')
- if expected_to_skip:
- self.assertRaises(testtools.TestCase.skipException, t.test_bar)
- if (len(decorator_args) >= 3):
- # decorator_args[2]: skip message specified
- self._assert_skip_message(t.test_bar, decorator_args[2])
- else:
- try:
- self.assertEqual(t.test_bar(), 0)
- except testtools.TestCase.skipException:
- # We caught a skipException but we didn't expect to skip
- # this test so raise a hard test failure instead.
- raise testtools.TestCase.failureException(
- "Not supposed to skip")
-
- def _test_skip_if_config(self, expected_to_skip=True,
- *decorator_args):
-
- class TestFoo(test.BaseTestCase):
- @config.skip_if_config(*decorator_args)
- def test_bar(self):
- return 0
-
- t = TestFoo('test_bar')
- if expected_to_skip:
- self.assertRaises(testtools.TestCase.skipException, t.test_bar)
- if (len(decorator_args) >= 3):
- # decorator_args[2]: skip message specified
- self._assert_skip_message(t.test_bar, decorator_args[2])
- else:
- try:
- self.assertEqual(t.test_bar(), 0)
- except testtools.TestCase.skipException:
- # We caught a skipException but we didn't expect to skip
- # this test so raise a hard test failure instead.
- raise testtools.TestCase.failureException(
- "Not supposed to skip")
-
- def test_skip_unless_no_group(self):
- self._test_skip_unless_config(True, 'fake_group', 'an_option')
-
- def test_skip_unless_no_option(self):
- self._test_skip_unless_config(True, 'service_available',
- 'not_an_option')
-
- def test_skip_unless_false_option(self):
- self._test_skip_unless_config(True, 'service_available', 'glance')
-
- def test_skip_unless_false_option_msg(self):
- self._test_skip_unless_config(True, 'service_available', 'glance',
- 'skip message')
-
- def test_skip_unless_true_option(self):
- self._test_skip_unless_config(False,
- 'service_available', 'nova')
-
- def test_skip_if_no_group(self):
- self._test_skip_if_config(False, 'fake_group', 'an_option')
-
- def test_skip_if_no_option(self):
- self._test_skip_if_config(False, 'service_available', 'not_an_option')
-
- def test_skip_if_false_option(self):
- self._test_skip_if_config(False, 'service_available', 'glance')
-
- def test_skip_if_true_option(self):
- self._test_skip_if_config(True, 'service_available', 'nova')
-
- def test_skip_if_true_option_msg(self):
- self._test_skip_if_config(True, 'service_available', 'nova',
- 'skip message')
diff --git a/tempest/tests/test_list_tests.py b/tempest/tests/test_list_tests.py
index 38d4c5c..a238879 100644
--- a/tempest/tests/test_list_tests.py
+++ b/tempest/tests/test_list_tests.py
@@ -14,9 +14,10 @@
import os
import re
-import six
import subprocess
+import six
+
from tempest.tests import base
diff --git a/test-requirements.txt b/test-requirements.txt
index 475fb16..f7d63a8 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -9,3 +9,4 @@
mock>=2.0 # BSD
coverage>=4.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
+flake8-import-order==0.11 # LGPLv3
diff --git a/tools/check_logs.py b/tools/check_logs.py
index caad85c..f82b387 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -19,10 +19,10 @@
import gzip
import os
import re
-import six
-import six.moves.urllib.request as urlreq
import sys
+import six
+import six.moves.urllib.request as urlreq
import yaml
diff --git a/tools/find_stack_traces.py b/tools/find_stack_traces.py
index f2da27a..2ba8b16 100755
--- a/tools/find_stack_traces.py
+++ b/tools/find_stack_traces.py
@@ -18,9 +18,10 @@
import gzip
import pprint
import re
+import sys
+
import six
import six.moves.urllib.request as urlreq
-import sys
pp = pprint.PrettyPrinter()
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index 03e838e..acb29af 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -25,6 +25,7 @@
import json
import re
+
import requests
url = 'https://review.openstack.org/projects/'
diff --git a/tox.ini b/tox.ini
index 46823d8..d8d390e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -147,6 +147,7 @@
show-source = True
exclude = .git,.venv,.tox,dist,doc,*egg
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