Merge "Refactor volume groups and group snapshots tests"
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 7189312..aca1845 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -352,6 +352,10 @@
 
   .. _3.12:  https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id12
 
+  * `3.13`_
+
+  .. _3.13:  https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id13
+
   * `3.14`_
 
   .. _3.14:  https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id14
diff --git a/tempest/api/volume/admin/test_group_snapshots.py b/tempest/api/volume/admin/test_group_snapshots.py
new file mode 100644
index 0000000..36e0035
--- /dev/null
+++ b/tempest/api/volume/admin/test_group_snapshots.py
@@ -0,0 +1,193 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# Copyright (C) 2017 Dell Inc. or its subsidiaries.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.volume import base
+from tempest.common import waiters
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+
+class BaseGroupSnapshotsTest(base.BaseVolumeAdminTest):
+
+    def _create_group_snapshot(self, **kwargs):
+        if 'name' not in kwargs:
+            kwargs['name'] = data_utils.rand_name(
+                self.__class__.__name__ + '-Group_Snapshot')
+
+        group_snapshot = self.group_snapshots_client.create_group_snapshot(
+            **kwargs)['group_snapshot']
+        group_snapshot['group_id'] = kwargs['group_id']
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self._delete_group_snapshot, group_snapshot)
+        waiters.wait_for_volume_resource_status(
+            self.group_snapshots_client, group_snapshot['id'], 'available')
+        return group_snapshot
+
+    def _delete_group_snapshot(self, group_snapshot):
+        self.group_snapshots_client.delete_group_snapshot(group_snapshot['id'])
+        vols = self.volumes_client.list_volumes(detail=True)['volumes']
+        snapshots = self.snapshots_client.list_snapshots(
+            detail=True)['snapshots']
+        for vol in vols:
+            for snap in snapshots:
+                if (vol['group_id'] == group_snapshot['group_id'] and
+                        vol['id'] == snap['volume_id']):
+                    self.snapshots_client.wait_for_resource_deletion(
+                        snap['id'])
+        self.group_snapshots_client.wait_for_resource_deletion(
+            group_snapshot['id'])
+
+
+class GroupSnapshotsTest(BaseGroupSnapshotsTest):
+    _api_version = 3
+    min_microversion = '3.14'
+    max_microversion = 'latest'
+
+    @decorators.idempotent_id('1298e537-f1f0-47a3-a1dd-8adec8168897')
+    def test_group_snapshot_create_show_list_delete(self):
+        # Create volume type
+        volume_type = self.create_volume_type()
+
+        # Create group type
+        group_type = self.create_group_type()
+
+        # Create group
+        grp = self.create_group(group_type=group_type['id'],
+                                volume_types=[volume_type['id']])
+
+        # Create volume
+        vol = self.create_volume(volume_type=volume_type['id'],
+                                 group_id=grp['id'])
+
+        # Create group snapshot
+        group_snapshot_name = data_utils.rand_name('group_snapshot')
+        group_snapshot = self._create_group_snapshot(
+            group_id=grp['id'], name=group_snapshot_name)
+        snapshots = self.snapshots_client.list_snapshots(
+            detail=True)['snapshots']
+        for snap in snapshots:
+            if vol['id'] == snap['volume_id']:
+                waiters.wait_for_volume_resource_status(
+                    self.snapshots_client, snap['id'], 'available')
+        self.assertEqual(group_snapshot_name, group_snapshot['name'])
+
+        # Get a given group snapshot
+        group_snapshot = self.group_snapshots_client.show_group_snapshot(
+            group_snapshot['id'])['group_snapshot']
+        self.assertEqual(group_snapshot_name, group_snapshot['name'])
+
+        # Get all group snapshots with details, check some detail-specific
+        # elements, and look for the created group snapshot
+        group_snapshots = self.group_snapshots_client.list_group_snapshots(
+            detail=True)['group_snapshots']
+        for grp_snapshot in group_snapshots:
+            self.assertIn('created_at', grp_snapshot)
+            self.assertIn('group_id', grp_snapshot)
+        self.assertIn((group_snapshot['name'], group_snapshot['id']),
+                      [(m['name'], m['id']) for m in group_snapshots])
+
+        # Delete group snapshot
+        self._delete_group_snapshot(group_snapshot)
+        group_snapshots = self.group_snapshots_client.list_group_snapshots()[
+            'group_snapshots']
+        self.assertEmpty(group_snapshots)
+
+    @decorators.idempotent_id('eff52c70-efc7-45ed-b47a-4ad675d09b81')
+    def test_create_group_from_group_snapshot(self):
+        # Create volume type
+        volume_type = self.create_volume_type()
+
+        # Create group type
+        group_type = self.create_group_type()
+
+        # Create Group
+        grp = self.create_group(group_type=group_type['id'],
+                                volume_types=[volume_type['id']])
+
+        # Create volume
+        vol = self.create_volume(volume_type=volume_type['id'],
+                                 group_id=grp['id'])
+
+        # Create group_snapshot
+        group_snapshot_name = data_utils.rand_name('group_snapshot')
+        group_snapshot = self._create_group_snapshot(
+            group_id=grp['id'], name=group_snapshot_name)
+        self.assertEqual(group_snapshot_name, group_snapshot['name'])
+        snapshots = self.snapshots_client.list_snapshots(
+            detail=True)['snapshots']
+        for snap in snapshots:
+            if vol['id'] == snap['volume_id']:
+                waiters.wait_for_volume_resource_status(
+                    self.snapshots_client, snap['id'], 'available')
+
+        # Create Group from Group snapshot
+        grp_name2 = data_utils.rand_name('Group_from_snap')
+        grp2 = self.groups_client.create_group_from_source(
+            group_snapshot_id=group_snapshot['id'], name=grp_name2)['group']
+        self.addCleanup(self.delete_group, grp2['id'])
+        self.assertEqual(grp_name2, grp2['name'])
+        vols = self.volumes_client.list_volumes(detail=True)['volumes']
+        for vol in vols:
+            if vol['group_id'] == grp2['id']:
+                waiters.wait_for_volume_resource_status(
+                    self.volumes_client, vol['id'], 'available')
+        waiters.wait_for_volume_resource_status(
+            self.groups_client, grp2['id'], 'available')
+
+
+class GroupSnapshotsV319Test(BaseGroupSnapshotsTest):
+    _api_version = 3
+    min_microversion = '3.19'
+    max_microversion = 'latest'
+
+    @decorators.idempotent_id('3b42c9b9-c984-4444-816e-ca2e1ed30b40')
+    def test_reset_group_snapshot_status(self):
+        # Create volume type
+        volume_type = self.create_volume_type()
+
+        # Create group type
+        group_type = self.create_group_type()
+
+        # Create group
+        group = self.create_group(group_type=group_type['id'],
+                                  volume_types=[volume_type['id']])
+
+        # Create volume
+        volume = self.create_volume(volume_type=volume_type['id'],
+                                    group_id=group['id'])
+
+        # Create group snapshot
+        group_snapshot = self._create_group_snapshot(group_id=group['id'])
+        snapshots = self.snapshots_client.list_snapshots(
+            detail=True)['snapshots']
+        for snap in snapshots:
+            if volume['id'] == snap['volume_id']:
+                waiters.wait_for_volume_resource_status(
+                    self.snapshots_client, snap['id'], 'available')
+
+        # Reset group snapshot status
+        self.addCleanup(waiters.wait_for_volume_resource_status,
+                        self.group_snapshots_client,
+                        group_snapshot['id'], 'available')
+        self.addCleanup(
+            self.admin_group_snapshots_client.reset_group_snapshot_status,
+            group_snapshot['id'], 'available')
+        for status in ['creating', 'available', 'error']:
+            self.admin_group_snapshots_client.reset_group_snapshot_status(
+                group_snapshot['id'], status)
+            waiters.wait_for_volume_resource_status(
+                self.group_snapshots_client, group_snapshot['id'], status)
diff --git a/tempest/api/volume/admin/test_groups.py b/tempest/api/volume/admin/test_groups.py
index 6b53d85..2f6eb6b 100644
--- a/tempest/api/volume/admin/test_groups.py
+++ b/tempest/api/volume/admin/test_groups.py
@@ -17,54 +17,14 @@
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
 
 
-class BaseGroupsTest(base.BaseVolumeAdminTest):
-
-    def _delete_group(self, grp_id, delete_volumes=True):
-        self.groups_client.delete_group(grp_id, delete_volumes)
-        vols = self.volumes_client.list_volumes(detail=True)['volumes']
-        for vol in vols:
-            if vol['group_id'] == grp_id:
-                self.volumes_client.wait_for_resource_deletion(vol['id'])
-        self.groups_client.wait_for_resource_deletion(grp_id)
-
-    def _delete_group_snapshot(self, group_snapshot_id, grp_id):
-        self.group_snapshots_client.delete_group_snapshot(group_snapshot_id)
-        vols = self.volumes_client.list_volumes(detail=True)['volumes']
-        snapshots = self.snapshots_client.list_snapshots(
-            detail=True)['snapshots']
-        for vol in vols:
-            for snap in snapshots:
-                if (vol['group_id'] == grp_id and
-                        vol['id'] == snap['volume_id']):
-                    self.snapshots_client.wait_for_resource_deletion(
-                        snap['id'])
-        self.group_snapshots_client.wait_for_resource_deletion(
-            group_snapshot_id)
-
-    def _create_group(self, group_type, volume_type, grp_name=None):
-        if not grp_name:
-            grp_name = data_utils.rand_name('Group')
-        grp = self.groups_client.create_group(
-            group_type=group_type['id'],
-            volume_types=[volume_type['id']],
-            name=grp_name)['group']
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self._delete_group, grp['id'])
-        waiters.wait_for_volume_resource_status(
-            self.groups_client, grp['id'], 'available')
-        self.assertEqual(grp_name, grp['name'])
-        return grp
-
-
-class GroupsTest(BaseGroupsTest):
+class GroupsTest(base.BaseVolumeAdminTest):
     _api_version = 3
