Consolidate waiters methods

Currently, for each resource there is a waiter method.
The code is almost the same in all waiter methods.
This patch suggests proposes to consolidate these methods.

Change-Id: I92f4628051731a9f7e05404b48a96d2ed27a855b
diff --git a/manila_tempest_tests/common/waiters.py b/manila_tempest_tests/common/waiters.py
index d3dbcb4..e5ac0e1 100644
--- a/manila_tempest_tests/common/waiters.py
+++ b/manila_tempest_tests/common/waiters.py
@@ -19,7 +19,6 @@
 from tempest import config
 from tempest.lib import exceptions
 
-from manila_tempest_tests.common import constants
 from manila_tempest_tests.services.share.v2.json import shares_client
 from manila_tempest_tests import share_exceptions
 
@@ -27,279 +26,82 @@
 LATEST_MICROVERSION = CONF.share.max_api_microversion
 
 
-def wait_for_share_instance_status(client, instance_id, status,
-                                   version=LATEST_MICROVERSION):
-    """Waits for a share to reach a given status."""
-    body = client.get_share_instance(instance_id, version=version)
-    instance_status = body['status']
-    start = int(time.time())
-
-    while instance_status != status:
-        time.sleep(client.build_interval)
-        body = client.get_share_instance(instance_id)
-        instance_status = body['status']
-        if instance_status == status:
-            return
-        elif 'error' in instance_status.lower():
-            raise share_exceptions.ShareInstanceBuildErrorException(
-                id=instance_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('Share instance %s failed to reach %s status within'
-                       ' the required time (%s s).' %
-                       (instance_id, status, client.build_timeout))
-            raise exceptions.TimeoutException(message)
+def _get_access_rule(body, rule_id):
+    for rule in body:
+        if rule['id'] in rule_id:
+            return rule
 
 
-def wait_for_share_status(client, share_id, status, status_attr='status',
-                          version=LATEST_MICROVERSION):
-    """Waits for a share to reach a given status."""
+def _get_name_of_raise_method(resource_name):
+    if resource_name == 'snapshot_access_rule':
+        return 'AccessRuleBuildErrorException'
+    if resource_name == 'share_replica':
+        return 'ShareInstanceBuildErrorException'
+    resource_name = resource_name.title()
+    name = resource_name.replace('_', '')
+    return name + 'BuildErrorException'
+
+
+def wait_for_resource_status(client, resource_id, status,
+                             resource_name='share', rule_id=None,
+                             status_attr='status',
+                             raise_rule_in_error_state=True,
+                             version=LATEST_MICROVERSION):
+    """Waits for a resource to reach a given status."""
+
+    get_resource_action = {
+        'share': 'get_share',
+        'snapshot': 'get_snapshot',
+        'share_server': 'show_share_server',
+        'share_instance': 'get_share_instance',
+        'snapshot_instance': 'get_snapshot_instance',
+        'access_rule': 'list_access_rules',
+        'snapshot_access_rule': 'get_snapshot_access_rule',
+        'share_group': 'get_share_group',
+        'share_group_snapshot': 'get_share_group_snapshot',
+        'share_replica': 'get_share_replica',
+    }
+
+    # Since API v2 requests require an additional parameter for micro-versions,
+    # it's necessary to pass the required parameters according to the version.
+    resource_action = getattr(client, get_resource_action[resource_name])
+    method_args = [resource_id]
+    method_kwargs = {}
     if isinstance(client, shares_client.SharesV2Client):
-        body = client.get_share(share_id, version=version)
-    else:
-        body = client.get_share(share_id)
-    share_status = body[status_attr]
+        method_kwargs.update({'version': version})
+        if resource_name == 'snapshot_access_rule':
+            method_args.insert(1, rule_id)
+    body = resource_action(*method_args, **method_kwargs)
+
+    if resource_name == 'access_rule':
+        status_attr = 'state'
+        body = _get_access_rule(body, rule_id)
+
+    resource_status = body[status_attr]
     start = int(time.time())
 
     exp_status = status if isinstance(status, list) else [status]
-    while share_status not in exp_status:
+    while resource_status not in exp_status:
         time.sleep(client.build_interval)
-        if isinstance(client, shares_client.SharesV2Client):
-            body = client.get_share(share_id, version=version)
-        else:
-            body = client.get_share(share_id)
-        share_status = body[status_attr]
-        if share_status in exp_status:
+        body = resource_action(*method_args, **method_kwargs)
+
+        if resource_name == 'access_rule':
+            status_attr = 'state'
+            body = _get_access_rule(body, rule_id)
+
+        resource_status = body[status_attr]
+
+        if resource_status in exp_status:
             return
-        elif 'error' in share_status.lower():
-            raise share_exceptions.ShareBuildErrorException(
-                share_id=share_id)
+        elif 'error' in resource_status.lower() and raise_rule_in_error_state:
+            raise_method = _get_name_of_raise_method(resource_name)
+            resource_exception = getattr(share_exceptions, raise_method)
+            raise resource_exception(resource_id=resource_id)
         if int(time.time()) - start >= client.build_timeout:
-            message = ("Share's %(status_attr)s failed to transition to "
-                       "%(status)s within the required "
-                       "time %(seconds)s." %
-                       {"status_attr": status_attr, "status": exp_status,
-                        "seconds": client.build_timeout})
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_snapshot_status(client, snapshot_id, status,
-                             version=LATEST_MICROVERSION):
-    """Waits for a snapshot to reach a given status."""
-    if isinstance(client, shares_client.SharesV2Client):
-        body = client.get_snapshot(snapshot_id, version=version)
-    else:
-        body = client.get_snapshot(snapshot_id)
-    snapshot_name = body['name']
-    snapshot_status = body['status']
-    start = int(time.time())
-
-    while snapshot_status != status:
-        time.sleep(client.build_interval)
-        if isinstance(client, shares_client.SharesV2Client):
-            body = client.get_snapshot(snapshot_id, version=version)
-        else:
-            body = client.get_snapshot(snapshot_id)
-        snapshot_status = body['status']
-        if snapshot_status in status:
-            return
-        if 'error' in snapshot_status:
-            raise (share_exceptions.
-                   SnapshotBuildErrorException(snapshot_id=snapshot_id))
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('Share Snapshot %s failed to reach %s status '
+            message = ('%s %s failed to reach %s status (current %s) '
                        'within the required time (%s s).' %
-                       (snapshot_name, status, client.build_timeout))
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_access_rule_status(client, share_id, rule_id, status,
-                                raise_rule_in_error_state=True):
-    """Waits for an access rule to reach a given status."""
-    rule_status = "new"
-    start = int(time.time())
-    while rule_status != status:
-        time.sleep(client.build_interval)
-        rules = client.list_access_rules(share_id)
-        for rule in rules:
-            if rule["id"] in rule_id:
-                rule_status = rule['state']
-                break
-        if 'error' in rule_status and raise_rule_in_error_state:
-            raise share_exceptions.AccessRuleBuildErrorException(
-                rule_id=rule_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('Share Access Rule %s failed to reach %s status '
-                       'within the required time (%s s).' %
-                       (rule_id, status, client.build_timeout))
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_snapshot_instance_status(client, instance_id, expected_status):
-    """Waits for a snapshot instance status to reach a given status."""
-    body = client.get_snapshot_instance(instance_id)
-    instance_status = body['status']
-    start = int(time.time())
-
-    while instance_status != expected_status:
-        time.sleep(client.build_interval)
-        body = client.get_snapshot_instance(instance_id)
-        instance_status = body['status']
-        if instance_status == expected_status:
-            return
-        if 'error' in instance_status:
-            raise share_exceptions.SnapshotInstanceBuildErrorException(
-                id=instance_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('The status of snapshot instance %(id)s failed to '
-                       'reach %(expected_status)s status within the '
-                       'required time (%(time)ss). Current '
-                       'status: %(current_status)s.' %
-                       {
-                           'expected_status': expected_status,
-                           'time': client.build_timeout,
-                           'id': instance_id,
-                           'current_status': instance_status,
-                       })
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_share_group_status(client, share_group_id, status):
-    """Waits for a share group to reach a given status."""
-    body = client.get_share_group(share_group_id)
-    sg_name = body['name']
-    sg_status = body['status']
-    start = int(time.time())
-
-    while sg_status != status:
-        time.sleep(client.build_interval)
-        body = client.get_share_group(share_group_id)
-        sg_status = body['status']
-        if 'error' in sg_status and status != 'error':
-            raise share_exceptions.ShareGroupBuildErrorException(
-                share_group_id=share_group_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            sg_name = sg_name or share_group_id
-            message = ('Share Group %s failed to reach %s status '
-                       'within the required time (%s s). '
-                       'Current status: %s' %
-                       (sg_name, status, client.build_timeout, sg_status))
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_share_group_snapshot_status(client, share_group_snapshot_id,
-                                         status):
-    """Waits for a share group snapshot to reach a given status."""
-    body = client.get_share_group_snapshot(share_group_snapshot_id)
-    sg_snapshot_name = body['name']
-    sg_snapshot_status = body['status']
-    start = int(time.time())
-
-    while sg_snapshot_status != status:
-        time.sleep(client.build_interval)
-        body = client.get_share_group_snapshot(share_group_snapshot_id)
-        sg_snapshot_status = body['status']
-        if 'error' in sg_snapshot_status and status != 'error':
-            raise share_exceptions.ShareGroupSnapshotBuildErrorException(
-                share_group_snapshot_id=share_group_snapshot_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('Share Group Snapshot %s failed to reach %s status '
-                       'within the required time (%s s).' %
-                       (sg_snapshot_name, status, client.build_timeout))
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_share_server_status(client, server_id, status,
-                                 status_attr='status'):
-    """Waits for a share to reach a given status."""
-    body = client.show_share_server(server_id)
-    server_status = body[status_attr]
-    start = int(time.time())
-
-    while server_status != status:
-        time.sleep(client.build_interval)
-        body = client.show_share_server(server_id)
-        server_status = body[status_attr]
-        if server_status in status:
-            return
-        elif constants.STATUS_ERROR in server_status.lower():
-            raise share_exceptions.ShareServerBuildErrorException(
-                server_id=server_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ("Share server's %(status_attr)s failed to "
-                       "transition to %(status)s within the required "
-                       "time %(seconds)s." %
-                       {"status_attr": status_attr, "status": status,
-                        "seconds": client.build_timeout})
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_share_replica_status(client, replica_id, expected_status,
-                                  status_attr='status'):
-    """Waits for a replica's status_attr to reach a given status."""
-    body = client.get_share_replica(replica_id)
-    replica_status = body[status_attr]
-    start = int(time.time())
-
-    while replica_status != expected_status:
-        time.sleep(client.build_interval)
-        body = client.get_share_replica(replica_id)
-        replica_status = body[status_attr]
-        if replica_status == expected_status:
-            return
-        if ('error' in replica_status
-                and expected_status != constants.STATUS_ERROR):
-            raise share_exceptions.ShareInstanceBuildErrorException(
-                id=replica_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('The %(status_attr)s of Replica %(id)s failed to '
-                       'reach %(expected_status)s status within the '
-                       'required time (%(time)ss). Current '
-                       '%(status_attr)s: %(current_status)s.' %
-                       {
-                           'status_attr': status_attr,
-                           'expected_status': expected_status,
-                           'time': client.build_timeout,
-                           'id': replica_id,
-                           'current_status': replica_status,
-                       })
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_snapshot_access_rule_status(client, snapshot_id, rule_id,
-                                         expected_state='active'):
-    rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
-    state = rule['state']
-    start = int(time.time())
-
-    while state != expected_state:
-        time.sleep(client.build_interval)
-        rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
-        state = rule['state']
-        if state == expected_state:
-            return
-        if 'error' in state:
-            raise share_exceptions.AccessRuleBuildErrorException(
-                snapshot_id)
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('The status of snapshot access rule %(id)s failed '
-                       'to reach %(expected_state)s state within the '
-                       'required time (%(time)ss). Current '
-                       'state: %(current_state)s.' %
-                       {
-                           'expected_state': expected_state,
-                           'time': client.build_timeout,
-                           'id': rule_id,
-                           'current_state': state,
-                       })
+                       (resource_name.replace('_', ' '), resource_id, status,
+                        resource_status, client.build_timeout))
             raise exceptions.TimeoutException(message)