Merge "Add glance test for uploading the image" into mcp/caracal
diff --git a/tempest/api/network/test_tags.py b/tempest/api/network/test_tags.py
index bd3e360..af0a8b0 100644
--- a/tempest/api/network/test_tags.py
+++ b/tempest/api/network/test_tags.py
@@ -113,7 +113,10 @@
 
     # NOTE(felipemonteiro): The supported resource names are plural. Use
     # the singular case for the corresponding class resource object.
-    SUPPORTED_RESOURCES = ['subnets', 'ports', 'routers', 'subnetpools']
+    if config.is_tungstenfabric_backend_enabled():
+        SUPPORTED_RESOURCES = ['subnets', 'ports', 'routers']
+    else:
+        SUPPORTED_RESOURCES = ['subnets', 'ports', 'routers', 'subnetpools']
 
     @classmethod
     def skip_checks(cls):
@@ -134,6 +137,9 @@
         cls.port = cls.create_port(cls.network)
         cls.router = cls.create_router()
 
+        if config.is_tungstenfabric_backend_enabled():
+            return
+
         subnetpool_name = data_utils.rand_name(
             cls.__name__ + '-Subnetpool', prefix=CONF.resource_name_prefix)
         prefix = CONF.network.default_network
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 028bf1a..b45824e 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -30,8 +30,9 @@
             raise cls.skipException("Cinder multi-backend feature disabled")
 
         if len(set(CONF.volume.backend_names)) < 2:
-            raise cls.skipException("Requires at least two different "
-                                    "backend names")
+            raise cls.skipException(
+                "Requires at least two different "
+                "backend names")
 
     @classmethod
     def resource_setup(cls):
@@ -66,21 +67,34 @@
             extra_specs = {spec_key_with_prefix: backend_name_key}
         else:
             extra_specs = {spec_key_without_prefix: backend_name_key}
-        cls.create_volume_type(name=type_name,
-                               extra_specs=extra_specs)
+        cls.create_volume_type(
+            name=type_name, extra_specs=extra_specs)
+        # Pick up AZ from volume_type
+        services = cls.admin_volume_services_client.list_services()
+        vol_svrs = [
+            srv
+            for srv in services.get("services")
+            if srv["binary"] == "cinder-volume" and backend_name_key
+                                in srv["host"]
+        ]
+        vol_type_zone = vol_svrs[0]["zone"]
 
-        params = {'name': vol_name, 'volume_type': type_name,
-                  'size': CONF.volume.volume_size}
+        params = {
+            "name": vol_name,
+            "volume_type": type_name,
+            "size": CONF.volume.volume_size,
+            "availability_zone": vol_type_zone,
+        }
         cls.volume = cls.create_volume(**params)
         if with_prefix:
-            cls.volume_id_list_with_prefix.append(cls.volume['id'])
+            cls.volume_id_list_with_prefix.append(cls.volume["id"])
         else:
-            cls.volume_id_list_without_prefix.append(
-                cls.volume['id'])
-        waiters.wait_for_volume_resource_status(cls.admin_volume_client,
-                                                cls.volume['id'], 'available')
+            cls.volume_id_list_without_prefix.append(cls.volume["id"])
+        waiters.wait_for_volume_resource_status(
+            cls.admin_volume_client, cls.volume["id"], "available"
+        )
 
-    @decorators.idempotent_id('c1a41f3f-9dad-493e-9f09-3ff197d477cc')
+    @decorators.idempotent_id("c1a41f3f-9dad-493e-9f09-3ff197d477cc")
     def test_backend_name_reporting(self):
         """Test backend name reporting for volume when type is without prefix
 
@@ -92,7 +106,7 @@
         for volume_id in self.volume_id_list_without_prefix:
             self._test_backend_name_reporting_by_volume_id(volume_id)
 
-    @decorators.idempotent_id('f38e647f-ab42-4a31-a2e7-ca86a6485215')
+    @decorators.idempotent_id("f38e647f-ab42-4a31-a2e7-ca86a6485215")
     def test_backend_name_reporting_with_prefix(self):
         """Test backend name reporting for volume when type is with prefix
 
@@ -105,7 +119,7 @@
         for volume_id in self.volume_id_list_with_prefix:
             self._test_backend_name_reporting_by_volume_id(volume_id)
 
-    @decorators.idempotent_id('46435ab1-a0af-4401-8373-f14e66b0dd58')
+    @decorators.idempotent_id("46435ab1-a0af-4401-8373-f14e66b0dd58")
     def test_backend_name_distinction(self):
         """Test volume backend distinction when type is without prefix
 
@@ -116,7 +130,7 @@
         """
         self._test_backend_name_distinction(self.volume_id_list_without_prefix)
 
