Skip to content

Commit

Permalink
Allow custom boot/connect timeouts for testcloud VMs
Browse files Browse the repository at this point in the history
  • Loading branch information
happz committed Feb 12, 2024
1 parent 69b3cda commit dd43fba
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 15 deletions.
9 changes: 9 additions & 0 deletions docs/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,15 @@ TMT_GIT_CLONE_TIMEOUT
Overall maximum time in seconds to clone a git repository. By
default, the limit is not set.

TMT_BOOT_TIMEOUT
How many seconds to wait for a guest to boot. Applies to provision
plugins that control the guest creation, e.g. ``virtual``. By
default, it is 2 minutes.

TMT_CONNECT_TIMEOUT
How many seconds to wait for a connection to succeed after guest
boot. By default, it is 2 minutes.

TMT_REBOOT_TIMEOUT
How many seconds to wait for a connection to succeed after
guest reboot. By default, it is 10 minutes.
Expand Down
28 changes: 20 additions & 8 deletions tmt/steps/provision/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,33 @@
import tmt.cli


def _configure_constant(default: int, envvar: str) -> int:
"""
Deduce the actual value of global constant.
:param default: the default value of the constant.
:param envvar: name of the optional environment variable which would
override the default value.
:returns: value extracted from the environment variable, or the
given default value if the variable did not exist.
"""

try:
return int(os.environ.get(envvar, default))

except ValueError as exc:
raise tmt.utils.GeneralError(
f"Could not parse '{os.environ[envvar]}' as integer.") from exc


#: How many seconds to wait for a connection to succeed after guest reboot.
#: This is the default value tmt would use unless told otherwise.
DEFAULT_REBOOT_TIMEOUT: int = 10 * 60

#: How many seconds to wait for a connection to succeed after guest reboot.
#: This is the effective value, combining the default and optional envvar,
#: ``TMT_REBOOT_TIMEOUT``.
REBOOT_TIMEOUT: int

try:
REBOOT_TIMEOUT = int(os.environ.get('TMT_REBOOT_TIMEOUT', DEFAULT_REBOOT_TIMEOUT))

except ValueError as exc:
raise tmt.utils.GeneralError(
f"Could not parse '{os.environ['TMT_REBOOT_TIMEOUT']}' as integer.") from exc
REBOOT_TIMEOUT: int = _configure_constant(DEFAULT_REBOOT_TIMEOUT, 'TMT_REBOOT_TIMEOUT')

# When waiting for guest to recover from reboot, try re-connecting every
# this many seconds.
Expand Down
31 changes: 24 additions & 7 deletions tmt/steps/provision/testcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import tmt.steps
import tmt.steps.provision
import tmt.utils
from tmt.steps.provision import _configure_constant
from tmt.utils import (
WORKDIR_ROOT,
Command,
Expand Down Expand Up @@ -149,8 +150,24 @@ def import_testcloud() -> None:
"""

# VM defaults
DEFAULT_BOOT_TIMEOUT = 120 # seconds
DEFAULT_CONNECT_TIMEOUT = 120 # seconds
#: How many seconds to wait for a VM to start.
#: This is the default value tmt would use unless told otherwise.
DEFAULT_BOOT_TIMEOUT: int = 2 * 60

#: How many seconds to wait for a VM to start.
#: This is the effective value, combining the default and optional envvar,
#: ``TMT_BOOT_TIMEOUT``.
BOOT_TIMEOUT: int = _configure_constant(DEFAULT_BOOT_TIMEOUT, 'TMT_BOOT_TIMEOUT')

#: How many seconds to wait for a connection to succeed after guest boot.
#: This is the default value tmt would use unless told otherwise.
DEFAULT_CONNECT_TIMEOUT = 2 * 60

#: How many seconds to wait for a connection to succeed after guest boot.
#: This is the effective value, combining the default and optional envvar,
#: ``TMT_CONNECT_TIMEOUT``.
CONNECT_TIMEOUT: int = _configure_constant(DEFAULT_CONNECT_TIMEOUT, 'TMT_CONNECT_TIMEOUT')

NON_KVM_ADDITIONAL_WAIT = 20 # seconds
NON_KVM_TIMEOUT_COEF = 10 # times

Expand Down Expand Up @@ -378,11 +395,11 @@ def try_get_url() -> requests.Response:
try:
return tmt.utils.wait(
self, try_get_url, datetime.timedelta(
seconds=DEFAULT_CONNECT_TIMEOUT), tick=1)
seconds=CONNECT_TIMEOUT), tick=1)

except tmt.utils.WaitingTimedOutError:
raise ProvisionError(
f'Failed to {message} in {DEFAULT_CONNECT_TIMEOUT}s.')
f'Failed to {message} in {CONNECT_TIMEOUT}s.')

def _guess_image_url(self, name: str) -> str:
""" Guess image url for given name """
Expand Down Expand Up @@ -737,7 +754,7 @@ def start(self) -> None:
try:
self._instance.prepare()
self._instance.spawn_vm()
self._instance.start(DEFAULT_BOOT_TIMEOUT * time_coeff)
self._instance.start(BOOT_TIMEOUT * time_coeff)
except (testcloud.exceptions.TestcloudInstanceError,
libvirt.libvirtError) as error:
raise ProvisionError(
Expand All @@ -750,11 +767,11 @@ def start(self) -> None:

# Wait a bit until the box is up
if not self.reconnect(
timeout=DEFAULT_CONNECT_TIMEOUT *
timeout=CONNECT_TIMEOUT *
time_coeff,
tick=1):
raise ProvisionError(
f"Failed to connect in {DEFAULT_CONNECT_TIMEOUT * time_coeff}s.")
f"Failed to connect in {CONNECT_TIMEOUT * time_coeff}s.")

if not self._instance.kvm:
self.debug(
Expand Down

0 comments on commit dd43fba

Please sign in to comment.