Merge "Resolve TODO in test: 'test_available_volume_retype_with_migration'"
diff --git a/tempest/api/compute/admin/test_servers_on_multinodes.py b/tempest/api/compute/admin/test_servers_on_multinodes.py
index 72f4ddc..2e7b07b 100644
--- a/tempest/api/compute/admin/test_servers_on_multinodes.py
+++ b/tempest/api/compute/admin/test_servers_on_multinodes.py
@@ -76,3 +76,38 @@
                                            wait_until='ACTIVE')['id']
         host02 = self._get_host(server02)
         self.assertNotEqual(self.host01, host02)
+
+    @decorators.idempotent_id('f8bd0867-e459-45f5-ba53-59134552fe04')
+    @testtools.skipUnless(
+        compute.is_scheduler_filter_enabled("ServerGroupAntiAffinityFilter"),
+        'ServerGroupAntiAffinityFilter is not available.')
+    def test_create_server_with_scheduler_hint_group_anti_affinity(self):
+        """Tests the ServerGroupAntiAffinityFilter
+
+        Creates two servers in an anti-affinity server group and
+        asserts the servers are in the group and on different hosts.
+        """
+        group_id = self.create_test_server_group(
+            policy=['anti-affinity'])['id']
+        hints = {'group': group_id}
+        reservation_id = self.create_test_server(
+            scheduler_hints=hints, wait_until='ACTIVE', min_count=2,
+            return_reservation_id=True)['reservation_id']
+
+        # Get the servers using the reservation_id.
+        servers = self.servers_client.list_servers(
+            detail=True, reservation_id=reservation_id)['servers']
+        self.assertEqual(2, len(servers))
+
+        # Assert the servers are in the group.
+        server_group = self.server_groups_client.show_server_group(
+            group_id)['server_group']
+        hosts = {}
+        for server in servers:
+            self.assertIn(server['id'], server_group['members'])
+            hosts[server['id']] = self._get_host(server['id'])
+
+        # Assert the servers are on different hosts.
+        hostnames = list(hosts.values())
+        self.assertNotEqual(hostnames[0], hostnames[1],
+                            'Servers are on the same host: %s' % hosts)
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index 49b6585..e61dbc8 100644
--- a/tempest/api/identity/admin/v3/test_inherits.py
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -16,17 +16,17 @@
 from tempest import test
 
 
