Allow to specify a per-image SSH connection timeout
Change-Id: Id67bee67b3f236eaaa48cfa4bde2ea0afc6cbd13
This commit is contained in:
parent
af4fb955bf
commit
1b84d5c385
@ -58,7 +58,12 @@ def get_images_options():
|
|||||||
cfg.StrOpt('username',
|
cfg.StrOpt('username',
|
||||||
help="Default " + name + " username"),
|
help="Default " + name + " username"),
|
||||||
cfg.StrOpt('password',
|
cfg.StrOpt('password',
|
||||||
help="Default " + name + " password")])]
|
help="Default " + name + " password"),
|
||||||
|
cfg.FloatOpt('connection_timeout',
|
||||||
|
default=None,
|
||||||
|
help=("Default " + name +
|
||||||
|
" SSH connection timeout (seconds)")), ]
|
||||||
|
)]
|
||||||
|
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ class CentosImageFixture(glance.URLGlanceImageFixture):
|
|||||||
container_format = CONF.tobiko.centos.container_format or "bare"
|
container_format = CONF.tobiko.centos.container_format or "bare"
|
||||||
username = CONF.tobiko.centos.username or 'centos'
|
username = CONF.tobiko.centos.username or 'centos'
|
||||||
password = CONF.tobiko.centos.password
|
password = CONF.tobiko.centos.password
|
||||||
|
connection_timeout = CONF.tobiko.centos.connection_timeout or 400.
|
||||||
|
|
||||||
|
|
||||||
class CentosFlavorStackFixture(_nova.FlavorStackFixture):
|
class CentosFlavorStackFixture(_nova.FlavorStackFixture):
|
||||||
|
@ -38,6 +38,7 @@ class CirrosImageFixture(glance.URLGlanceImageFixture):
|
|||||||
disk_format = CONF.tobiko.cirros.disk_format or "qcow2"
|
disk_format = CONF.tobiko.cirros.disk_format or "qcow2"
|
||||||
username = CONF.tobiko.cirros.username or 'cirros'
|
username = CONF.tobiko.cirros.username or 'cirros'
|
||||||
password = CONF.tobiko.cirros.password or 'gocubsgo'
|
password = CONF.tobiko.cirros.password or 'gocubsgo'
|
||||||
|
connection_timeout = CONF.tobiko.cirros.connection_timeout or 200.
|
||||||
|
|
||||||
|
|
||||||
class CirrosFlavorStackFixture(_nova.FlavorStackFixture):
|
class CirrosFlavorStackFixture(_nova.FlavorStackFixture):
|
||||||
|
@ -114,6 +114,10 @@ class ServerStackFixture(heat.HeatStackFixture):
|
|||||||
"""password used to login to a Nova server instance"""
|
"""password used to login to a Nova server instance"""
|
||||||
return self.image_fixture.password
|
return self.image_fixture.password
|
||||||
|
|
||||||
|
@property
|
||||||
|
def connection_timeout(self):
|
||||||
|
return self.image_fixture.connection_timeout
|
||||||
|
|
||||||
# Stack used to create flavor for Nova server instance
|
# Stack used to create flavor for Nova server instance
|
||||||
flavor_stack = None
|
flavor_stack = None
|
||||||
|
|
||||||
@ -146,10 +150,11 @@ class ServerStackFixture(heat.HeatStackFixture):
|
|||||||
return bool(self.floating_network)
|
return bool(self.floating_network)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ssh_client(self):
|
def ssh_client(self) -> ssh.SSHClientFixture:
|
||||||
return ssh.ssh_client(host=self.ip_address,
|
return ssh.ssh_client(host=self.ip_address,
|
||||||
username=self.username,
|
username=self.username,
|
||||||
password=self.password)
|
password=self.password,
|
||||||
|
connection_timeout=self.connection_timeout)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ssh_command(self):
|
def ssh_command(self):
|
||||||
@ -283,7 +288,7 @@ class ServerStackFixture(heat.HeatStackFixture):
|
|||||||
|
|
||||||
|
|
||||||
class PeerServerStackFixture(ServerStackFixture):
|
class PeerServerStackFixture(ServerStackFixture):
|
||||||
"""Server witch networking access requires passing by a peer Nova server
|
"""Server witch networking access requires passing by another Nova server
|
||||||
"""
|
"""
|
||||||
|
|
||||||
has_floating_ip = False
|
has_floating_ip = False
|
||||||
@ -296,6 +301,7 @@ class PeerServerStackFixture(ServerStackFixture):
|
|||||||
return ssh.ssh_client(host=self.ip_address,
|
return ssh.ssh_client(host=self.ip_address,
|
||||||
username=self.username,
|
username=self.username,
|
||||||
password=self.password,
|
password=self.password,
|
||||||
|
connection_timeout=self.connection_timeout,
|
||||||
proxy_jump=self.peer_stack.ssh_client)
|
proxy_jump=self.peer_stack.ssh_client)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -33,6 +33,7 @@ class UbuntuImageFixture(glance.URLGlanceImageFixture):
|
|||||||
container_format = CONF.tobiko.ubuntu.container_format or "bare"
|
container_format = CONF.tobiko.ubuntu.container_format or "bare"
|
||||||
username = CONF.tobiko.ubuntu.username or 'ubuntu'
|
username = CONF.tobiko.ubuntu.username or 'ubuntu'
|
||||||
password = CONF.tobiko.ubuntu.password
|
password = CONF.tobiko.ubuntu.password
|
||||||
|
connection_timeout = CONF.tobiko.ubuntu.connection_timeout or 300.
|
||||||
|
|
||||||
|
|
||||||
class UbuntuFlavorStackFixture(_nova.FlavorStackFixture):
|
class UbuntuFlavorStackFixture(_nova.FlavorStackFixture):
|
||||||
|
@ -39,8 +39,8 @@ class RebootHostTimeoutError(RebootHostError):
|
|||||||
message = "host {hostname!r} not rebooted after {timeout!s} seconds"
|
message = "host {hostname!r} not rebooted after {timeout!s} seconds"
|
||||||
|
|
||||||
|
|
||||||
def reboot_host(ssh_client, wait: bool = True, timeout: tobiko.Seconds = None,
|
def reboot_host(ssh_client: ssh.SSHClientFixture, wait: bool = True,
|
||||||
method=soft_reset_method):
|
timeout: tobiko.Seconds = None, method=soft_reset_method):
|
||||||
reboot = RebootHostOperation(ssh_client=ssh_client, wait=wait,
|
reboot = RebootHostOperation(ssh_client=ssh_client, wait=wait,
|
||||||
timeout=timeout, method=method)
|
timeout=timeout, method=method)
|
||||||
return tobiko.setup_fixture(reboot)
|
return tobiko.setup_fixture(reboot)
|
||||||
@ -58,6 +58,8 @@ class RebootHostOperation(tobiko.Operation):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def ssh_client(self) -> ssh.SSHClientFixture:
|
def ssh_client(self) -> ssh.SSHClientFixture:
|
||||||
|
if self._ssh_client is None:
|
||||||
|
raise ValueError(f"SSH client for object '{self}' is None")
|
||||||
return self._ssh_client
|
return self._ssh_client
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
@ -66,8 +68,7 @@ class RebootHostOperation(tobiko.Operation):
|
|||||||
timeout: tobiko.Seconds = None,
|
timeout: tobiko.Seconds = None,
|
||||||
method=soft_reset_method):
|
method=soft_reset_method):
|
||||||
super(RebootHostOperation, self).__init__()
|
super(RebootHostOperation, self).__init__()
|
||||||
if ssh_client is not None:
|
self._ssh_client = ssh_client
|
||||||
self._ssh_client = ssh_client
|
|
||||||
tobiko.check_valid_type(self.ssh_client, ssh.SSHClientFixture)
|
tobiko.check_valid_type(self.ssh_client, ssh.SSHClientFixture)
|
||||||
self.wait = bool(wait)
|
self.wait = bool(wait)
|
||||||
self.timeout = tobiko.to_seconds(timeout)
|
self.timeout = tobiko.to_seconds(timeout)
|
||||||
|
@ -452,7 +452,8 @@ class SSHClientManager(object):
|
|||||||
|
|
||||||
def get_client(self, host, hostname=None, username=None, port=None,
|
def get_client(self, host, hostname=None, username=None, port=None,
|
||||||
proxy_jump=None, host_config=None, config_files=None,
|
proxy_jump=None, host_config=None, config_files=None,
|
||||||
proxy_client=None, **connect_parameters):
|
proxy_client=None, **connect_parameters) -> \
|
||||||
|
SSHClientFixture:
|
||||||
if isinstance(host, netaddr.IPAddress):
|
if isinstance(host, netaddr.IPAddress):
|
||||||
host = str(host)
|
host = str(host)
|
||||||
|
|
||||||
@ -468,17 +469,22 @@ class SSHClientManager(object):
|
|||||||
username = username or global_host_config.username
|
username = username or global_host_config.username
|
||||||
|
|
||||||
host_key = hostname, port, username, proxy_jump
|
host_key = hostname, port, username, proxy_jump
|
||||||
client = self.clients.get(host_key, UNDEFINED_CLIENT)
|
existing_client = self.clients.get(host_key)
|
||||||
if client is UNDEFINED_CLIENT:
|
if isinstance(existing_client, SSHClientFixture):
|
||||||
# Put a placeholder client to avoid infinite recursive lookup
|
return existing_client
|
||||||
self.clients[host_key] = None
|
|
||||||
proxy_client = proxy_client or self.get_proxy_client(
|
# Put a placeholder to avoid infinite recursive lookup
|
||||||
host=host, proxy_jump=proxy_jump, config_files=config_files)
|
if existing_client is UNDEFINED_CLIENT:
|
||||||
self.clients[host_key] = client = SSHClientFixture(
|
raise RuntimeError('Recursive SSH proxy client definition')
|
||||||
host=host, hostname=hostname, port=port, username=username,
|
self.clients[host_key] = UNDEFINED_CLIENT
|
||||||
proxy_client=proxy_client, host_config=host_config,
|
|
||||||
**connect_parameters)
|
proxy_client = proxy_client or self.get_proxy_client(
|
||||||
return client
|
host=host, proxy_jump=proxy_jump, config_files=config_files)
|
||||||
|
self.clients[host_key] = new_client = SSHClientFixture(
|
||||||
|
host=host, hostname=hostname, port=port, username=username,
|
||||||
|
proxy_client=proxy_client, host_config=host_config,
|
||||||
|
**connect_parameters)
|
||||||
|
return new_client
|
||||||
|
|
||||||
def get_proxy_client(self, host=None, proxy_jump=None, host_config=None,
|
def get_proxy_client(self, host=None, proxy_jump=None, host_config=None,
|
||||||
config_files=None):
|
config_files=None):
|
||||||
@ -495,7 +501,7 @@ CLIENTS = SSHClientManager()
|
|||||||
|
|
||||||
def ssh_client(host, port=None, username=None, proxy_jump=None,
|
def ssh_client(host, port=None, username=None, proxy_jump=None,
|
||||||
host_config=None, config_files=None, manager=None,
|
host_config=None, config_files=None, manager=None,
|
||||||
**connect_parameters):
|
**connect_parameters) -> SSHClientFixture:
|
||||||
manager = manager or CLIENTS
|
manager = manager or CLIENTS
|
||||||
return manager.get_client(host=host, port=port, username=username,
|
return manager.get_client(host=host, port=port, username=username,
|
||||||
proxy_jump=proxy_jump, host_config=host_config,
|
proxy_jump=proxy_jump, host_config=host_config,
|
||||||
|
Loading…
Reference in New Issue
Block a user