Merge "Separate admin test from RoutersNegativeTest"
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 79d03f4..902ea9a 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -59,15 +59,20 @@
                 msg += " for hypervisor_type %s" % CONF.compute.hypervisor_type
             raise testtools.TestCase.failureException(msg)
 
+    def _create_test_aggregate(self, **kwargs):
+        if 'name' not in kwargs:
+            kwargs['name'] = data_utils.rand_name(self.aggregate_name_prefix)
+        aggregate = self.client.create_aggregate(**kwargs)['aggregate']
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_aggregate, aggregate['id'])
+        self.assertEqual(kwargs['name'], aggregate['name'])
+
+        return aggregate
+
     @decorators.idempotent_id('0d148aa3-d54c-4317-aa8d-42040a475e20')
     def test_aggregate_create_delete(self):
         # Create and delete an aggregate.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.client.delete_aggregate, aggregate['id'])
-        self.assertEqual(aggregate_name, aggregate['name'])
+        aggregate = self._create_test_aggregate()
         self.assertIsNone(aggregate['availability_zone'])
 
         self.client.delete_aggregate(aggregate['id'])
@@ -76,13 +81,8 @@
     @decorators.idempotent_id('5873a6f8-671a-43ff-8838-7ce430bb6d0b')
     def test_aggregate_create_delete_with_az(self):
         # Create and delete an aggregate.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         az_name = data_utils.rand_name(self.az_name_prefix)
-        aggregate = self.client.create_aggregate(
-            name=aggregate_name, availability_zone=az_name)['aggregate']
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.client.delete_aggregate, aggregate['id'])
-        self.assertEqual(aggregate_name, aggregate['name'])
+        aggregate = self._create_test_aggregate(availability_zone=az_name)
         self.assertEqual(az_name, aggregate['availability_zone'])
 
         self.client.delete_aggregate(aggregate['id'])