-    min_microversion = '3.14'
+    min_microversion = '3.13'
     max_microversion = 'latest'
 
     @decorators.idempotent_id('4b111d28-b73d-4908-9bd2-03dc2992e4d4')
@@ -77,13 +37,15 @@
 
         # Create group
         grp1_name = data_utils.rand_name('Group1')
-        grp1 = self._create_group(group_type, volume_type,
-                                  grp_name=grp1_name)
+        grp1 = self.create_group(group_type=group_type['id'],
+                                 volume_types=[volume_type['id']],
+                                 name=grp1_name)
         grp1_id = grp1['id']
 
         grp2_name = data_utils.rand_name('Group2')
-        grp2 = self._create_group(group_type, volume_type,
-                                  grp_name=grp2_name)
+        grp2 = self.create_group(group_type=group_type['id'],
+                                 volume_types=[volume_type['id']],
+                                 name=grp2_name)
         grp2_id = grp2['id']
 
         # Create volume
@@ -125,143 +87,12 @@
 
         # Delete group
         # grp1 has a volume so delete_volumes flag is set to True by default
-        self._delete_group(grp1_id)
+        self.delete_group(grp1_id)
         # grp2 is empty so delete_volumes flag can be set to False
-        self._delete_group(grp2_id, delete_volumes=False)
+        self.delete_group(grp2_id, delete_volumes=False)
         grps = self.groups_client.list_groups(detail=True)['groups']
         self.assertEmpty(grps)
 
