Update wait_for_cloud_init_status function

Change-Id: Id1942bb9fa665a81bf9d3e11451ce1ef301e44e6
This commit is contained in:
Federico Ressi 2021-12-10 15:04:26 +01:00
parent e809608e4d
commit 343812ccbe
1 changed files with 51 additions and 59 deletions

View File

@ -14,7 +14,6 @@
from __future__ import absolute_import from __future__ import absolute_import
import collections import collections
import contextlib
import typing import typing
from oslo_log import log from oslo_log import log
@ -187,76 +186,69 @@ def wait_for_cloud_init_status(
timeout: tobiko.Seconds = None, timeout: tobiko.Seconds = None,
sleep_interval: tobiko.Seconds = None) \ sleep_interval: tobiko.Seconds = None) \
-> str: -> str:
hostname = getattr(ssh_client, 'hostname', None) hostname = sh.get_hostname(ssh_client=ssh_client,
timeout=timeout)
if transient_states is None: if transient_states is None:
transient_states = list() transient_states = list()
for status in expected_states: for status in expected_states:
transient_states += CLOUD_INIT_TRANSIENT_STATES.get(status, []) transient_states += CLOUD_INIT_TRANSIENT_STATES.get(status, [])
with open_output_file(filename=CLOUD_INIT_LOG_FILE, def _read_file(filename: str, tail=False) -> str:
timeout=timeout, return read_file(filename=filename,
ssh_client=ssh_client) as log_file, \ ssh_client=ssh_client,
open_output_file(filename=CLOUD_INIT_OUTPUT_FILE, timeout=timeout,
timeout=timeout, tail=tail)
ssh_client=ssh_client) as output_file:
for attempt in tobiko.retry(timeout=timeout,
interval=sleep_interval,
default_timeout=1200.,
default_interval=5.):
actual_status = get_cloud_init_status(ssh_client=ssh_client,
timeout=attempt.time_left)
if actual_status in expected_states:
return actual_status
log_file.readall() for attempt in tobiko.retry(timeout=timeout,
output_file.readall() interval=sleep_interval,
if actual_status not in transient_states: default_timeout=1200.,
raise InvalidCloudInitStatusError( default_interval=5.):
hostname=hostname, actual_status = get_cloud_init_status(ssh_client=ssh_client,
actual_status=actual_status, timeout=attempt.time_left)
expected_states=expected_states, if actual_status in expected_states:
log_file=str(log_file), break
output_file=str(output_file))
try: if attempt.is_last:
attempt.check_limits() raise WaitForCloudInitTimeoutError(
except tobiko.RetryTimeLimitError as ex: timeout=attempt.timeout,
raise WaitForCloudInitTimeoutError( hostname=hostname,
timeout=attempt.timeout, actual_status=actual_status,
hostname=hostname, expected_states=expected_states,
actual_status=actual_status, log_file=_read_file(CLOUD_INIT_LOG_FILE),
expected_states=expected_states, output_file=_read_file(CLOUD_INIT_OUTPUT_FILE))
log_file=str(log_file),
output_file=str(output_file)) from ex
# show only the last log line elif actual_status in transient_states:
try: last_log_lines = _read_file(CLOUD_INIT_LOG_FILE, tail=True)
last_log_line = str(log_file).splitlines()[-1]
except IndexError:
last_log_line = ""
LOG.debug(f"Waiting cloud-init status on host '{hostname}' to " LOG.debug(f"Waiting cloud-init status on host '{hostname}' to "
f"switch from '{actual_status}' to any of expected " f"switch from '{actual_status}' to any of expected "
f"states ({', '.join(expected_states)}):\n\n" f"states ({', '.join(expected_states)}):\n\n"
f"--- {CLOUD_INIT_LOG_FILE} ---\n" f"--- {CLOUD_INIT_LOG_FILE} ---\n"
f"{last_log_line}\n\n") f"{last_log_lines}\n\n")
else:
raise InvalidCloudInitStatusError(
hostname=hostname,
actual_status=actual_status,
expected_states=expected_states,
log_file=_read_file(CLOUD_INIT_LOG_FILE),
output_file=_read_file(CLOUD_INIT_OUTPUT_FILE))
raise RuntimeError("Retry loop ended himself") else:
raise RuntimeError('Broken retry loop')
return actual_status
@contextlib.contextmanager def read_file(filename: str,
def open_output_file(filename: str = CLOUD_INIT_OUTPUT_FILE, tail=False,
tail=False, ssh_client: ssh.SSHClientType = None,
follow=False, timeout: tobiko.Seconds = None):
**process_params) \ if tail:
-> typing.Generator[sh.ShellStdout, None, None]: command = 'tail'
command = ['tail'] else:
if not tail: command = 'cat'
# Start from the begin of the file try:
command += ['-c', '+0'] return sh.execute(f'{command} "{filename}"',
if follow: timeout=timeout,
command += ['-F'] ssh_client=ssh_client).stdout
except sh.ShellCommandFailed:
command += [filename] LOG.exception(f"Error reading file '{filename}'")
process = sh.process(command, **process_params) return ""
with process:
yield process.stdout