@@ -91,11 +91,7 @@
     @decorators.idempotent_id('68089c38-04b1-4758-bdf0-cf0daec4defd')
     def test_aggregate_create_verify_entry_in_list(self):
         # Create an aggregate and ensure it is listed.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         aggregates = self.client.list_aggregates()['aggregates']
         self.assertIn((aggregate['id'], aggregate['availability_zone']),
                       map(lambda x: (x['id'], x['availability_zone']),
@@ -104,11 +100,7 @@
     @decorators.idempotent_id('36ec92ca-7a73-43bc-b920-7531809e8540')
     def test_aggregate_create_update_metadata_get_details(self):
         # Create an aggregate and ensure its details are returned.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         body = self.client.show_aggregate(aggregate['id'])['aggregate']
         self.assertEqual(aggregate['name'], body['name'])
         self.assertEqual(aggregate['availability_zone'],
@@ -129,11 +121,9 @@
         # Update an aggregate and ensure properties are updated correctly
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         az_name = data_utils.rand_name(self.az_name_prefix)
-        aggregate = self.client.create_aggregate(
-            name=aggregate_name, availability_zone=az_name)['aggregate']
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate(
+            name=aggregate_name, availability_zone=az_name)
 
-        self.assertEqual(aggregate_name, aggregate['name'])
         self.assertEqual(az_name, aggregate['availability_zone'])
         self.assertIsNotNone(aggregate['id'])
 
@@ -159,9 +149,7 @@
         # Add a host to the given aggregate and remove.
         self.useFixture(fixtures.LockFixture('availability_zone'))
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate(name=aggregate_name)
 
         body = (self.client.add_host(aggregate['id'], host=self.host)
                 ['aggregate'])
@@ -182,9 +170,8 @@
         # Add a host to the given aggregate and list.
         self.useFixture(fixtures.LockFixture('availability_zone'))
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate(name=aggregate_name)
+
         self.client.add_host(aggregate['id'], host=self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'],
                         host=self.host)
@@ -202,9 +189,8 @@
         # Add a host to the given aggregate and get details.
         self.useFixture(fixtures.LockFixture('availability_zone'))
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate(name=aggregate_name)
+
         self.client.add_host(aggregate['id'], host=self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'],
                         host=self.host)
@@ -218,11 +204,9 @@
     def test_aggregate_add_host_create_server_with_az(self):
         # Add a host to the given aggregate and create a server.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         az_name = data_utils.rand_name(self.az_name_prefix)
-        aggregate = self.client.create_aggregate(
-            name=aggregate_name, availability_zone=az_name)['aggregate']
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate(availability_zone=az_name)
+
         self.client.add_host(aggregate['id'], host=self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'],
                         host=self.host)
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index b0f18d7..ca53696 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -124,8 +124,8 @@
                           data_utils.rand_uuid())
 
     @decorators.idempotent_id('b0b17f83-d14e-4fc4-8f31-bcc9f3cfa629')
-    @testtools.skipUnless(CONF.compute_feature_enabled.resize,
-                          'Resize not available.')
+    @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+                          'Cold migration not available.')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     @decorators.attr(type=['negative'])
diff --git a/tempest/api/compute/admin/test_servers_on_multinodes.py b/tempest/api/compute/admin/test_servers_on_multinodes.py
index 6a2e5e9..858998a 100644
--- a/tempest/api/compute/admin/test_servers_on_multinodes.py
+++ b/tempest/api/compute/admin/test_servers_on_multinodes.py
@@ -25,6 +25,12 @@
 class ServersOnMultiNodesTest(base.BaseV2ComputeAdminTest):
 
     @classmethod
+    def resource_setup(cls):
+        super(ServersOnMultiNodesTest, cls).resource_setup()
+        cls.server01 = cls.create_test_server(wait_until='ACTIVE')['id']
+        cls.host01 = cls._get_host(cls.server01)
+
+    @classmethod
     def skip_checks(cls):
         super(ServersOnMultiNodesTest, cls).skip_checks()
 
@@ -32,8 +38,9 @@
             raise cls.skipException(
                 "Less than 2 compute nodes, skipping multi-nodes test.")
 
-    def _get_host(self, server_id):
-        return self.os_admin.servers_client.show_server(
+    @classmethod
+    def _get_host(cls, server_id):
+        return cls.os_admin.servers_client.show_server(
             server_id)['server']['OS-EXT-SRV-ATTR:host']
 
     @decorators.idempotent_id('26a9d5df-6890-45f2-abc4-a659290cb130')
@@ -41,40 +48,31 @@
         test.is_scheduler_filter_enabled("SameHostFilter"),
         'SameHostFilter is not available.')
     def test_create_servers_on_same_host(self):
-        server01 = self.create_test_server(wait_until='ACTIVE')['id']
-
-        hints = {'same_host': server01}
+        hints = {'same_host': self.server01}
         server02 = self.create_test_server(scheduler_hints=hints,
                                            wait_until='ACTIVE')['id']
-        host01 = self._get_host(server01)
         host02 = self._get_host(server02)
-        self.assertEqual(host01, host02)
+        self.assertEqual(self.host01, host02)
 
     @decorators.idempotent_id('cc7ca884-6e3e-42a3-a92f-c522fcf25e8e')
     @testtools.skipUnless(
         test.is_scheduler_filter_enabled("DifferentHostFilter"),
         'DifferentHostFilter is not available.')
     def test_create_servers_on_different_hosts(self):
-        server01 = self.create_test_server(wait_until='ACTIVE')['id']
-
-        hints = {'different_host': server01}
+        hints = {'different_host': self.server01}
         server02 = self.create_test_server(scheduler_hints=hints,
                                            wait_until='ACTIVE')['id']
-        host01 = self._get_host(server01)
         host02 = self._get_host(server02)
-        self.assertNotEqual(host01, host02)
+        self.assertNotEqual(self.host01, host02)
 
     @decorators.idempotent_id('7869cc84-d661-4e14-9f00-c18cdc89cf57')
     @testtools.skipUnless(
         test.is_scheduler_filter_enabled("DifferentHostFilter"),
         'DifferentHostFilter is not available.')
     def test_create_servers_on_different_hosts_with_list_of_servers(self):
-        server01 = self.create_test_server(wait_until='ACTIVE')['id']
-
         # This scheduler-hint supports list of servers also.
-        hints = {'different_host': [server01]}
+        hints = {'different_host': [self.server01]}
         server02 = self.create_test_server(scheduler_hints=hints,
                                            wait_until='ACTIVE')['id']
-        host01 = self._get_host(server01)
         host02 = self._get_host(server02)
-        self.assertNotEqual(host01, host02)
+        self.assertNotEqual(self.host01, host02)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index a5ee716..141b9f3 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -123,10 +123,13 @@
 
     @classmethod
     def resource_cleanup(cls):
-        cls.clear_images()
+        cls.clear_resources('images', cls.images,
+                            cls.compute_images_client.delete_image)
         cls.clear_servers()
-        cls.clear_security_groups()
-        cls.clear_server_groups()
+        cls.clear_resources('security groups', cls.security_groups,
+                            cls.security_groups_client.delete_security_group)
+        cls.clear_resources('server groups', cls.server_groups,
+                            cls.server_groups_client.delete_server_group)
         cls.clear_volumes()
         super(BaseV2ComputeTest, cls).resource_cleanup()
 
@@ -172,42 +175,19 @@
                 raise
 
     @classmethod
-    def clear_images(cls):
-        LOG.debug('Clearing images: %s', ','.join(cls.images))
-        for image_id in cls.images:
+    def clear_resources(cls, resource_name, resources, resource_del_func):
+        LOG.debug('Clearing %s: %s', resource_name,
+                  ','.join(map(str, resources)))
+        for res_id in resources:
             try:
                 test_utils.call_and_ignore_notfound_exc(
-                    cls.compute_images_client.delete_image, image_id)
-            except Exception:
-                LOG.exception('Exception raised deleting image %s', image_id)
-
-    @classmethod
-    def clear_security_groups(cls):
-        LOG.debug('Clearing security groups: %s', ','.join(
-            str(sg['id']) for sg in cls.security_groups))
-        for sg in cls.security_groups:
-            try:
-                test_utils.call_and_ignore_notfound_exc(
-                    cls.security_groups_client.delete_security_group, sg['id'])
+                    resource_del_func, res_id)
             except Exception as exc:
-                LOG.info('Exception raised deleting security group %s',
-                         sg['id'])
+                LOG.exception('Exception raised deleting %s: %s',
+                              resource_name, res_id)
                 LOG.exception(exc)
 
     @classmethod
-    def clear_server_groups(cls):
-        LOG.debug('Clearing server groups: %s', ','.join(cls.server_groups))
-        for server_group_id in cls.server_groups:
-            try:
-                test_utils.call_and_ignore_notfound_exc(
-                    cls.server_groups_client.delete_server_group,
-                    server_group_id
-                )
-            except Exception:
-                LOG.exception('Exception raised deleting server-group %s',
-                              server_group_id)
-
-    @classmethod
     def create_test_server(cls, validatable=False, volume_backed=False,
                            **kwargs):
         """Wrapper utility that returns a test server.
@@ -243,7 +223,7 @@
             description = data_utils.rand_name('description')
         body = cls.security_groups_client.create_security_group(
             name=name, description=description)['security_group']
-        cls.security_groups.append(body)
+        cls.security_groups.append(body['id'])
 
         return body
 
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 8808510..76b9c44 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -168,6 +168,9 @@
 
     @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
     def test_rebuild_server(self):
+        # Get the IPs the server has before rebuilding it
+        original_addresses = (self.client.show_server(self.server_id)['server']
+                              ['addresses'])
         # The server should be rebuilt using the provided image and data
         meta = {'rebuild': 'server'}
         new_name = data_utils.rand_name(self.__class__.__name__ + '-server')
@@ -197,6 +200,7 @@
         rebuilt_image_id = server['image']['id']
         self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
         self.assertEqual(new_name, server['name'])
+        self.assertEqual(original_addresses, server['addresses'])
 
         if CONF.validation.run_validation:
             # Authentication is attempted in the following order of priority:
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index b0a6622..11517cc 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -113,51 +113,35 @@
     def test_list_get_volume_attachments(self):
         # List volume attachment of the server
         server = self._create_server()
-        volume = self.create_volume()
-        attachment = self.attach_volume(server, volume,
-                                        device=('/dev/%s' % self.device))
+        volume_1st = self.create_volume()
+        attachment_1st = self.attach_volume(server, volume_1st,
+                                            device=('/dev/%s' % self.device))
         body = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
         self.assertEqual(1, len(body))
-        self.assertIn(attachment, body)
+        self.assertIn(attachment_1st, body)
 
         # Get volume attachment of the server
         body = self.servers_client.show_volume_attachment(
             server['id'],
-            attachment['id'])['volumeAttachment']
+            attachment_1st['id'])['volumeAttachment']
         self.assertEqual(server['id'], body['serverId'])
-        self.assertEqual(volume['id'], body['volumeId'])
-        self.assertEqual(attachment['id'], body['id'])
+        self.assertEqual(volume_1st['id'], body['volumeId'])
+        self.assertEqual(attachment_1st['id'], body['id'])
 
-    @decorators.idempotent_id('757d488b-a951-4bc7-b3cd-f417028da08a')
-    def test_list_get_two_volume_attachments(self):
-        # NOTE: This test is using the volume device auto-assignment
-        # without specifying the device ("/dev/sdb", etc). The feature
-        # is supported since Nova Liberty release or later. So this should
-        # be skipped on older clouds.
-        server = self._create_server()
-        volume_1st = self.create_volume()
+        # attach one more volume to server
         volume_2nd = self.create_volume()
-        attachment_1st = self.attach_volume(server, volume_1st)
         attachment_2nd = self.attach_volume(server, volume_2nd)
-
         body = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
         self.assertEqual(2, len(body))
 
-        body = self.servers_client.show_volume_attachment(
-            server['id'],
-            attachment_1st['id'])['volumeAttachment']
-        self.assertEqual(server['id'], body['serverId'])
-        self.assertEqual(attachment_1st['volumeId'], body['volumeId'])
-        self.assertEqual(attachment_1st['id'], body['id'])
-
-        body = self.servers_client.show_volume_attachment(
-            server['id'],
-            attachment_2nd['id'])['volumeAttachment']
-        self.assertEqual(server['id'], body['serverId'])
-        self.assertEqual(attachment_2nd['volumeId'], body['volumeId'])
-        self.assertEqual(attachment_2nd['id'], body['id'])
+        for attachment in [attachment_1st, attachment_2nd]:
+            body = self.servers_client.show_volume_attachment(
+                server['id'], attachment['id'])['volumeAttachment']
+            self.assertEqual(server['id'], body['serverId'])
+            self.assertEqual(attachment['volumeId'], body['volumeId'])
+            self.assertEqual(attachment['id'], body['id'])
 
 
 class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 837758f..1eb76a0 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -40,6 +40,7 @@
     @decorators.idempotent_id('86be1cba-2640-11e5-9c82-635fb964c912')
     @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
                           "Cinder volume snapshots are disabled")
+    @decorators.skip_because(bug='1687044')
     def test_volume_extend_when_volume_has_snapshot(self):
         volume = self.create_volume()
         self.create_snapshot(volume['id'])
diff --git a/tempest/test.py b/tempest/test.py
index f6b17ad..e8108f4 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -339,24 +339,24 @@
                 if credentials_type == 'primary':
                     cls.os = debtcollector.moves.moved_read_only_property(
                         'os', 'os_primary', version='Pike',
-                        removal_version='Ocata')
+                        removal_version='Queens')
                     cls.manager =\
                         debtcollector.moves.moved_read_only_property(
                             'manager', 'os_primary', version='Pike',
-                            removal_version='Ocata')
+                            removal_version='Queens')
                 if credentials_type == 'admin':
                     cls.os_adm = debtcollector.moves.moved_read_only_property(
                         'os_adm', 'os_admin', version='Pike',
-                        removal_version='Ocata')
+                        removal_version='Queens')
                     cls.admin_manager =\
                         debtcollector.moves.moved_read_only_property(
                             'admin_manager', 'os_admin', version='Pike',
-                            removal_version='Ocata')
+                            removal_version='Queens')
                 if credentials_type == 'alt':
                     cls.alt_manager =\
                         debtcollector.moves.moved_read_only_property(
                             'alt_manager', 'os_alt', version='Pike',
-                            removal_version='Ocata')
+                            removal_version='Queens')
             elif isinstance(credentials_type, list):
                 manager = cls.get_client_manager(roles=credentials_type[1:],
                                                  force_new=True)