-    @decorators.idempotent_id('1298e537-f1f0-47a3-a1dd-8adec8168897')
-    def test_group_snapshot_create_show_list_delete(self):
-        # Create volume type
-        volume_type = self.create_volume_type()
-
-        # Create group type
-        group_type = self.create_group_type()
-
-        # Create group
-        grp = self._create_group(group_type, volume_type)
-
-        # Create volume
-        vol = self.create_volume(volume_type=volume_type['id'],
-                                 group_id=grp['id'])
-
-        # Create group snapshot
-        group_snapshot_name = data_utils.rand_name('group_snapshot')
-        group_snapshot = (
-            self.group_snapshots_client.create_group_snapshot(
-                group_id=grp['id'],
-                name=group_snapshot_name)['group_snapshot'])
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self._delete_group_snapshot,
-                        group_snapshot['id'], grp['id'])
-        snapshots = self.snapshots_client.list_snapshots(
-            detail=True)['snapshots']
-        for snap in snapshots:
-            if vol['id'] == snap['volume_id']:
-                waiters.wait_for_volume_resource_status(
-                    self.snapshots_client, snap['id'], 'available')
-        waiters.wait_for_volume_resource_status(
-            self.group_snapshots_client,
-            group_snapshot['id'], 'available')
-        self.assertEqual(group_snapshot_name, group_snapshot['name'])
-
-        # Get a given group snapshot
-        group_snapshot = self.group_snapshots_client.show_group_snapshot(
-            group_snapshot['id'])['group_snapshot']
-        self.assertEqual(group_snapshot_name, group_snapshot['name'])
-
-        # Get all group snapshots with details, check some detail-specific
-        # elements, and look for the created group snapshot
-        group_snapshots = (self.group_snapshots_client.list_group_snapshots(
-            detail=True)['group_snapshots'])
-        for grp_snapshot in group_snapshots:
-            self.assertIn('created_at', grp_snapshot)
-            self.assertIn('group_id', grp_snapshot)
-        self.assertIn((group_snapshot['name'], group_snapshot['id']),
-                      [(m['name'], m['id']) for m in group_snapshots])
-
-        # Delete group snapshot
-        self._delete_group_snapshot(group_snapshot['id'], grp['id'])
-        group_snapshots = (self.group_snapshots_client.list_group_snapshots()
-                           ['group_snapshots'])
-        self.assertEmpty(group_snapshots)
-
-    @decorators.idempotent_id('eff52c70-efc7-45ed-b47a-4ad675d09b81')
-    def test_create_group_from_group_snapshot(self):
-        # Create volume type
-        volume_type = self.create_volume_type()
-
-        # Create group type
-        group_type = self.create_group_type()
-
-        # Create Group
-        grp = self._create_group(group_type, volume_type)
-
-        # Create volume
-        vol = self.create_volume(volume_type=volume_type['id'],
-                                 group_id=grp['id'])
-
-        # Create group_snapshot
-        group_snapshot_name = data_utils.rand_name('group_snapshot')
-        group_snapshot = (
-            self.group_snapshots_client.create_group_snapshot(
-                group_id=grp['id'],
-                name=group_snapshot_name)['group_snapshot'])
-        self.addCleanup(self._delete_group_snapshot,
-                        group_snapshot['id'], grp['id'])
-        self.assertEqual(group_snapshot_name, group_snapshot['name'])
-        snapshots = self.snapshots_client.list_snapshots(
-            detail=True)['snapshots']
-        for snap in snapshots:
-            if vol['id'] == snap['volume_id']:
-                waiters.wait_for_volume_resource_status(
-                    self.snapshots_client, snap['id'], 'available')
-        waiters.wait_for_volume_resource_status(
-            self.group_snapshots_client, group_snapshot['id'], 'available')
-
-        # Create Group from Group snapshot
-        grp_name2 = data_utils.rand_name('Group_from_snap')
-        grp2 = self.groups_client.create_group_from_source(
-            group_snapshot_id=group_snapshot['id'], name=grp_name2)['group']
-        self.addCleanup(self._delete_group, grp2['id'])
-        self.assertEqual(grp_name2, grp2['name'])
-        vols = self.volumes_client.list_volumes(detail=True)['volumes']
-        for vol in vols:
-            if vol['group_id'] == grp2['id']:
-                waiters.wait_for_volume_resource_status(
-                    self.volumes_client, vol['id'], 'available')
-        waiters.wait_for_volume_resource_status(
-            self.groups_client, grp2['id'], 'available')
-
-    @decorators.idempotent_id('2424af8c-7851-4888-986a-794b10c3210e')
-    def test_create_group_from_group(self):
-        # Create volume type
-        volume_type = self.create_volume_type()
-
-        # Create group type
-        group_type = self.create_group_type()
-
-        # Create Group
-        grp = self._create_group(group_type, volume_type)
-
-        # Create volume
-        self.create_volume(volume_type=volume_type['id'], group_id=grp['id'])
-
-        # Create Group from Group
-        grp_name2 = data_utils.rand_name('Group_from_grp')
-        grp2 = self.groups_client.create_group_from_source(
-            source_group_id=grp['id'], name=grp_name2)['group']
-        self.addCleanup(self._delete_group, grp2['id'])
-        self.assertEqual(grp_name2, grp2['name'])
-        vols = self.volumes_client.list_volumes(detail=True)['volumes']
-        for vol in vols:
-            if vol['group_id'] == grp2['id']:
-                waiters.wait_for_volume_resource_status(
-                    self.volumes_client, vol['id'], 'available')
-        waiters.wait_for_volume_resource_status(
-            self.groups_client, grp2['id'], 'available')
-
     @decorators.idempotent_id('4a8a6fd2-8b3b-4641-8f54-6a6f99320006')
     def test_group_update(self):
         # Create volume type
