![Michael Johnson](/assets/img/avatar_default.png)
This patch updates the version of hacking to be consistent with octavia. It is also required for flake8 to understand f-strings correctly. Along with this version update, the patch fixes issues in the code found by the new versions. This patch also removes O349 check for importing mock since flake8 has added H216 which does the same check. Change-Id: I8e49fc19faff59b2811a7ee09b7ccaa286f73d82
236 lines
9.5 KiB
Python
236 lines
9.5 KiB
Python
# Copyright 2017 GoDaddy
|
|
# Copyright 2018 Rackspace US Inc. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import time
|
|
|
|
from oslo_log import log as logging
|
|
from tempest import config
|
|
from tempest.lib.common.utils import test_utils
|
|
from tempest.lib import exceptions
|
|
|
|
from octavia_tempest_plugin.common import constants as const
|
|
|
|
CONF = config.CONF
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def wait_for_status(show_client, id, status_key, status,
|
|
check_interval, check_timeout, root_tag=None,
|
|
error_ok=False, **kwargs):
|
|
"""Waits for an object to reach a specific status.
|
|
|
|
:param show_client: The tempest service client show method.
|
|
Ex. cls.os_primary.servers_client.show_server
|
|
:param id: The id of the object to query.
|
|
:param status_key: The key of the status field in the response.
|
|
Ex. provisioning_status
|
|
:param status: The status to wait for. Ex. "ACTIVE"
|
|
:check_interval: How often to check the status, in seconds.
|
|
:check_timeout: The maximum time, in seconds, to check the status.
|
|
:root_tag: The root tag on the response to remove, if any.
|
|
:error_ok: When true, ERROR status will not raise an exception.
|
|
:raises CommandFailed: Raised if the object goes into ERROR and ERROR was
|
|
not the desired status.
|
|
:raises TimeoutException: The object did not achieve the status or ERROR in
|
|
the check_timeout period.
|
|
:returns: The object details from the show client.
|
|
"""
|
|
start = int(time.time())
|
|
LOG.info('Waiting for %s status to update to %s',
|
|
show_client.__name__, status)
|
|
while True:
|
|
if status == const.DELETED:
|
|
try:
|
|
response = show_client(id, **kwargs)
|
|
except exceptions.NotFound:
|
|
return
|
|
else:
|
|
response = show_client(id, **kwargs)
|
|
|
|
if root_tag:
|
|
object_details = response[root_tag]
|
|
else:
|
|
object_details = response
|
|
|
|
if object_details[status_key] == status:
|
|
LOG.info('%s\'s status updated to %s.',
|
|
show_client.__name__, status)
|
|
return object_details
|
|
elif object_details[status_key] == 'ERROR' and not error_ok:
|
|
message = ('{name} {field} updated to an invalid state of '
|
|
'ERROR'.format(name=show_client.__name__,
|
|
field=status_key))
|
|
caller = test_utils.find_test_caller()
|
|
if caller:
|
|
message = '({caller}) {message}'.format(caller=caller,
|
|
message=message)
|
|
raise exceptions.UnexpectedResponseCode(message)
|
|
|
|
if int(time.time()) - start >= check_timeout:
|
|
message = (
|
|
'{name} {field} failed to update to {expected_status} within '
|
|
'the required time {timeout}. Current status of {name}: '
|
|
'{status}'.format(
|
|
name=show_client.__name__,
|
|
timeout=check_timeout,
|
|
status=object_details[status_key],
|
|
expected_status=status,
|
|
field=status_key
|
|
))
|
|
caller = test_utils.find_test_caller()
|
|
if caller:
|
|
message = '({caller}) {message}'.format(caller=caller,
|
|
message=message)
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
time.sleep(check_interval)
|
|
|
|
|
|
def wait_for_not_found(delete_func, show_func, *args, **kwargs):
|
|
"""Call the delete function, then wait for it to be 'NotFound'
|
|
|
|
:param delete_func: The delete function to call.
|
|
:param show_func: The show function to call looking for 'NotFound'.
|
|
:param ID: The ID of the object to delete/show.
|
|
:raises TimeoutException: The object did not achieve the status or ERROR in
|
|
the check_timeout period.
|
|
:returns: None
|
|
"""
|
|
try:
|
|
delete_func(*args, **kwargs)
|
|
except exceptions.NotFound:
|
|
return
|
|
start = int(time.time())
|
|
LOG.info('Waiting for object to be NotFound')
|
|
while True:
|
|
try:
|
|
show_func(*args, **kwargs)
|
|
except exceptions.NotFound:
|
|
return
|
|
if int(time.time()) - start >= CONF.load_balancer.check_timeout:
|
|
message = ('{name} did not raise NotFound in {timeout} '
|
|
'seconds.'.format(
|
|
name=show_func.__name__,
|
|
timeout=CONF.load_balancer.check_timeout))
|
|
raise exceptions.TimeoutException(message)
|
|
time.sleep(CONF.load_balancer.check_interval)
|
|
|
|
|
|
def wait_for_deleted_status_or_not_found(
|
|
show_client, id, status_key, check_interval, check_timeout,
|
|
root_tag=None, **kwargs):
|
|
"""Waits for an object to reach a DELETED status or be not found (404).
|
|
|
|
:param show_client: The tempest service client show method.
|
|
Ex. cls.os_primary.servers_client.show_server
|
|
:param id: The id of the object to query.
|
|
:param status_key: The key of the status field in the response.
|
|
Ex. provisioning_status
|
|
:check_interval: How often to check the status, in seconds.
|
|
:check_timeout: The maximum time, in seconds, to check the status.
|
|
:root_tag: The root tag on the response to remove, if any.
|
|
:raises CommandFailed: Raised if the object goes into ERROR and ERROR was
|
|
not the desired status.
|
|
:raises TimeoutException: The object did not achieve the status or ERROR in
|
|
the check_timeout period.
|
|
:returns: None
|
|
"""
|
|
start = int(time.time())
|
|
LOG.info('Waiting for %s status to update to DELETED or be not found(404)',
|
|
show_client.__name__)
|
|
while True:
|
|
try:
|
|
response = show_client(id, **kwargs)
|
|
except exceptions.NotFound:
|
|
return
|
|
|
|
if root_tag:
|
|
object_details = response[root_tag]
|
|
else:
|
|
object_details = response
|
|
|
|
if object_details[status_key] == const.DELETED:
|
|
LOG.info('%s\'s status updated to DELETED.',
|
|
show_client.__name__)
|
|
return
|
|
elif int(time.time()) - start >= check_timeout:
|
|
message = (
|
|
'{name} {field} failed to update to DELETED or become not '
|
|
'found (404) within the required time {timeout}. Current '
|
|
'status of {name}: {status}'.format(
|
|
name=show_client.__name__,
|
|
timeout=check_timeout,
|
|
status=object_details[status_key],
|
|
field=status_key
|
|
))
|
|
caller = test_utils.find_test_caller()
|
|
if caller:
|
|
message = '({caller}) {message}'.format(caller=caller,
|
|
message=message)
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
time.sleep(check_interval)
|
|
|
|
|
|
def wait_for_spare_amps(list_func, check_interval, check_timeout):
|
|
"""Waits for amphorae in spare pool.
|
|
|
|
:param list_func: The tempest service client amphora list method.
|
|
Ex. cls.os_admin.amphora_client.list_amphorae
|
|
:check_interval: How often to check the status, in seconds.
|
|
:check_timeout: The maximum time, in seconds, to check the status.
|
|
:raises TimeoutException: No amphora available in spare pool in the
|
|
check_timeout period.
|
|
:returns: A list of amphorae in spare pool.
|
|
"""
|
|
|
|
LOG.info('Waiting for amphorae in spare pool')
|
|
start = int(time.time())
|
|
while True:
|
|
spare_amps = list_func(
|
|
query_params='{status}={status_ready}'.format(
|
|
status=const.STATUS, status_ready=const.STATUS_READY))
|
|
if len(spare_amps) >= 1:
|
|
return spare_amps
|
|
if int(time.time()) - start >= check_timeout:
|
|
message = ("No available amphorae in spare pool within the "
|
|
"required time {timeout}.".format(
|
|
timeout=check_timeout))
|
|
raise exceptions.TimeoutException(message)
|
|
time.sleep(check_interval)
|
|
|
|
|
|
def wait_until_true(func, timeout=60, sleep=1, **kwargs):
|
|
"""Wait until callable predicate is evaluated as True
|
|
|
|
:param func: Callable deciding whether waiting should continue.
|
|
:param timeout: Timeout in seconds how long should function wait.
|
|
:param sleep: Polling interval for results in seconds.
|
|
"""
|
|
start = int(time.time())
|
|
while True:
|
|
try:
|
|
ret = func(**kwargs)
|
|
if ret:
|
|
return
|
|
except Exception as e:
|
|
LOG.error(e)
|
|
|
|
if int(time.time()) - start >= timeout:
|
|
message = "Timed out after {timeout} seconds waiting".format(
|
|
timeout=timeout)
|
|
raise exceptions.TimeoutException(message)
|
|
time.sleep(sleep)
|