blob: e5ac0e1f789ef6e81cd4f94433c41272328303bd [file] [log] [blame]
lkuchlan540e74a2021-01-19 18:08:25 +02001# Copyright 2021 Red Hat, Inc.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16import time
17
18import six
19from tempest import config
20from tempest.lib import exceptions
21
lkuchlan540e74a2021-01-19 18:08:25 +020022from manila_tempest_tests.services.share.v2.json import shares_client
23from manila_tempest_tests import share_exceptions
24
25CONF = config.CONF
26LATEST_MICROVERSION = CONF.share.max_api_microversion
27
28
lkuchlanf7fc5b62021-01-26 14:53:43 +020029def _get_access_rule(body, rule_id):
30 for rule in body:
31 if rule['id'] in rule_id:
32 return rule
lkuchlan540e74a2021-01-19 18:08:25 +020033
34
lkuchlanf7fc5b62021-01-26 14:53:43 +020035def _get_name_of_raise_method(resource_name):
36 if resource_name == 'snapshot_access_rule':
37 return 'AccessRuleBuildErrorException'
38 if resource_name == 'share_replica':
39 return 'ShareInstanceBuildErrorException'
40 resource_name = resource_name.title()
41 name = resource_name.replace('_', '')
42 return name + 'BuildErrorException'
43
44
45def wait_for_resource_status(client, resource_id, status,
46 resource_name='share', rule_id=None,
47 status_attr='status',
48 raise_rule_in_error_state=True,
49 version=LATEST_MICROVERSION):
50 """Waits for a resource to reach a given status."""
51
52 get_resource_action = {
53 'share': 'get_share',
54 'snapshot': 'get_snapshot',
55 'share_server': 'show_share_server',
56 'share_instance': 'get_share_instance',
57 'snapshot_instance': 'get_snapshot_instance',
58 'access_rule': 'list_access_rules',
59 'snapshot_access_rule': 'get_snapshot_access_rule',
60 'share_group': 'get_share_group',
61 'share_group_snapshot': 'get_share_group_snapshot',
62 'share_replica': 'get_share_replica',
63 }
64
65 # Since API v2 requests require an additional parameter for micro-versions,
66 # it's necessary to pass the required parameters according to the version.
67 resource_action = getattr(client, get_resource_action[resource_name])
68 method_args = [resource_id]
69 method_kwargs = {}
lkuchlan540e74a2021-01-19 18:08:25 +020070 if isinstance(client, shares_client.SharesV2Client):
lkuchlanf7fc5b62021-01-26 14:53:43 +020071 method_kwargs.update({'version': version})
72 if resource_name == 'snapshot_access_rule':
73 method_args.insert(1, rule_id)
74 body = resource_action(*method_args, **method_kwargs)
75
76 if resource_name == 'access_rule':
77 status_attr = 'state'
78 body = _get_access_rule(body, rule_id)
79
80 resource_status = body[status_attr]
lkuchlan540e74a2021-01-19 18:08:25 +020081 start = int(time.time())
82
83 exp_status = status if isinstance(status, list) else [status]
lkuchlanf7fc5b62021-01-26 14:53:43 +020084 while resource_status not in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +020085 time.sleep(client.build_interval)
lkuchlanf7fc5b62021-01-26 14:53:43 +020086 body = resource_action(*method_args, **method_kwargs)
87
88 if resource_name == 'access_rule':
89 status_attr = 'state'
90 body = _get_access_rule(body, rule_id)
91
92 resource_status = body[status_attr]
93
94 if resource_status in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +020095 return
lkuchlanf7fc5b62021-01-26 14:53:43 +020096 elif 'error' in resource_status.lower() and raise_rule_in_error_state:
97 raise_method = _get_name_of_raise_method(resource_name)
98 resource_exception = getattr(share_exceptions, raise_method)
99 raise resource_exception(resource_id=resource_id)
lkuchlan540e74a2021-01-19 18:08:25 +0200100 if int(time.time()) - start >= client.build_timeout:
lkuchlanf7fc5b62021-01-26 14:53:43 +0200101 message = ('%s %s failed to reach %s status (current %s) '
lkuchlan540e74a2021-01-19 18:08:25 +0200102 'within the required time (%s s).' %
lkuchlanf7fc5b62021-01-26 14:53:43 +0200103 (resource_name.replace('_', ' '), resource_id, status,
104 resource_status, client.build_timeout))
lkuchlan540e74a2021-01-19 18:08:25 +0200105 raise exceptions.TimeoutException(message)
106
107
108def wait_for_migration_status(client, share_id, dest_host, status_to_wait,
109 version=LATEST_MICROVERSION):
110 """Waits for a share to migrate to a certain host."""
111 statuses = ((status_to_wait,)
112 if not isinstance(status_to_wait, (tuple, list, set))
113 else status_to_wait)
114 share = client.get_share(share_id, version=version)
115 migration_timeout = CONF.share.migration_timeout
116 start = int(time.time())
117 while share['task_state'] not in statuses:
118 time.sleep(client.build_interval)
119 share = client.get_share(share_id, version=version)
120 if share['task_state'] in statuses:
121 break
122 elif share['task_state'] == 'migration_error':
123 raise share_exceptions.ShareMigrationException(
124 share_id=share['id'], src=share['host'], dest=dest_host)
125 elif int(time.time()) - start >= migration_timeout:
126 message = ('Share %(share_id)s failed to reach a status in'
127 '%(status)s when migrating from host %(src)s to '
128 'host %(dest)s within the required time '
129 '%(timeout)s.' % {
130 'src': share['host'],
131 'dest': dest_host,
132 'share_id': share['id'],
133 'timeout': client.build_timeout,
134 'status': six.text_type(statuses),
135 })
136 raise exceptions.TimeoutException(message)
137 return share
138
139
140def wait_for_snapshot_access_rule_deletion(client, snapshot_id, rule_id):
141 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
142 start = int(time.time())
143
144 while rule is not None:
145 time.sleep(client.build_interval)
146
147 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
148
149 if rule is None:
150 return
151 if int(time.time()) - start >= client.build_timeout:
152 message = ('The snapshot access rule %(id)s failed to delete '
153 'within the required time (%(time)ss).' %
154 {
155 'time': client.build_timeout,
156 'id': rule_id,
157 })
158 raise exceptions.TimeoutException(message)
159
160
161def wait_for_message(client, resource_id):
162 """Waits until a message for a resource with given id exists"""
163 start = int(time.time())
164 message = None
165
166 while not message:
167 time.sleep(client.build_interval)
168 for msg in client.list_messages():
169 if msg['resource_id'] == resource_id:
170 return msg
171
172 if int(time.time()) - start >= client.build_timeout:
173 message = ('No message for resource with id %s was created in'
174 ' the required time (%s s).' %
175 (resource_id, client.build_timeout))
176 raise exceptions.TimeoutException(message)