@@ -271,7 +102,8 @@
         group_type = self.create_group_type()
 
         # Create Group
-        grp = self._create_group(group_type, volume_type)
+        grp = self.create_group(group_type=group_type['id'],
+                                volume_types=[volume_type['id']])
 
         # Create volumes
         grp_vols = []
@@ -317,56 +149,42 @@
         self.assertEqual(2, len(grp_vols))
 
 
-class GroupsV319Test(BaseGroupsTest):
+class GroupsV314Test(base.BaseVolumeAdminTest):
     _api_version = 3
-    min_microversion = '3.19'
+    min_microversion = '3.14'
     max_microversion = 'latest'
 
-    @decorators.idempotent_id('3b42c9b9-c984-4444-816e-ca2e1ed30b40')
-    def test_reset_group_snapshot_status(self):
+    @decorators.idempotent_id('2424af8c-7851-4888-986a-794b10c3210e')
+    def test_create_group_from_group(self):
         # Create volume type
         volume_type = self.create_volume_type()
 
         # Create group type
         group_type = self.create_group_type()
 
-        # Create group
-        group = self._create_group(group_type, volume_type)
+        # Create Group
+        grp = self.create_group(group_type=group_type['id'],
+                                volume_types=[volume_type['id']])
 
         # Create volume
