lkuchlan | 540e74a | 2021-01-19 18:08:25 +0200 | [diff] [blame] | 1 | # 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 | |
| 16 | import time |
| 17 | |
| 18 | import six |
| 19 | from tempest import config |
| 20 | from tempest.lib import exceptions |
| 21 | |
| 22 | from manila_tempest_tests.common import constants |
| 23 | from manila_tempest_tests.services.share.v2.json import shares_client |
| 24 | from manila_tempest_tests import share_exceptions |
| 25 | |
| 26 | CONF = config.CONF |
| 27 | LATEST_MICROVERSION = CONF.share.max_api_microversion |
| 28 | |
| 29 | |
| 30 | def wait_for_share_instance_status(client, instance_id, status, |
| 31 | version=LATEST_MICROVERSION): |
| 32 | """Waits for a share to reach a given status.""" |
| 33 | body = client.get_share_instance(instance_id, version=version) |
| 34 | instance_status = body['status'] |
| 35 | start = int(time.time()) |
| 36 | |
| 37 | while instance_status != status: |
| 38 | time.sleep(client.build_interval) |
| 39 | body = client.get_share_instance(instance_id) |
| 40 | instance_status = body['status'] |
| 41 | if instance_status == status: |
| 42 | return |
| 43 | elif 'error' in instance_status.lower(): |
| 44 | raise share_exceptions.ShareInstanceBuildErrorException( |
| 45 | id=instance_id) |
| 46 | |
| 47 | if int(time.time()) - start >= client.build_timeout: |
| 48 | message = ('Share instance %s failed to reach %s status within' |
| 49 | ' the required time (%s s).' % |
| 50 | (instance_id, status, client.build_timeout)) |
| 51 | raise exceptions.TimeoutException(message) |
| 52 | |
| 53 | |
| 54 | def wait_for_share_status(client, share_id, status, status_attr='status', |
| 55 | version=LATEST_MICROVERSION): |
| 56 | """Waits for a share to reach a given status.""" |
| 57 | if isinstance(client, shares_client.SharesV2Client): |
| 58 | body = client.get_share(share_id, version=version) |
| 59 | else: |
| 60 | body = client.get_share(share_id) |
| 61 | share_status = body[status_attr] |
| 62 | start = int(time.time()) |
| 63 | |
| 64 | exp_status = status if isinstance(status, list) else [status] |
| 65 | while share_status not in exp_status: |
| 66 | time.sleep(client.build_interval) |
| 67 | if isinstance(client, shares_client.SharesV2Client): |
| 68 | body = client.get_share(share_id, version=version) |
| 69 | else: |
| 70 | body = client.get_share(share_id) |
| 71 | share_status = body[status_attr] |
| 72 | if share_status in exp_status: |
| 73 | return |
| 74 | elif 'error' in share_status.lower(): |
| 75 | raise share_exceptions.ShareBuildErrorException( |
| 76 | share_id=share_id) |
| 77 | if int(time.time()) - start >= client.build_timeout: |
| 78 | message = ("Share's %(status_attr)s failed to transition to " |
| 79 | "%(status)s within the required " |
| 80 | "time %(seconds)s." % |
| 81 | {"status_attr": status_attr, "status": exp_status, |
| 82 | "seconds": client.build_timeout}) |
| 83 | raise exceptions.TimeoutException(message) |
| 84 | |
| 85 | |
| 86 | def wait_for_snapshot_status(client, snapshot_id, status, |
| 87 | version=LATEST_MICROVERSION): |
| 88 | """Waits for a snapshot to reach a given status.""" |
| 89 | if isinstance(client, shares_client.SharesV2Client): |
| 90 | body = client.get_snapshot(snapshot_id, version=version) |
| 91 | else: |
| 92 | body = client.get_snapshot(snapshot_id) |
| 93 | snapshot_name = body['name'] |
| 94 | snapshot_status = body['status'] |
| 95 | start = int(time.time()) |
| 96 | |
| 97 | while snapshot_status != status: |
| 98 | time.sleep(client.build_interval) |
| 99 | if isinstance(client, shares_client.SharesV2Client): |
| 100 | body = client.get_snapshot(snapshot_id, version=version) |
| 101 | else: |
| 102 | body = client.get_snapshot(snapshot_id) |
| 103 | snapshot_status = body['status'] |
| 104 | if snapshot_status in status: |
| 105 | return |
| 106 | if 'error' in snapshot_status: |
| 107 | raise (share_exceptions. |
| 108 | SnapshotBuildErrorException(snapshot_id=snapshot_id)) |
| 109 | |
| 110 | if int(time.time()) - start >= client.build_timeout: |
| 111 | message = ('Share Snapshot %s failed to reach %s status ' |
| 112 | 'within the required time (%s s).' % |
| 113 | (snapshot_name, status, client.build_timeout)) |
| 114 | raise exceptions.TimeoutException(message) |
| 115 | |
| 116 | |
| 117 | def wait_for_access_rule_status(client, share_id, rule_id, status, |
| 118 | raise_rule_in_error_state=True): |
| 119 | """Waits for an access rule to reach a given status.""" |
| 120 | rule_status = "new" |
| 121 | start = int(time.time()) |
| 122 | while rule_status != status: |
| 123 | time.sleep(client.build_interval) |
| 124 | rules = client.list_access_rules(share_id) |
| 125 | for rule in rules: |
| 126 | if rule["id"] in rule_id: |
| 127 | rule_status = rule['state'] |
| 128 | break |
| 129 | if 'error' in rule_status and raise_rule_in_error_state: |
| 130 | raise share_exceptions.AccessRuleBuildErrorException( |
| 131 | rule_id=rule_id) |
| 132 | |
| 133 | if int(time.time()) - start >= client.build_timeout: |
| 134 | message = ('Share Access Rule %s failed to reach %s status ' |
| 135 | 'within the required time (%s s).' % |
| 136 | (rule_id, status, client.build_timeout)) |
| 137 | raise exceptions.TimeoutException(message) |
| 138 | |
| 139 | |
| 140 | def wait_for_snapshot_instance_status(client, instance_id, expected_status): |
| 141 | """Waits for a snapshot instance status to reach a given status.""" |
| 142 | body = client.get_snapshot_instance(instance_id) |
| 143 | instance_status = body['status'] |
| 144 | start = int(time.time()) |
| 145 | |
| 146 | while instance_status != expected_status: |
| 147 | time.sleep(client.build_interval) |
| 148 | body = client.get_snapshot_instance(instance_id) |
| 149 | instance_status = body['status'] |
| 150 | if instance_status == expected_status: |
| 151 | return |
| 152 | if 'error' in instance_status: |
| 153 | raise share_exceptions.SnapshotInstanceBuildErrorException( |
| 154 | id=instance_id) |
| 155 | |
| 156 | if int(time.time()) - start >= client.build_timeout: |
| 157 | message = ('The status of snapshot instance %(id)s failed to ' |
| 158 | 'reach %(expected_status)s status within the ' |
| 159 | 'required time (%(time)ss). Current ' |
| 160 | 'status: %(current_status)s.' % |
| 161 | { |
| 162 | 'expected_status': expected_status, |
| 163 | 'time': client.build_timeout, |
| 164 | 'id': instance_id, |
| 165 | 'current_status': instance_status, |
| 166 | }) |
| 167 | raise exceptions.TimeoutException(message) |
| 168 | |
| 169 | |
| 170 | def wait_for_share_group_status(client, share_group_id, status): |
| 171 | """Waits for a share group to reach a given status.""" |
| 172 | body = client.get_share_group(share_group_id) |
| 173 | sg_name = body['name'] |
| 174 | sg_status = body['status'] |
| 175 | start = int(time.time()) |
| 176 | |
| 177 | while sg_status != status: |
| 178 | time.sleep(client.build_interval) |
| 179 | body = client.get_share_group(share_group_id) |
| 180 | sg_status = body['status'] |
| 181 | if 'error' in sg_status and status != 'error': |
| 182 | raise share_exceptions.ShareGroupBuildErrorException( |
| 183 | share_group_id=share_group_id) |
| 184 | |
| 185 | if int(time.time()) - start >= client.build_timeout: |
| 186 | sg_name = sg_name or share_group_id |
| 187 | message = ('Share Group %s failed to reach %s status ' |
| 188 | 'within the required time (%s s). ' |
| 189 | 'Current status: %s' % |
| 190 | (sg_name, status, client.build_timeout, sg_status)) |
| 191 | raise exceptions.TimeoutException(message) |
| 192 | |
| 193 | |
| 194 | def wait_for_share_group_snapshot_status(client, share_group_snapshot_id, |
| 195 | status): |
| 196 | """Waits for a share group snapshot to reach a given status.""" |
| 197 | body = client.get_share_group_snapshot(share_group_snapshot_id) |
| 198 | sg_snapshot_name = body['name'] |
| 199 | sg_snapshot_status = body['status'] |
| 200 | start = int(time.time()) |
| 201 | |
| 202 | while sg_snapshot_status != status: |
| 203 | time.sleep(client.build_interval) |
| 204 | body = client.get_share_group_snapshot(share_group_snapshot_id) |
| 205 | sg_snapshot_status = body['status'] |
| 206 | if 'error' in sg_snapshot_status and status != 'error': |
| 207 | raise share_exceptions.ShareGroupSnapshotBuildErrorException( |
| 208 | share_group_snapshot_id=share_group_snapshot_id) |
| 209 | |
| 210 | if int(time.time()) - start >= client.build_timeout: |
| 211 | message = ('Share Group Snapshot %s failed to reach %s status ' |
| 212 | 'within the required time (%s s).' % |
| 213 | (sg_snapshot_name, status, client.build_timeout)) |
| 214 | raise exceptions.TimeoutException(message) |
| 215 | |
| 216 | |
| 217 | def wait_for_share_server_status(client, server_id, status, |
| 218 | status_attr='status'): |
| 219 | """Waits for a share to reach a given status.""" |
| 220 | body = client.show_share_server(server_id) |
| 221 | server_status = body[status_attr] |
| 222 | start = int(time.time()) |
| 223 | |
| 224 | while server_status != status: |
| 225 | time.sleep(client.build_interval) |
| 226 | body = client.show_share_server(server_id) |
| 227 | server_status = body[status_attr] |
| 228 | if server_status in status: |
| 229 | return |
| 230 | elif constants.STATUS_ERROR in server_status.lower(): |
| 231 | raise share_exceptions.ShareServerBuildErrorException( |
| 232 | server_id=server_id) |
| 233 | |
| 234 | if int(time.time()) - start >= client.build_timeout: |
| 235 | message = ("Share server's %(status_attr)s failed to " |
| 236 | "transition to %(status)s within the required " |
| 237 | "time %(seconds)s." % |
| 238 | {"status_attr": status_attr, "status": status, |
| 239 | "seconds": client.build_timeout}) |
| 240 | raise exceptions.TimeoutException(message) |
| 241 | |
| 242 | |
| 243 | def wait_for_share_replica_status(client, replica_id, expected_status, |
| 244 | status_attr='status'): |
| 245 | """Waits for a replica's status_attr to reach a given status.""" |
| 246 | body = client.get_share_replica(replica_id) |
| 247 | replica_status = body[status_attr] |
| 248 | start = int(time.time()) |
| 249 | |
| 250 | while replica_status != expected_status: |
| 251 | time.sleep(client.build_interval) |
| 252 | body = client.get_share_replica(replica_id) |
| 253 | replica_status = body[status_attr] |
| 254 | if replica_status == expected_status: |
| 255 | return |
| 256 | if ('error' in replica_status |
| 257 | and expected_status != constants.STATUS_ERROR): |
| 258 | raise share_exceptions.ShareInstanceBuildErrorException( |
| 259 | id=replica_id) |
| 260 | |
| 261 | if int(time.time()) - start >= client.build_timeout: |
| 262 | message = ('The %(status_attr)s of Replica %(id)s failed to ' |
| 263 | 'reach %(expected_status)s status within the ' |
| 264 | 'required time (%(time)ss). Current ' |
| 265 | '%(status_attr)s: %(current_status)s.' % |
| 266 | { |
| 267 | 'status_attr': status_attr, |
| 268 | 'expected_status': expected_status, |
| 269 | 'time': client.build_timeout, |
| 270 | 'id': replica_id, |
| 271 | 'current_status': replica_status, |
| 272 | }) |
| 273 | raise exceptions.TimeoutException(message) |
| 274 | |
| 275 | |
| 276 | def wait_for_snapshot_access_rule_status(client, snapshot_id, rule_id, |
| 277 | expected_state='active'): |
| 278 | rule = client.get_snapshot_access_rule(snapshot_id, rule_id) |
| 279 | state = rule['state'] |
| 280 | start = int(time.time()) |
| 281 | |
| 282 | while state != expected_state: |
| 283 | time.sleep(client.build_interval) |
| 284 | rule = client.get_snapshot_access_rule(snapshot_id, rule_id) |
| 285 | state = rule['state'] |
| 286 | if state == expected_state: |
| 287 | return |
| 288 | if 'error' in state: |
| 289 | raise share_exceptions.AccessRuleBuildErrorException( |
| 290 | snapshot_id) |
| 291 | |
| 292 | if int(time.time()) - start >= client.build_timeout: |
| 293 | message = ('The status of snapshot access rule %(id)s failed ' |
| 294 | 'to reach %(expected_state)s state within the ' |
| 295 | 'required time (%(time)ss). Current ' |
| 296 | 'state: %(current_state)s.' % |
| 297 | { |
| 298 | 'expected_state': expected_state, |
| 299 | 'time': client.build_timeout, |
| 300 | 'id': rule_id, |
| 301 | 'current_state': state, |
| 302 | }) |
| 303 | raise exceptions.TimeoutException(message) |
| 304 | |
| 305 | |
| 306 | def wait_for_migration_status(client, share_id, dest_host, status_to_wait, |
| 307 | version=LATEST_MICROVERSION): |
| 308 | """Waits for a share to migrate to a certain host.""" |
| 309 | statuses = ((status_to_wait,) |
| 310 | if not isinstance(status_to_wait, (tuple, list, set)) |
| 311 | else status_to_wait) |
| 312 | share = client.get_share(share_id, version=version) |
| 313 | migration_timeout = CONF.share.migration_timeout |
| 314 | start = int(time.time()) |
| 315 | while share['task_state'] not in statuses: |
| 316 | time.sleep(client.build_interval) |
| 317 | share = client.get_share(share_id, version=version) |
| 318 | if share['task_state'] in statuses: |
| 319 | break |
| 320 | elif share['task_state'] == 'migration_error': |
| 321 | raise share_exceptions.ShareMigrationException( |
| 322 | share_id=share['id'], src=share['host'], dest=dest_host) |
| 323 | elif int(time.time()) - start >= migration_timeout: |
| 324 | message = ('Share %(share_id)s failed to reach a status in' |
| 325 | '%(status)s when migrating from host %(src)s to ' |
| 326 | 'host %(dest)s within the required time ' |
| 327 | '%(timeout)s.' % { |
| 328 | 'src': share['host'], |
| 329 | 'dest': dest_host, |
| 330 | 'share_id': share['id'], |
| 331 | 'timeout': client.build_timeout, |
| 332 | 'status': six.text_type(statuses), |
| 333 | }) |
| 334 | raise exceptions.TimeoutException(message) |
| 335 | return share |
| 336 | |
| 337 | |
| 338 | def wait_for_snapshot_access_rule_deletion(client, snapshot_id, rule_id): |
| 339 | rule = client.get_snapshot_access_rule(snapshot_id, rule_id) |
| 340 | start = int(time.time()) |
| 341 | |
| 342 | while rule is not None: |
| 343 | time.sleep(client.build_interval) |
| 344 | |
| 345 | rule = client.get_snapshot_access_rule(snapshot_id, rule_id) |
| 346 | |
| 347 | if rule is None: |
| 348 | return |
| 349 | if int(time.time()) - start >= client.build_timeout: |
| 350 | message = ('The snapshot access rule %(id)s failed to delete ' |
| 351 | 'within the required time (%(time)ss).' % |
| 352 | { |
| 353 | 'time': client.build_timeout, |
| 354 | 'id': rule_id, |
| 355 | }) |
| 356 | raise exceptions.TimeoutException(message) |
| 357 | |
| 358 | |
| 359 | def wait_for_message(client, resource_id): |
| 360 | """Waits until a message for a resource with given id exists""" |
| 361 | start = int(time.time()) |
| 362 | message = None |
| 363 | |
| 364 | while not message: |
| 365 | time.sleep(client.build_interval) |
| 366 | for msg in client.list_messages(): |
| 367 | if msg['resource_id'] == resource_id: |
| 368 | return msg |
| 369 | |
| 370 | if int(time.time()) - start >= client.build_timeout: |
| 371 | message = ('No message for resource with id %s was created in' |
| 372 | ' the required time (%s s).' % |
| 373 | (resource_id, client.build_timeout)) |
| 374 | raise exceptions.TimeoutException(message) |