-    @decorators.idempotent_id('4236305b-b65a-4bfc-a9d2-69cb5b2bf2ed')
+    @decorators.idempotent_id("4236305b-b65a-4bfc-a9d2-69cb5b2bf2ed")
     def test_backend_name_distinction_with_prefix(self):
         """Test volume backend distinction when type is with prefix
 
@@ -128,28 +142,29 @@
         self._test_backend_name_distinction(self.volume_id_list_with_prefix)
 
     def _get_volume_host(self, volume_id):
-        return self.admin_volume_client.show_volume(
-            volume_id)['volume']['os-vol-host-attr:host']
+        return self.admin_volume_client.show_volume(volume_id)["volume"][
+            "os-vol-host-attr:host"
+        ]
 
     def _test_backend_name_reporting_by_volume_id(self, volume_id):
         # this test checks if os-vol-attr:host is populated correctly after
         # the multi backend feature has been enabled
         # if multi-backend is enabled: os-vol-attr:host should be like:
         # host@backend_name
-        volume = self.admin_volume_client.show_volume(volume_id)['volume']
+        volume = self.admin_volume_client.show_volume(volume_id)["volume"]
 
-        volume1_host = volume['os-vol-host-attr:host']
-        msg = ("multi-backend reporting incorrect values for volume %s" %
-               volume_id)
+        volume1_host = volume["os-vol-host-attr:host"]
+        msg = ("multi-backend reporting incorrect values for volume %s"
+               % volume_id)
         self.assertGreater(len(volume1_host.split("@")), 1, msg)
 
     def _test_backend_name_distinction(self, volume_id_list):
         # this test checks that the volumes created at setUp don't
         # belong to the same backend (if they are, than the
         # volume backend distinction is not working properly)
-        volume_hosts = [self._get_volume_host(volume) for volume in
-                        volume_id_list]
+        volume_hosts = [self._get_volume_host(volume)
+                        for volume in volume_id_list]
         # assert that volumes are each created on separate hosts:
-        msg = ("volumes %s were created in the same backend" % ", "
-               .join(volume_hosts))
+        msg = "volumes %s were created in the same backend" % ", ".join(
+            volume_hosts)
         self.assertCountEqual(volume_hosts, set(volume_hosts), msg)
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 8d699ab..2e07c80 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -87,7 +87,8 @@
         ('create_networks', (CONF.auth.create_isolated_networks and not
                              CONF.network.shared_physical_network)),
         ('resource_prefix', 'tempest'),
-        ('identity_admin_endpoint_type', endpoint_type)
+        ('identity_admin_endpoint_type', endpoint_type),
+        ('networking_timeout_409', CONF.network.timeout_409)
     ]))
 
 
diff --git a/tempest/config.py b/tempest/config.py
index 999e905..ecdc6e9 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -845,6 +845,10 @@
     cfg.IntOpt('service_ports_number',
                default=0,
                help="Number of neutron service ports created per network"),
+    cfg.IntOpt('timeout_409',
+               default=120,
+               help="Total time in seconds to keep retrying a request that "
+                    "returns HTTP 409 (Conflict)."),
 ]
 
 network_feature_group = cfg.OptGroup(name='network-feature-enabled',
@@ -1695,6 +1699,17 @@
     return _parameters
 
 
+def is_tungstenfabric_backend_enabled():
+    """Return True if TungstenFabric is used as a backend."""
+    try:
+        sdn = getattr(CONF, 'sdn')
+        service_name = getattr(sdn, 'service_name')
+        if service_name == 'tungstenfabric':
+            return True
+    except cfg.NoSuchOptError:
+        return False
+
+
 def _register_tempest_service_clients():
     # Register tempest own service clients using the same mechanism used
     # for external plugins.
diff --git a/tempest/lib/common/cred_provider.py b/tempest/lib/common/cred_provider.py
index 2da206f..84f5264 100644
--- a/tempest/lib/common/cred_provider.py
+++ b/tempest/lib/common/cred_provider.py
@@ -13,6 +13,8 @@
 #    limitations under the License.
 
 import abc
+import time
+
 from oslo_log import log as logging
 
 from tempest.lib import auth
@@ -133,11 +135,24 @@
             name="default")
         secgroups_to_delete = resp_body['security_groups']
         for secgroup in secgroups_to_delete:
-            try:
-                security_group_client.delete_security_group(secgroup['id'])
-            except exceptions.NotFound:
-                LOG.warning('Security group %s, id %s not found for clean-up',
-                            secgroup['name'], secgroup['id'])
+            # Workaround for PRODX-4003
+            start_time = time.time()
+            while True:
+                try:
+                    security_group_client.delete_security_group(secgroup['id'])
+                    break
+                except exceptions.NotFound:
+                    LOG.warning('Security group %s, id %s not found for '
+                                'clean-up', secgroup['name'], secgroup['id'])
+                    break
+                except exceptions.Conflict:
+                    LOG.warning('Conflict with state of security group %s, '
+                                'id %s.', secgroup['name'], secgroup['id'])
+                    if (time.time() - self.networking_timeout_409) > \
+                            start_time:
+                        raise
+                    else:
+                        time.sleep(5)
 
 
 class TestResources(object):
diff --git a/tempest/lib/common/dynamic_creds.py b/tempest/lib/common/dynamic_creds.py
index 9994ee6..9eb3c22 100644
--- a/tempest/lib/common/dynamic_creds.py
+++ b/tempest/lib/common/dynamic_creds.py
@@ -76,7 +76,8 @@
                  neutron_available=False, create_networks=True,
                  project_network_cidr=None, project_network_mask_bits=None,
                  public_network_id=None, resource_prefix=None,
-                 identity_admin_endpoint_type='public', identity_uri=None):
+                 identity_admin_endpoint_type='public', identity_uri=None,
+                 networking_timeout_409=120):
         super(DynamicCredentialProvider, self).__init__(
             identity_version=identity_version, identity_uri=identity_uri,
             admin_role=admin_role, name=name,
@@ -121,6 +122,7 @@
             self.roles_admin_client,
             self.domains_admin_client,
             self.creds_domain_name)
+        self.networking_timeout_409 = networking_timeout_409
 
     def _get_admin_clients(self, endpoint_type):
         """Returns a tuple with instances of the following admin clients