-        volume = self.create_volume(volume_type=volume_type['id'],
-                                    group_id=group['id'])
+        self.create_volume(volume_type=volume_type['id'], group_id=grp['id'])
 
-        # Create group snapshot
-        group_snapshot_name = data_utils.rand_name('group_snapshot')
-        group_snapshot = (self.group_snapshots_client.create_group_snapshot(
-            group_id=group['id'], name=group_snapshot_name)['group_snapshot'])
-        self.addCleanup(self._delete_group_snapshot,
-                        group_snapshot['id'], group['id'])
-        snapshots = self.snapshots_client.list_snapshots(
-            detail=True)['snapshots']
-        for snap in snapshots:
-            if volume['id'] == snap['volume_id']:
+        # Create Group from Group
+        grp_name2 = data_utils.rand_name('Group_from_grp')
+        grp2 = self.groups_client.create_group_from_source(
+            source_group_id=grp['id'], name=grp_name2)['group']
+        self.addCleanup(self.delete_group, grp2['id'])
+        self.assertEqual(grp_name2, grp2['name'])
+        vols = self.volumes_client.list_volumes(detail=True)['volumes']
+        for vol in vols:
+            if vol['group_id'] == grp2['id']:
                 waiters.wait_for_volume_resource_status(
-                    self.snapshots_client, snap['id'], 'available')
+                    self.volumes_client, vol['id'], 'available')
         waiters.wait_for_volume_resource_status(
-            self.group_snapshots_client, group_snapshot['id'], 'available')
-
-        # Reset group snapshot status
-        self.addCleanup(waiters.wait_for_volume_resource_status,
-                        self.group_snapshots_client,
-                        group_snapshot['id'], 'available')
-        self.addCleanup(
-            self.admin_group_snapshots_client.reset_group_snapshot_status,
-            group_snapshot['id'], 'available')
-        for status in ['creating', 'available', 'error']:
-            self.admin_group_snapshots_client.reset_group_snapshot_status(
-                group_snapshot['id'], status)
-            waiters.wait_for_volume_resource_status(
-                self.group_snapshots_client, group_snapshot['id'], status)
+            self.groups_client, grp2['id'], 'available')
 
 
-class GroupsV320Test(BaseGroupsTest):
+class GroupsV320Test(base.BaseVolumeAdminTest):
     _api_version = 3
     min_microversion = '3.20'
     max_microversion = 'latest'
@@ -380,7 +198,8 @@
         group_type = self.create_group_type()
 
         # Create group
-        group = self._create_group(group_type, volume_type)
+        group = self.create_group(group_type=group_type['id'],
+                                  volume_types=[volume_type['id']])
 
         # Reset group status
         self.addCleanup(waiters.wait_for_volume_resource_status,
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 63ef85b..ea3bb5a 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -242,6 +242,27 @@
                         self.servers_client.delete_server, body['id'])
         return body
 
+    def create_group(self, **kwargs):
+        if 'name' not in kwargs:
+            kwargs['name'] = data_utils.rand_name(
+                self.__class__.__name__ + '-Group')
+
+        group = self.groups_client.create_group(**kwargs)['group']
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.delete_group, group['id'])
+        waiters.wait_for_volume_resource_status(
+            self.groups_client, group['id'], 'available')
+        return group
+
+    def delete_group(self, group_id, delete_volumes=True):
+        self.groups_client.delete_group(group_id, delete_volumes)
+        if delete_volumes:
+            vols = self.volumes_client.list_volumes(detail=True)['volumes']
+            for vol in vols:
+                if vol['group_id'] == group_id:
+                    self.volumes_client.wait_for_resource_deletion(vol['id'])
+        self.groups_client.wait_for_resource_deletion(group_id)
+
 
 class BaseVolumeAdminTest(BaseVolumeTest):
     """Base test case class for all Volume Admin API tests."""