blob: eb7410ac013c993d0ff47d85439766035bf049e6 [file] [log] [blame]
Jude Cross986e3f52017-07-24 14:57:20 -07001# Copyright 2017 GoDaddy
2# Copyright 2018 Rackspace US Inc. 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
18from oslo_log import log as logging
19from tempest import config
20from tempest.lib.common.utils import test_utils
21from tempest.lib import exceptions
22
23from octavia_tempest_plugin.common import constants as const
24
25CONF = config.CONF
26LOG = logging.getLogger(__name__)
27
28
29def wait_for_status(show_client, id, status_key, status,
Adam Harwellde3e0542018-05-03 18:21:06 -070030 check_interval, check_timeout, root_tag=None,
Michael Johnson8d420802019-08-30 11:11:42 -070031 error_ok=False, **kwargs):
Jude Cross986e3f52017-07-24 14:57:20 -070032 """Waits for an object to reach a specific status.
33
34 :param show_client: The tempest service client show method.
35 Ex. cls.os_primary.servers_client.show_server
36 :param id: The id of the object to query.
37 :param status_key: The key of the status field in the response.
38 Ex. provisioning_status
39 :param status: The status to wait for. Ex. "ACTIVE"
40 :check_interval: How often to check the status, in seconds.
41 :check_timeout: The maximum time, in seconds, to check the status.
42 :root_tag: The root tag on the response to remove, if any.
Michael Johnson8d420802019-08-30 11:11:42 -070043 :error_ok: When true, ERROR status will not raise an exception.
Jude Cross986e3f52017-07-24 14:57:20 -070044 :raises CommandFailed: Raised if the object goes into ERROR and ERROR was
45 not the desired status.
46 :raises TimeoutException: The object did not achieve the status or ERROR in
47 the check_timeout period.
48 :returns: The object details from the show client.
49 """
50 start = int(time.time())
51 LOG.info('Waiting for {name} status to update to {status}'.format(
52 name=show_client.__name__, status=status))
53 while True:
Adam Harwella795ae62018-04-23 12:11:19 -070054 if status == const.DELETED:
55 try:
Adam Harwellde3e0542018-05-03 18:21:06 -070056 response = show_client(id, **kwargs)
Adam Harwella795ae62018-04-23 12:11:19 -070057 except exceptions.NotFound:
58 return
59 else:
Adam Harwellde3e0542018-05-03 18:21:06 -070060 response = show_client(id, **kwargs)
Adam Harwella795ae62018-04-23 12:11:19 -070061
Jude Cross986e3f52017-07-24 14:57:20 -070062 if root_tag:
63 object_details = response[root_tag]
64 else:
65 object_details = response
66
67 if object_details[status_key] == status:
68 LOG.info('{name}\'s status updated to {status}.'.format(
69 name=show_client.__name__, status=status))
70 return object_details
71 elif object_details[status_key] == 'ERROR':
72 message = ('{name} {field} updated to an invalid state of '
73 'ERROR'.format(name=show_client.__name__,
74 field=status_key))
75 caller = test_utils.find_test_caller()
76 if caller:
77 message = '({caller}) {message}'.format(caller=caller,
78 message=message)
Michael Johnson8d420802019-08-30 11:11:42 -070079 if not error_ok:
80 raise exceptions.UnexpectedResponseCode(message)
Jude Cross986e3f52017-07-24 14:57:20 -070081 elif int(time.time()) - start >= check_timeout:
82 message = (
83 '{name} {field} failed to update to {expected_status} within '
84 'the required time {timeout}. Current status of {name}: '
85 '{status}'.format(
86 name=show_client.__name__,
87 timeout=check_timeout,
88 status=object_details[status_key],
89 expected_status=status,
90 field=status_key
91 ))
92 caller = test_utils.find_test_caller()
93 if caller:
94 message = '({caller}) {message}'.format(caller=caller,
95 message=message)
96 raise exceptions.TimeoutException(message)
97
98 time.sleep(check_interval)
99
100
101def wait_for_not_found(delete_func, show_func, *args, **kwargs):
102 """Call the delete function, then wait for it to be 'NotFound'
103
104 :param delete_func: The delete function to call.
105 :param show_func: The show function to call looking for 'NotFound'.
106 :param ID: The ID of the object to delete/show.
107 :raises TimeoutException: The object did not achieve the status or ERROR in
108 the check_timeout period.
109 :returns: None
110 """
111 try:
Jude Crossfbbd2b42017-08-09 15:21:04 -0700112 delete_func(*args, **kwargs)
Jude Cross986e3f52017-07-24 14:57:20 -0700113 except exceptions.NotFound:
114 return
115 start = int(time.time())
116 LOG.info('Waiting for object to be NotFound')
117 while True:
118 try:
119 show_func(*args, **kwargs)
120 except exceptions.NotFound:
121 return
122 if int(time.time()) - start >= CONF.load_balancer.check_timeout:
123 message = ('{name} did not raise NotFound in {timeout} '
124 'seconds.'.format(
125 name=show_func.__name__,
126 timeout=CONF.load_balancer.check_timeout))
127 raise exceptions.TimeoutException(message)
128 time.sleep(CONF.load_balancer.check_interval)
129
130
131def wait_for_deleted_status_or_not_found(
132 show_client, id, status_key, check_interval, check_timeout,
Adam Harwellde3e0542018-05-03 18:21:06 -0700133 root_tag=None, **kwargs):
Jude Cross986e3f52017-07-24 14:57:20 -0700134 """Waits for an object to reach a DELETED status or be not found (404).
135
136 :param show_client: The tempest service client show method.
137 Ex. cls.os_primary.servers_client.show_server
138 :param id: The id of the object to query.
139 :param status_key: The key of the status field in the response.
140 Ex. provisioning_status
141 :check_interval: How often to check the status, in seconds.
142 :check_timeout: The maximum time, in seconds, to check the status.
143 :root_tag: The root tag on the response to remove, if any.
144 :raises CommandFailed: Raised if the object goes into ERROR and ERROR was
145 not the desired status.
146 :raises TimeoutException: The object did not achieve the status or ERROR in
147 the check_timeout period.
148 :returns: None
149 """
150 start = int(time.time())
151 LOG.info('Waiting for {name} status to update to DELETED or be not '
152 'found(404)'.format(name=show_client.__name__))
153 while True:
154 try:
Adam Harwellde3e0542018-05-03 18:21:06 -0700155 response = show_client(id, **kwargs)
Jude Cross986e3f52017-07-24 14:57:20 -0700156 except exceptions.NotFound:
157 return
158
159 if root_tag:
160 object_details = response[root_tag]
161 else:
162 object_details = response
163
164 if object_details[status_key] == const.DELETED:
165 LOG.info('{name}\'s status updated to DELETED.'.format(
166 name=show_client.__name__))
167 return
168 elif int(time.time()) - start >= check_timeout:
169 message = (
170 '{name} {field} failed to update to DELETED or become not '
171 'found (404) within the required time {timeout}. Current '
172 'status of {name}: {status}'.format(
173 name=show_client.__name__,
174 timeout=check_timeout,
175 status=object_details[status_key],
176 field=status_key
177 ))
178 caller = test_utils.find_test_caller()
179 if caller:
180 message = '({caller}) {message}'.format(caller=caller,
181 message=message)
182 raise exceptions.TimeoutException(message)
183
184 time.sleep(check_interval)
Carlos Goncalves5b963c42019-02-03 15:37:28 +0100185
186
187def wait_for_spare_amps(list_func, check_interval, check_timeout):
188 """Waits for amphorae in spare pool.
189
190 :param list_func: The tempest service client amphora list method.
191 Ex. cls.os_admin.amphora_client.list_amphorae
192 :check_interval: How often to check the status, in seconds.
193 :check_timeout: The maximum time, in seconds, to check the status.
194 :raises TimeoutException: No amphora available in spare pool in the
195 check_timeout period.
196 :returns: A list of amphorae in spare pool.
197 """
198
199 LOG.info('Waiting for amphorae in spare pool')
200 start = int(time.time())
201 while True:
202 spare_amps = list_func(
203 query_params='{status}={status_ready}'.format(
204 status=const.STATUS, status_ready=const.STATUS_READY))
205 if len(spare_amps) >= 1:
206 return spare_amps
207 if int(time.time()) - start >= check_timeout:
208 message = ("No available amphorae in spare pool within the "
209 "required time {timeout}.".format(
210 timeout=check_timeout))
211 raise exceptions.TimeoutException(message)
212 time.sleep(check_interval)