blob: 5d8d344398483df797121f0ab1102d45b13520b9 [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):
lkuchlan86f24322021-04-27 14:23:05 +030036 if resource_name == 'snapshot_access':
lkuchlanf7fc5b62021-01-26 14:53:43 +020037 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',
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]
lkuchlanf7fc5b62021-01-26 14:53:43 +020090 while resource_status not in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +020091 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +030092 body = resource_action(*method_args, **method_kwargs)[rn]
lkuchlanf7fc5b62021-01-26 14:53:43 +020093
lkuchlan86f24322021-04-27 14:23:05 +030094 if 'access' in resource_name:
lkuchlanf7fc5b62021-01-26 14:53:43 +020095 status_attr = 'state'
96 body = _get_access_rule(body, rule_id)
97
98 resource_status = body[status_attr]
99
100 if resource_status in exp_status:
lkuchlan540e74a2021-01-19 18:08:25 +0200101 return
lkuchlanf7fc5b62021-01-26 14:53:43 +0200102 elif 'error' in resource_status.lower() and raise_rule_in_error_state:
103 raise_method = _get_name_of_raise_method(resource_name)
104 resource_exception = getattr(share_exceptions, raise_method)
105 raise resource_exception(resource_id=resource_id)
lkuchlan540e74a2021-01-19 18:08:25 +0200106 if int(time.time()) - start >= client.build_timeout:
lkuchlanf7fc5b62021-01-26 14:53:43 +0200107 message = ('%s %s failed to reach %s status (current %s) '
lkuchlan540e74a2021-01-19 18:08:25 +0200108 'within the required time (%s s).' %
lkuchlanf7fc5b62021-01-26 14:53:43 +0200109 (resource_name.replace('_', ' '), resource_id, status,
110 resource_status, client.build_timeout))
lkuchlan540e74a2021-01-19 18:08:25 +0200111 raise exceptions.TimeoutException(message)
112
113
114def wait_for_migration_status(client, share_id, dest_host, status_to_wait,
115 version=LATEST_MICROVERSION):
116 """Waits for a share to migrate to a certain host."""
117 statuses = ((status_to_wait,)
118 if not isinstance(status_to_wait, (tuple, list, set))
119 else status_to_wait)
lkuchlan86f24322021-04-27 14:23:05 +0300120 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200121 migration_timeout = CONF.share.migration_timeout
122 start = int(time.time())
123 while share['task_state'] not in statuses:
124 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300125 share = client.get_share(share_id, version=version)['share']
lkuchlan540e74a2021-01-19 18:08:25 +0200126 if share['task_state'] in statuses:
127 break
128 elif share['task_state'] == 'migration_error':
129 raise share_exceptions.ShareMigrationException(
130 share_id=share['id'], src=share['host'], dest=dest_host)
131 elif int(time.time()) - start >= migration_timeout:
132 message = ('Share %(share_id)s failed to reach a status in'
133 '%(status)s when migrating from host %(src)s to '
134 'host %(dest)s within the required time '
135 '%(timeout)s.' % {
136 'src': share['host'],
137 'dest': dest_host,
138 'share_id': share['id'],
139 'timeout': client.build_timeout,
140 'status': six.text_type(statuses),
141 })
142 raise exceptions.TimeoutException(message)
143 return share
144
145
146def wait_for_snapshot_access_rule_deletion(client, snapshot_id, rule_id):
147 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
148 start = int(time.time())
149
150 while rule is not None:
151 time.sleep(client.build_interval)
152
153 rule = client.get_snapshot_access_rule(snapshot_id, rule_id)
154
155 if rule is None:
156 return
157 if int(time.time()) - start >= client.build_timeout:
158 message = ('The snapshot access rule %(id)s failed to delete '
159 'within the required time (%(time)ss).' %
160 {
161 'time': client.build_timeout,
162 'id': rule_id,
163 })
164 raise exceptions.TimeoutException(message)
165
166
167def wait_for_message(client, resource_id):
168 """Waits until a message for a resource with given id exists"""
169 start = int(time.time())
170 message = None
171
172 while not message:
173 time.sleep(client.build_interval)
lkuchlan86f24322021-04-27 14:23:05 +0300174 for msg in client.list_messages()['messages']:
lkuchlan540e74a2021-01-19 18:08:25 +0200175 if msg['resource_id'] == resource_id:
176 return msg
177
178 if int(time.time()) - start >= client.build_timeout:
179 message = ('No message for resource with id %s was created in'
180 ' the required time (%s s).' %
181 (resource_id, client.build_timeout))
182 raise exceptions.TimeoutException(message)