blob: 11a02d35bd815fb707e04eaeca59094d79a4e12f [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',
63 }
64
lkuchlan86f24322021-04-27 14:23:05 +030065 action_name = get_resource_action[resource_name]
66 # This code snippet is intended to set the dictionary key of the returned
67 # response for share access rule and for snapshot access rule.
68 if 'access' in resource_name:
69 rn = '_'.join(action_name.split('_')[1:-1]) + '_list'
70 else:
71 rn = resource_name
72
lkuchlanf7fc5b62021-01-26 14:53:43 +020073 # Since API v2 requests require an additional parameter for micro-versions,
74 # it's necessary to pass the required parameters according to the version.
lkuchlan86f24322021-04-27 14:23:05 +030075 resource_action = getattr(client, action_name)
lkuchlanf7fc5b62021-01-26 14:53:43 +020076 method_args = [resource_id]
77 method_kwargs = {}
lkuchlan540e74a2021-01-19 18:08:25 +020078 if isinstance(client, shares_client.SharesV2Client):
lkuchlanf7fc5b62021-01-26 14:53:43 +020079 method_kwargs.update({'version': version})
lkuchlan86f24322021-04-27 14:23:05 +030080 body = resource_action(*method_args, **method_kwargs)[rn]
lkuchlanf7fc5b62021-01-26 14:53:43 +020081
lkuchlan86f24322021-04-27 14:23:05 +030082 if 'access' in resource_name:
lkuchlanf7fc5b62021-01-26 14:53:43 +020083 status_attr = 'state'
84 body = _get_access_rule(body, rule_id)
85
86 resource_status = body[status_attr]
lkuchlan540e74a2021-01-19 18:08:25 +020087 start = int(time.time())
88
89 exp_status = status if isinstance(status, list) else [status]
agireesh541c6cd2023-10-17 14:57:32 +053090 resource_status_check_time_out = client.build_timeout
91 if timeout is not None:
92 resource_status_check_time_out = timeout
lkuchlanf7fc5b62021-01-26 14:53:43 +020093 while resource_status not in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +020094 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +030095 body = resource_action(*method_args, **method_kwargs)[rn]
lkuchlanf7fc5b62021-01-26 14:53:43 +020096
lkuchlan86f24322021-04-27 14:23:05 +030097 if 'access' in resource_name:
lkuchlanf7fc5b62021-01-26 14:53:43 +020098 status_attr = 'state'
99 body = _get_access_rule(body, rule_id)
100
101 resource_status = body[status_attr]
102
103 if resource_status in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +0200104 return
lkuchlanf7fc5b62021-01-26 14:53:43 +0200105 elif 'error' in resource_status.lower() and raise_rule_in_error_state:
106 raise_method = _get_name_of_raise_method(resource_name)
107 resource_exception = getattr(share_exceptions, raise_method)
108 raise resource_exception(resource_id=resource_id)
agireesh541c6cd2023-10-17 14:57:32 +0530109 if int(time.time()) - start >= resource_status_check_time_out:
lkuchlanf7fc5b62021-01-26 14:53:43 +0200110 message = ('%s %s failed to reach %s status (current %s) '
lkuchlan540e74a2021-01-19 18:08:25 +0200111 'within the required time (%s s).' %
lkuchlanf7fc5b62021-01-26 14:53:43 +0200112 (resource_name.replace('_', ' '), resource_id, status,
agireesh541c6cd2023-10-17 14:57:32 +0530113 resource_status, resource_status_check_time_out))
lkuchlan540e74a2021-01-19 18:08:25 +0200114 raise exceptions.TimeoutException(message)
115
116
117def wait_for_migration_status(client, share_id, dest_host, status_to_wait,
118 version=LATEST_MICROVERSION):
119 """Waits for a share to migrate to a certain host."""
120 statuses = ((status_to_wait,)
121 if not isinstance(status_to_wait, (tuple, list, set))
122 else status_to_wait)
lkuchlan86f24322021-04-27 14:23:05 +0300123 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200124 migration_timeout = CONF.share.migration_timeout
125 start = int(time.time())
126 while share['task_state'] not in statuses:
127 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300128 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200129 if share['task_state'] in statuses:
130 break
131 elif share['task_state'] == 'migration_error':
132 raise share_exceptions.ShareMigrationException(
133 share_id=share['id'], src=share['host'], dest=dest_host)
134 elif int(time.time()) - start >= migration_timeout:
135 message = ('Share %(share_id)s failed to reach a status in'
136 '%(status)s when migrating from host %(src)s to '
137 'host %(dest)s within the required time '
138 '%(timeout)s.' % {
139 'src': share['host'],
140 'dest': dest_host,
141 'share_id': share['id'],
142 'timeout': client.build_timeout,
haixin48895812020-09-30 13:50:37 +0800143 'status': str(statuses),
lkuchlan540e74a2021-01-19 18:08:25 +0200144 })
145 raise exceptions.TimeoutException(message)
146 return share
147
148
149def wait_for_snapshot_access_rule_deletion(client, snapshot_id, rule_id):
150 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
151 start = int(time.time())
152
153 while rule is not None:
154 time.sleep(client.build_interval)
155
156 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
157
158 if rule is None:
159 return
160 if int(time.time()) - start >= client.build_timeout:
161 message = ('The snapshot access rule %(id)s failed to delete '
162 'within the required time (%(time)ss).' %
163 {
164 'time': client.build_timeout,
165 'id': rule_id,
166 })
167 raise exceptions.TimeoutException(message)
168
169
170def wait_for_message(client, resource_id):
171 """Waits until a message for a resource with given id exists"""
172 start = int(time.time())
173 message = None
174
175 while not message:
176 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300177 for msg in client.list_messages()['messages']:
lkuchlan540e74a2021-01-19 18:08:25 +0200178 if msg['resource_id'] == resource_id:
179 return msg
180
181 if int(time.time()) - start >= client.build_timeout:
182 message = ('No message for resource with id %s was created in'
183 ' the required time (%s s).' %
184 (resource_id, client.build_timeout))
185 raise exceptions.TimeoutException(message)
haixin1c5e68d2021-07-28 09:54:34 +0800186
187
188def wait_for_soft_delete(client, share_id, version=LATEST_MICROVERSION):
189 """Wait for a share soft delete to recycle bin."""
190 share = client.get_share(share_id, version=version)['share']
191 start = int(time.time())
192 while not share['is_soft_deleted']:
193 time.sleep(client.build_interval)
194 share = client.get_share(share_id, version=version)['share']
195 if share['is_soft_deleted']:
196 break
197 elif int(time.time()) - start >= client.build_timeout:
198 message = ('Share %(share_id)s failed to be soft deleted to '
199 'recycle bin within the required time '
200 '%(timeout)s.' % {
201 'share_id': share['id'],
202 'timeout': client.build_timeout,
203 })
204 raise exceptions.TimeoutException(message)
205
206
207def wait_for_restore(client, share_id, version=LATEST_MICROVERSION):
208 """Wait for a share restore from recycle bin."""
209 share = client.get_share(share_id, version=version)['share']
210 start = int(time.time())
211 while share['is_soft_deleted']:
212 time.sleep(client.build_interval)
213 share = client.get_share(share_id, version=version)['share']
214 if not share['is_soft_deleted']:
215 break
216 elif int(time.time()) - start >= client.build_timeout:
217 message = ('Share %(share_id)s failed to restore from '
218 'recycle bin within the required time '
219 '%(timeout)s.' % {
220 'share_id': share['id'],
221 'timeout': client.build_timeout,
222 })
223 raise exceptions.TimeoutException(message)
Andrec1a3c0e2022-01-29 14:46:53 +0000224
225
226def wait_for_subnet_create_check(client, share_network_id,
227 neutron_net_id=None,
228 neutron_subnet_id=None,
229 availability_zone=None):
230 result = client.subnet_create_check(
231 share_network_id, neutron_net_id=neutron_net_id,
232 neutron_subnet_id=neutron_subnet_id,
233 availability_zone=availability_zone)
234 start = int(time.time())
235 while not result['compatible']:
236 time.sleep(client.build_interval)
237 result = client.subnet_create_check(
238 share_network_id, neutron_net_id=neutron_net_id,
239 neutron_subnet_id=neutron_subnet_id,
240 availability_zone=availability_zone)
241 if result['compatible']:
242 break
243 elif int(time.time()) - start >= client.build_timeout or (
244 result['compatible'] is False):
245 message = ('Subnet create check failed within the '
246 'required time %(timeout)s seconds for share network '
247 '%(share_network)s.' % {
248 'timeout': client.build_timeout,
249 'share_network': share_network_id,
250 })
251 raise exceptions.TimeoutException(message)