-class BaseInheritsV3Test(base.BaseIdentityV3AdminTest):
+class InheritsV3TestJSON(base.BaseIdentityV3AdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(BaseInheritsV3Test, cls).skip_checks()
+        super(InheritsV3TestJSON, cls).skip_checks()
         if not test.is_extension_enabled('OS-INHERIT', 'identity'):
             raise cls.skipException("Inherits aren't enabled")
 
     @classmethod
     def resource_setup(cls):
-        super(BaseInheritsV3Test, cls).resource_setup()
+        super(InheritsV3TestJSON, cls).resource_setup()
         u_name = data_utils.rand_name('user-')
         u_desc = '%s description' % u_name
         u_email = '%s@testmail.tm' % u_name
@@ -51,15 +51,12 @@
         cls.projects_client.delete_project(cls.project['id'])
         cls.domains_client.update_domain(cls.domain['id'], enabled=False)
         cls.domains_client.delete_domain(cls.domain['id'])
-        super(BaseInheritsV3Test, cls).resource_cleanup()
+        super(InheritsV3TestJSON, cls).resource_cleanup()
 
     def _list_assertions(self, body, fetched_role_ids, role_id):
         self.assertEqual(len(body), 1)
         self.assertIn(role_id, fetched_role_ids)
 
-
-class InheritsV3TestJSON(BaseInheritsV3Test):
-
     @decorators.idempotent_id('4e6f0366-97c8-423c-b2be-41eae6ac91c8')
     def test_inherit_assign_list_check_revoke_roles_on_domains_user(self):
         # Create role
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 850e549..2530072 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -26,25 +26,27 @@
 CONF = config.CONF
 
 
-class BaseTrustsV3Test(base.BaseIdentityV3AdminTest):
+class TrustsV3TestJSON(base.BaseIdentityV3AdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(BaseTrustsV3Test, cls).skip_checks()
+        super(TrustsV3TestJSON, cls).skip_checks()
         if not CONF.identity_feature_enabled.trust:
             raise cls.skipException("Trusts aren't enabled")
 
     def setUp(self):
-        super(BaseTrustsV3Test, self).setUp()
+        super(TrustsV3TestJSON, self).setUp()
         # Use alt_username as the trustee
         self.trust_id = None
+        self.create_trustor_and_roles()
+        self.addCleanup(self.cleanup_user_and_roles)
 
     def tearDown(self):
         if self.trust_id:
             # Do the delete in tearDown not addCleanup - we want the test to
             # fail in the event there is a bug which causes undeletable trusts
             self.delete_trust()
-        super(BaseTrustsV3Test, self).tearDown()
+        super(TrustsV3TestJSON, self).tearDown()
 
     def create_trustor_and_roles(self):
         # create a project that trusts will be granted on
@@ -193,14 +195,6 @@
                           self.trust_id)
         self.trust_id = None
 
-
-class TrustsV3TestJSON(BaseTrustsV3Test):
-
-    def setUp(self):
-        super(TrustsV3TestJSON, self).setUp()
-        self.create_trustor_and_roles()
-        self.addCleanup(self.cleanup_user_and_roles)
-
     @decorators.idempotent_id('5a0a91a4-baef-4a14-baba-59bf4d7fcace')
     def test_trust_impersonate(self):
         # Test case to check we can create, get and delete a trust
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 72face8..db165ab 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -128,13 +128,6 @@
             msg = "DVR extension not enabled."
             raise cls.skipException(msg)
 
-    @classmethod
-    def resource_setup(cls):
-        super(DvrRoutersNegativeTest, cls).resource_setup()
-        cls.router = cls.create_router()
-        cls.network = cls.create_network()
-        cls.subnet = cls.create_subnet(cls.network)
-
     @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4990b055-8fc7-48ab-bba7-aa28beaad0b9')
     def test_router_create_tenant_distributed_returns_forbidden(self):
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index 9e83a07..84f1c9d 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -13,20 +13,14 @@
 
 from oslo_log import log as logging
 
-from tempest import config
-
 from tempest.lib.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 
-CONF = config.CONF
 LOG = logging.getLogger(__name__)
 
 
-def _create_neutron_sec_group_rules(os, sec_group):
+def _create_neutron_sec_group_rules(os, sec_group, ethertype='IPv4'):
     sec_group_rules_client = os.security_group_rules_client
-    ethertype = 'IPv4'
-    if CONF.validation.ip_version_for_ssh == 6:
-        ethertype = 'IPv6'
 
     sec_group_rules_client.create_security_group_rule(
         security_group_id=sec_group['id'],
@@ -42,7 +36,8 @@
         direction='ingress')
 
 
-def create_ssh_security_group(os, add_rule=False):
+def create_ssh_security_group(os, add_rule=False, ethertype='IPv4',
+                              use_neutron=True):
     security_groups_client = os.compute_security_groups_client
     security_group_rules_client = os.compute_security_group_rules_client
     sg_name = data_utils.rand_name('securitygroup-')
@@ -50,8 +45,9 @@
     security_group = security_groups_client.create_security_group(
         name=sg_name, description=sg_description)['security_group']
     if add_rule:
-        if CONF.service_available.neutron:
-            _create_neutron_sec_group_rules(os, security_group)
+        if use_neutron:
+            _create_neutron_sec_group_rules(os, security_group,
+                                            ethertype=ethertype)
         else:
             security_group_rules_client.create_security_group_rule(
                 parent_group_id=security_group['id'], ip_protocol='tcp',
@@ -64,7 +60,10 @@
     return security_group
 
 
-def create_validation_resources(os, validation_resources=None):
+def create_validation_resources(os, validation_resources=None,
+                                ethertype='IPv4', use_neutron=True,
+                                floating_network_id=None,
+                                floating_network_name=None):
     # Create and Return the validation resources required to validate a VM
     validation_data = {}
     if validation_resources:
@@ -78,11 +77,12 @@
             if validation_resources['security_group_rules']:
                 add_rule = True
             validation_data['security_group'] = \
-                create_ssh_security_group(os, add_rule)
+                create_ssh_security_group(
+                    os, add_rule, use_neutron=use_neutron, ethertype=ethertype)
         if validation_resources['floating_ip']:
-            if CONF.service_available.neutron:
+            if use_neutron:
                 floatingip = os.floating_ips_client.create_floatingip(
-                    floating_network_id=CONF.network.public_network_id)
+                    floating_network_id=floating_network_id)
                 # validation_resources['floating_ip'] has historically looked
                 # like a compute API POST /os-floating-ips response, so we need
                 # to mangle it a bit for a Neutron response with different
@@ -96,7 +96,7 @@
                 # floating IPs using the compute API should be capped at 2.35.
                 validation_data.update(
                     os.compute_floating_ips_client.create_floating_ip(
-                        pool=CONF.network.floating_network_name))
+                        pool=floating_network_name))
     return validation_data
 
 
diff --git a/tempest/test.py b/tempest/test.py
index 00f99d7..47cbb5e 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -373,9 +373,18 @@
     @classmethod
     def resource_setup(cls):
         """Class level resource setup for test cases."""
+        if (CONF.validation.ip_version_for_ssh not in (4, 6) and
+            CONF.service_available.neutron):
+            msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
+            raise lib_exc.InvalidConfiguration(
+                msg % CONF.validation.ip_version_for_ssh)
         if hasattr(cls, "os_primary"):
             cls.validation_resources = vresources.create_validation_resources(
-                cls.os_primary, cls.validation_resources)
+                cls.os_primary, cls.validation_resources,
+                use_neutron=CONF.service_available.neutron,
+                ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
+                floating_network_id=CONF.network.public_network_id,
+                floating_network_name=CONF.network.floating_network_name)
         else:
             LOG.warning("Client manager not found, validation resources not"
                         " created")