blob: 8a97c8eeda003a0182f06b11a097fc84a12cb332 [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,
48 version=LATEST_MICROVERSION):
49 """Waits for a resource to reach a given status."""
50
51 get_resource_action = {
52 'share': 'get_share',
53 'snapshot': 'get_snapshot',
54 'share_server': 'show_share_server',
55 'share_instance': 'get_share_instance',
56 'snapshot_instance': 'get_snapshot_instance',
57 'access_rule': 'list_access_rules',
lkuchlan86f24322021-04-27 14:23:05 +030058 'snapshot_access': 'list_snapshot_access_rules',
lkuchlanf7fc5b62021-01-26 14:53:43 +020059 'share_group': 'get_share_group',
60 'share_group_snapshot': 'get_share_group_snapshot',
61 'share_replica': 'get_share_replica',
62 }
63
lkuchlan86f24322021-04-27 14:23:05 +030064 action_name = get_resource_action[resource_name]
65 # This code snippet is intended to set the dictionary key of the returned
66 # response for share access rule and for snapshot access rule.
67 if 'access' in resource_name:
68 rn = '_'.join(action_name.split('_')[1:-1]) + '_list'
69 else:
70 rn = resource_name
71
lkuchlanf7fc5b62021-01-26 14:53:43 +020072 # Since API v2 requests require an additional parameter for micro-versions,
73 # it's necessary to pass the required parameters according to the version.
lkuchlan86f24322021-04-27 14:23:05 +030074 resource_action = getattr(client, action_name)
lkuchlanf7fc5b62021-01-26 14:53:43 +020075 method_args = [resource_id]
76 method_kwargs = {}
lkuchlan540e74a2021-01-19 18:08:25 +020077 if isinstance(client, shares_client.SharesV2Client):
lkuchlanf7fc5b62021-01-26 14:53:43 +020078 method_kwargs.update({'version': version})
lkuchlan86f24322021-04-27 14:23:05 +030079 body = resource_action(*method_args, **method_kwargs)[rn]
lkuchlanf7fc5b62021-01-26 14:53:43 +020080
lkuchlan86f24322021-04-27 14:23:05 +030081 if 'access' in resource_name:
lkuchlanf7fc5b62021-01-26 14:53:43 +020082 status_attr = 'state'
83 body = _get_access_rule(body, rule_id)
84
85 resource_status = body[status_attr]
lkuchlan540e74a2021-01-19 18:08:25 +020086 start = int(time.time())
87
88 exp_status = status if isinstance(status, list) else [status]
lkuchlanf7fc5b62021-01-26 14:53:43 +020089 while resource_status not in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +020090 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +030091 body = resource_action(*method_args, **method_kwargs)[rn]
lkuchlanf7fc5b62021-01-26 14:53:43 +020092
lkuchlan86f24322021-04-27 14:23:05 +030093 if 'access' in resource_name:
lkuchlanf7fc5b62021-01-26 14:53:43 +020094 status_attr = 'state'
95 body = _get_access_rule(body, rule_id)
96
97 resource_status = body[status_attr]
98
99 if resource_status in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +0200100 return
lkuchlanf7fc5b62021-01-26 14:53:43 +0200101 elif 'error' in resource_status.lower() and raise_rule_in_error_state:
102 raise_method = _get_name_of_raise_method(resource_name)
103 resource_exception = getattr(share_exceptions, raise_method)
104 raise resource_exception(resource_id=resource_id)
lkuchlan540e74a2021-01-19 18:08:25 +0200105 if int(time.time()) - start >= client.build_timeout:
lkuchlanf7fc5b62021-01-26 14:53:43 +0200106 message = ('%s %s failed to reach %s status (current %s) '
lkuchlan540e74a2021-01-19 18:08:25 +0200107 'within the required time (%s s).' %
lkuchlanf7fc5b62021-01-26 14:53:43 +0200108 (resource_name.replace('_', ' '), resource_id, status,
109 resource_status, client.build_timeout))
lkuchlan540e74a2021-01-19 18:08:25 +0200110 raise exceptions.TimeoutException(message)
111
112
113def wait_for_migration_status(client, share_id, dest_host, status_to_wait,
114 version=LATEST_MICROVERSION):
115 """Waits for a share to migrate to a certain host."""
116 statuses = ((status_to_wait,)
117 if not isinstance(status_to_wait, (tuple, list, set))
118 else status_to_wait)
lkuchlan86f24322021-04-27 14:23:05 +0300119 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200120 migration_timeout = CONF.share.migration_timeout
121 start = int(time.time())
122 while share['task_state'] not in statuses:
123 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300124 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200125 if share['task_state'] in statuses:
126 break
127 elif share['task_state'] == 'migration_error':
128 raise share_exceptions.ShareMigrationException(
129 share_id=share['id'], src=share['host'], dest=dest_host)
130 elif int(time.time()) - start >= migration_timeout:
131 message = ('Share %(share_id)s failed to reach a status in'
132 '%(status)s when migrating from host %(src)s to '
133 'host %(dest)s within the required time '
134 '%(timeout)s.' % {
135 'src': share['host'],
136 'dest': dest_host,
137 'share_id': share['id'],
138 'timeout': client.build_timeout,
haixin48895812020-09-30 13:50:37 +0800139 'status': str(statuses),
lkuchlan540e74a2021-01-19 18:08:25 +0200140 })
141 raise exceptions.TimeoutException(message)
142 return share
143
144
145def wait_for_snapshot_access_rule_deletion(client, snapshot_id, rule_id):
146 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
147 start = int(time.time())
148
149 while rule is not None:
150 time.sleep(client.build_interval)
151
152 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
153
154 if rule is None:
155 return
156 if int(time.time()) - start >= client.build_timeout:
157 message = ('The snapshot access rule %(id)s failed to delete '
158 'within the required time (%(time)ss).' %
159 {
160 'time': client.build_timeout,
161 'id': rule_id,
162 })
163 raise exceptions.TimeoutException(message)
164
165
166def wait_for_message(client, resource_id):
167 """Waits until a message for a resource with given id exists"""
168 start = int(time.time())
169 message = None
170
171 while not message:
172 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300173 for msg in client.list_messages()['messages']:
lkuchlan540e74a2021-01-19 18:08:25 +0200174 if msg['resource_id'] == resource_id:
175 return msg
176
177 if int(time.time()) - start >= client.build_timeout:
178 message = ('No message for resource with id %s was created in'
179 ' the required time (%s s).' %
180 (resource_id, client.build_timeout))
181 raise exceptions.TimeoutException(message)
haixin1c5e68d2021-07-28 09:54:34 +0800182
183
184def wait_for_soft_delete(client, share_id, version=LATEST_MICROVERSION):
185 """Wait for a share soft delete to recycle bin."""
186 share = client.get_share(share_id, version=version)['share']
187 start = int(time.time())
188 while not share['is_soft_deleted']:
189 time.sleep(client.build_interval)
190 share = client.get_share(share_id, version=version)['share']
191 if share['is_soft_deleted']:
192 break
193 elif int(time.time()) - start >= client.build_timeout:
194 message = ('Share %(share_id)s failed to be soft deleted to '
195 'recycle bin within the required time '
196 '%(timeout)s.' % {
197 'share_id': share['id'],
198 'timeout': client.build_timeout,
199 })
200 raise exceptions.TimeoutException(message)
201
202
203def wait_for_restore(client, share_id, version=LATEST_MICROVERSION):
204 """Wait for a share restore from recycle bin."""
205 share = client.get_share(share_id, version=version)['share']
206 start = int(time.time())
207 while share['is_soft_deleted']:
208 time.sleep(client.build_interval)
209 share = client.get_share(share_id, version=version)['share']
210 if not share['is_soft_deleted']:
211 break
212 elif int(time.time()) - start >= client.build_timeout:
213 message = ('Share %(share_id)s failed to restore from '
214 'recycle bin within the required time '
215 '%(timeout)s.' % {
216 'share_id': share['id'],
217 'timeout': client.build_timeout,
218 })
219 raise exceptions.TimeoutException(message)
Andrec1a3c0e2022-01-29 14:46:53 +0000220
221
222def wait_for_subnet_create_check(client, share_network_id,
223 neutron_net_id=None,
224 neutron_subnet_id=None,
225 availability_zone=None):
226 result = client.subnet_create_check(
227 share_network_id, neutron_net_id=neutron_net_id,
228 neutron_subnet_id=neutron_subnet_id,
229 availability_zone=availability_zone)
230 start = int(time.time())
231 while not result['compatible']:
232 time.sleep(client.build_interval)
233 result = client.subnet_create_check(
234 share_network_id, neutron_net_id=neutron_net_id,
235 neutron_subnet_id=neutron_subnet_id,
236 availability_zone=availability_zone)
237 if result['compatible']:
238 break
239 elif int(time.time()) - start >= client.build_timeout or (
240 result['compatible'] is False):
241 message = ('Subnet create check failed within the '
242 'required time %(timeout)s seconds for share network '
243 '%(share_network)s.' % {
244 'timeout': client.build_timeout,
245 'share_network': share_network_id,
246 })
247 raise exceptions.TimeoutException(message)