123 lines
5.0 KiB
Python
123 lines
5.0 KiB
Python
# Copyright (c) 2021 Red Hat
|
|
# 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.
|
|
from __future__ import absolute_import
|
|
|
|
from oslo_log import log
|
|
|
|
import tobiko
|
|
from tobiko.openstack import octavia
|
|
from tobiko import config
|
|
from tobiko.shell import sh
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
CONF = config.CONF
|
|
|
|
|
|
def wait_for_status(status_key, status, get_client, object_id,
|
|
interval: tobiko.Seconds = None,
|
|
timeout: tobiko.Seconds = None,
|
|
error_ok=False, **kwargs):
|
|
"""Waits for an object to reach a specific status.
|
|
|
|
:param status_key: The key of the status field in the response.
|
|
Ex. provisioning_status
|
|
:param status: The status to wait for. Ex. "ACTIVE"
|
|
:param get_client: The tobiko client get method.
|
|
Ex. _client.get_loadbalancer
|
|
:param object_id: The id of the object to query.
|
|
:param interval: How often to check the status, in seconds.
|
|
:param timeout: The maximum time, in seconds, to check the status.
|
|
:param error_ok: When true, ERROR status will not raise an exception.
|
|
:raises TimeoutException: The object did not achieve the status or ERROR in
|
|
the check_timeout period.
|
|
:raises UnexpectedStatusException: The request returned an unexpected
|
|
response code.
|
|
"""
|
|
|
|
for attempt in tobiko.retry(timeout=timeout,
|
|
interval=interval,
|
|
default_timeout=(
|
|
CONF.tobiko.octavia.check_timeout),
|
|
default_interval=(
|
|
CONF.tobiko.octavia.check_interval)):
|
|
response = get_client(object_id, **kwargs)
|
|
if response[status_key] == status:
|
|
return response
|
|
|
|
if response[status_key] == octavia.ERROR and not error_ok:
|
|
message = ('{name} {field} was updated to an invalid state of '
|
|
'ERROR'.format(name=get_client.__name__,
|
|
field=status_key))
|
|
raise octavia.RequestException(message)
|
|
# it will raise tobiko.RetryTimeLimitError in case of timeout
|
|
attempt.check_limits()
|
|
|
|
LOG.debug(f"Waiting for {get_client.__name__} {status_key} to get "
|
|
f"from '{response[status_key]}' to '{status}'...")
|
|
|
|
|
|
def wait_for_members_to_be_reachable(members,
|
|
lb_protocol: str,
|
|
lb_port: int,
|
|
interval: tobiko.Seconds = None,
|
|
timeout: tobiko.Seconds = None,
|
|
count: int = 10):
|
|
|
|
# Wait for members to be reachable from localhost
|
|
last_reached_id = 0
|
|
for attempt in tobiko.retry(timeout=timeout,
|
|
count=count,
|
|
interval=interval):
|
|
try:
|
|
for member in members[last_reached_id:]:
|
|
octavia.check_members_balanced(
|
|
members_count=1,
|
|
ip_address=member.server_stack.ip_address,
|
|
protocol=lb_protocol,
|
|
port=lb_port,
|
|
requests_count=1)
|
|
last_reached_id += 1 # prevent retrying same member again
|
|
except sh.ShellCommandFailed:
|
|
LOG.info("Waiting for members to have HTTP service available...")
|
|
else:
|
|
break
|
|
|
|
if attempt.is_last:
|
|
break
|
|
else:
|
|
raise RuntimeError("Members couldn't be reached!")
|
|
|
|
|
|
def wait_for_octavia_service(loadbalancer_id: str,
|
|
interval: tobiko.Seconds = None,
|
|
timeout: tobiko.Seconds = None,
|
|
client=None):
|
|
for attempt in tobiko.retry(timeout=timeout,
|
|
interval=interval,
|
|
default_timeout=180.,
|
|
default_interval=5.):
|
|
try:
|
|
octavia.list_amphorae(loadbalancer_id=loadbalancer_id,
|
|
client=client)
|
|
except octavia.OctaviaClientException as ex:
|
|
LOG.debug(f"Error listing amphorae: {ex}")
|
|
if attempt.is_last:
|
|
raise
|
|
LOG.info('Waiting for the LB to become functional again...')
|
|
else:
|
|
LOG.info('Octavia service is available!')
|
|
break
|