blob: a11b620d41ab812491bd47a1234c711aebbb4138 [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
lkuchlan540e74a2021-01-19 18:08:25 +020018from tempest import config
19from tempest.lib import exceptions
20
lkuchlan540e74a2021-01-19 18:08:25 +020021from manila_tempest_tests.services.share.v2.json import shares_client
22from manila_tempest_tests import share_exceptions
23
24CONF = config.CONF
25LATEST_MICROVERSION = CONF.share.max_api_microversion
26
27
lkuchlanf7fc5b62021-01-26 14:53:43 +020028def _get_access_rule(body, rule_id):
29 for rule in body:
30 if rule['id'] in rule_id:
31 return rule
lkuchlan540e74a2021-01-19 18:08:25 +020032
33
lkuchlanf7fc5b62021-01-26 14:53:43 +020034def _get_name_of_raise_method(resource_name):
lkuchlan86f24322021-04-27 14:23:05 +030035 if resource_name == 'snapshot_access':
lkuchlanf7fc5b62021-01-26 14:53:43 +020036 return 'AccessRuleBuildErrorException'
37 if resource_name == 'share_replica':
38 return 'ShareInstanceBuildErrorException'
39 resource_name = resource_name.title()
40 name = resource_name.replace('_', '')
41 return name + 'BuildErrorException'
42
43
44def wait_for_resource_status(client, resource_id, status,
45 resource_name='share', rule_id=None,
46 status_attr='status',
47 raise_rule_in_error_state=True,
agireesh541c6cd2023-10-17 14:57:32 +053048 version=LATEST_MICROVERSION,
49 timeout=None):
lkuchlanf7fc5b62021-01-26 14:53:43 +020050 """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',
lkuchlan86f24322021-04-27 14:23:05 +030059 'snapshot_access': 'list_snapshot_access_rules',
lkuchlanf7fc5b62021-01-26 14:53:43 +020060 'share_group': 'get_share_group',
61 'share_group_snapshot': 'get_share_group_snapshot',
62 'share_replica': 'get_share_replica',
Kiran Pawaredd82c72022-05-07 14:48:36 +000063 'share_backup': 'get_share_backup'
lkuchlanf7fc5b62021-01-26 14:53:43 +020064 }
65
lkuchlan86f24322021-04-27 14:23:05 +030066 action_name = get_resource_action[resource_name]
67 # This code snippet is intended to set the dictionary key of the returned
68 # response for share access rule and for snapshot access rule.
69 if 'access' in resource_name:
70 rn = '_'.join(action_name.split('_')[1:-1]) + '_list'
71 else:
72 rn = resource_name
73
lkuchlanf7fc5b62021-01-26 14:53:43 +020074 # Since API v2 requests require an additional parameter for micro-versions,
75 # it's necessary to pass the required parameters according to the version.
lkuchlan86f24322021-04-27 14:23:05 +030076 resource_action = getattr(client, action_name)
lkuchlanf7fc5b62021-01-26 14:53:43 +020077 method_args = [resource_id]
78 method_kwargs = {}
lkuchlan540e74a2021-01-19 18:08:25 +020079 if isinstance(client, shares_client.SharesV2Client):
lkuchlanf7fc5b62021-01-26 14:53:43 +020080 method_kwargs.update({'version': version})
lkuchlan86f24322021-04-27 14:23:05 +030081 body = resource_action(*method_args, **method_kwargs)[rn]
lkuchlanf7fc5b62021-01-26 14:53:43 +020082
lkuchlan86f24322021-04-27 14:23:05 +030083 if 'access' in resource_name:
lkuchlanf7fc5b62021-01-26 14:53:43 +020084 status_attr = 'state'
85 body = _get_access_rule(body, rule_id)
86
87 resource_status = body[status_attr]
lkuchlan540e74a2021-01-19 18:08:25 +020088 start = int(time.time())
89
90 exp_status = status if isinstance(status, list) else [status]
agireesh541c6cd2023-10-17 14:57:32 +053091 resource_status_check_time_out = client.build_timeout
92 if timeout is not None:
93 resource_status_check_time_out = timeout
lkuchlanf7fc5b62021-01-26 14:53:43 +020094 while resource_status not in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +020095 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +030096 body = resource_action(*method_args, **method_kwargs)[rn]
lkuchlanf7fc5b62021-01-26 14:53:43 +020097
lkuchlan86f24322021-04-27 14:23:05 +030098 if 'access' in resource_name:
lkuchlanf7fc5b62021-01-26 14:53:43 +020099 status_attr = 'state'
100 body = _get_access_rule(body, rule_id)
101
102 resource_status = body[status_attr]
103
104 if resource_status in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +0200105 return
lkuchlanf7fc5b62021-01-26 14:53:43 +0200106 elif 'error' in resource_status.lower() and raise_rule_in_error_state:
107 raise_method = _get_name_of_raise_method(resource_name)
108 resource_exception = getattr(share_exceptions, raise_method)
109 raise resource_exception(resource_id=resource_id)
agireesh541c6cd2023-10-17 14:57:32 +0530110 if int(time.time()) - start >= resource_status_check_time_out:
lkuchlanf7fc5b62021-01-26 14:53:43 +0200111 message = ('%s %s failed to reach %s status (current %s) '
lkuchlan540e74a2021-01-19 18:08:25 +0200112 'within the required time (%s s).' %
lkuchlanf7fc5b62021-01-26 14:53:43 +0200113 (resource_name.replace('_', ' '), resource_id, status,
agireesh541c6cd2023-10-17 14:57:32 +0530114 resource_status, resource_status_check_time_out))
lkuchlan540e74a2021-01-19 18:08:25 +0200115 raise exceptions.TimeoutException(message)
116
117
118def wait_for_migration_status(client, share_id, dest_host, status_to_wait,
119 version=LATEST_MICROVERSION):
120 """Waits for a share to migrate to a certain host."""
121 statuses = ((status_to_wait,)
122 if not isinstance(status_to_wait, (tuple, list, set))
123 else status_to_wait)
lkuchlan86f24322021-04-27 14:23:05 +0300124 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200125 migration_timeout = CONF.share.migration_timeout
126 start = int(time.time())
127 while share['task_state'] not in statuses:
128 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300129 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200130 if share['task_state'] in statuses:
131 break
132 elif share['task_state'] == 'migration_error':
133 raise share_exceptions.ShareMigrationException(
134 share_id=share['id'], src=share['host'], dest=dest_host)
135 elif int(time.time()) - start >= migration_timeout:
136 message = ('Share %(share_id)s failed to reach a status in'
137 '%(status)s when migrating from host %(src)s to '
138 'host %(dest)s within the required time '
139 '%(timeout)s.' % {
140 'src': share['host'],
141 'dest': dest_host,
142 'share_id': share['id'],
143 'timeout': client.build_timeout,
haixin48895812020-09-30 13:50:37 +0800144 'status': str(statuses),
lkuchlan540e74a2021-01-19 18:08:25 +0200145 })
146 raise exceptions.TimeoutException(message)
147 return share
148
149
150def wait_for_snapshot_access_rule_deletion(client, snapshot_id, rule_id):
151 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
152 start = int(time.time())
153
154 while rule is not None:
155 time.sleep(client.build_interval)
156
157 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
158
159 if rule is None:
160 return
161 if int(time.time()) - start >= client.build_timeout:
162 message = ('The snapshot access rule %(id)s failed to delete '
163 'within the required time (%(time)ss).' %
164 {
165 'time': client.build_timeout,
166 'id': rule_id,
167 })
168 raise exceptions.TimeoutException(message)
169
170
171def wait_for_message(client, resource_id):
172 """Waits until a message for a resource with given id exists"""
173 start = int(time.time())
174 message = None
175
176 while not message:
177 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300178 for msg in client.list_messages()['messages']:
lkuchlan540e74a2021-01-19 18:08:25 +0200179 if msg['resource_id'] == resource_id:
180 return msg
181
182 if int(time.time()) - start >= client.build_timeout:
183 message = ('No message for resource with id %s was created in'
184 ' the required time (%s s).' %
185 (resource_id, client.build_timeout))
186 raise exceptions.TimeoutException(message)
haixin1c5e68d2021-07-28 09:54:34 +0800187
188
189def wait_for_soft_delete(client, share_id, version=LATEST_MICROVERSION):
190 """Wait for a share soft delete to recycle bin."""
191 share = client.get_share(share_id, version=version)['share']
192 start = int(time.time())
193 while not share['is_soft_deleted']:
194 time.sleep(client.build_interval)
195 share = client.get_share(share_id, version=version)['share']
196 if share['is_soft_deleted']:
197 break
198 elif int(time.time()) - start >= client.build_timeout:
199 message = ('Share %(share_id)s failed to be soft deleted to '
200 'recycle bin within the required time '
201 '%(timeout)s.' % {
202 'share_id': share['id'],
203 'timeout': client.build_timeout,
204 })
205 raise exceptions.TimeoutException(message)
206
207
208def wait_for_restore(client, share_id, version=LATEST_MICROVERSION):
209 """Wait for a share restore from recycle bin."""
210 share = client.get_share(share_id, version=version)['share']
211 start = int(time.time())
212 while share['is_soft_deleted']:
213 time.sleep(client.build_interval)
214 share = client.get_share(share_id, version=version)['share']
215 if not share['is_soft_deleted']:
216 break
217 elif int(time.time()) - start >= client.build_timeout:
218 message = ('Share %(share_id)s failed to restore from '
219 'recycle bin within the required time '
220 '%(timeout)s.' % {
221 'share_id': share['id'],
222 'timeout': client.build_timeout,
223 })
224 raise exceptions.TimeoutException(message)
Andrec1a3c0e2022-01-29 14:46:53 +0000225
226
227def wait_for_subnet_create_check(client, share_network_id,
228 neutron_net_id=None,
229 neutron_subnet_id=None,
230 availability_zone=None):
231 result = client.subnet_create_check(
232 share_network_id, neutron_net_id=neutron_net_id,
233 neutron_subnet_id=neutron_subnet_id,
234 availability_zone=availability_zone)
235 start = int(time.time())
236 while not result['compatible']:
237 time.sleep(client.build_interval)
238 result = client.subnet_create_check(
239 share_network_id, neutron_net_id=neutron_net_id,
240 neutron_subnet_id=neutron_subnet_id,
241 availability_zone=availability_zone)
242 if result['compatible']:
243 break
244 elif int(time.time()) - start >= client.build_timeout or (
245 result['compatible'] is False):
246 message = ('Subnet create check failed within the '
247 'required time %(timeout)s seconds for share network '
248 '%(share_network)s.' % {
249 'timeout': client.build_timeout,
250 'share_network': share_network_id,
251 })
252 raise exceptions.TimeoutException(message)