Fix topology discovery via proxy clients

Change-Id: Ifeae3eb236ef88d8e1ac495568de5018cb441ebd
This commit is contained in:
Federico Ressi 2020-09-25 13:42:43 +02:00
parent dd4340d36a
commit 4d16b52e06
2 changed files with 31 additions and 10 deletions

View File

@ -36,9 +36,11 @@ class SSHConnection(object):
def __init__(self, def __init__(self,
address: netaddr.IPAddress, address: netaddr.IPAddress,
ssh_client: typing.Optional[ssh.SSHClientFixture] = None, ssh_client: typing.Optional[ssh.SSHClientFixture] = None,
proxy_client: typing.Optional[ssh.SSHClientFixture] = None,
failure: typing.Optional[Exception] = None): failure: typing.Optional[Exception] = None):
self.address = address self.address = address
self.ssh_client = ssh_client self.ssh_client = ssh_client
self.proxy_client = proxy_client
self.failure = failure self.failure = failure
def __repr__(self) -> str: def __repr__(self) -> str:
@ -50,6 +52,8 @@ class SSHConnection(object):
yield 'address', self.address yield 'address', self.address
if self.ssh_client is not None: if self.ssh_client is not None:
yield 'ssh_client', self.ssh_client yield 'ssh_client', self.ssh_client
if self.proxy_client is not None:
yield 'proxy_client', self.proxy_client
if self.failure is not None: if self.failure is not None:
yield 'failure', self.failure yield 'failure', self.failure
@ -76,11 +80,13 @@ class SSHConnectionManager(tobiko.SharedFixture):
def connect(self, def connect(self,
addresses: typing.List[netaddr.IPAddress], addresses: typing.List[netaddr.IPAddress],
proxy_client: typing.Optional[ssh.SSHClientFixture] = None,
**connect_parameters) -> ssh.SSHClientFixture: **connect_parameters) -> ssh.SSHClientFixture:
if not addresses: if not addresses:
raise ValueError(f"'addresses' list is empty: {addresses}") raise ValueError(f"'addresses' list is empty: {addresses}")
connections = tobiko.select(self.list_connections(addresses)) connections = tobiko.select(
self.list_connections(addresses, proxy_client=proxy_client))
try: try:
return connections.with_attributes(is_valid=True).first.ssh_client return connections.with_attributes(is_valid=True).first.ssh_client
except tobiko.ObjectNotFound: except tobiko.ObjectNotFound:
@ -89,14 +95,15 @@ class SSHConnectionManager(tobiko.SharedFixture):
for connection in connections.with_attributes(failure=None): for connection in connections.with_attributes(failure=None):
# connection not tried yet # connection not tried yet
LOG.debug("Establishing SSH connection to " LOG.debug("Establishing SSH connection to "
f"'{connection.address}'") f"'{connection.address}' (proxy_client={proxy_client})")
try: try:
ssh_client = self.ssh_client(connection.address, ssh_client = self.ssh_client(connection.address,
proxy_client=proxy_client,
**connect_parameters) **connect_parameters)
ssh_client.connect(retry_count=1, connection_attempts=1) ssh_client.connect(retry_count=1, connection_attempts=1)
except Exception as ex: except Exception as ex:
LOG.debug("Failed establishing SSH connect to " LOG.debug("Failed establishing SSH connect to "
f"'{connection.address}'.", exc_info=1) f"'{connection.address}': {ex}")
# avoid re-checking again later the same address # avoid re-checking again later the same address
connection.failure = ex connection.failure = ex
continue continue
@ -111,17 +118,27 @@ class SSHConnectionManager(tobiko.SharedFixture):
raise UreachableSSHServer(addresses=addresses, raise UreachableSSHServer(addresses=addresses,
failures=failures) failures=failures)
def list_connections(self, addresses: typing.List[netaddr.IPAddress]) -> \ def list_connections(
typing.List[SSHConnection]: self, addresses: typing.List[netaddr.IPAddress],
proxy_client: typing.Optional[ssh.SSHClientFixture] = None
) -> typing.List[SSHConnection]:
connections = [] connections = []
for address in addresses: for address in addresses:
connections.append(self.get_connection(address)) connection = self.get_connection(address,
proxy_client=proxy_client)
connections.append(connection)
return connections return connections
def get_connection(self, address: netaddr.IPAddress): def get_connection(
self, address: netaddr.IPAddress,
proxy_client: typing.Optional[ssh.SSHClientFixture] = None
) -> SSHConnection:
tobiko.check_valid_type(address, netaddr.IPAddress) tobiko.check_valid_type(address, netaddr.IPAddress)
return self._connections.setdefault(address, if proxy_client is not None:
SSHConnection(address)) tobiko.check_valid_type(proxy_client, ssh.SSHClientFixture)
connection = SSHConnection(address, proxy_client=proxy_client)
return self._connections.setdefault((address, proxy_client),
connection)
def ssh_client(self, address, username=None, port=None, def ssh_client(self, address, username=None, port=None,
key_filename=None, **ssh_parameters): key_filename=None, **ssh_parameters):

View File

@ -202,7 +202,11 @@ class OpenStackTopology(tobiko.SharedFixture):
addresses = set(parse.urlparse(endpoint.url).hostname addresses = set(parse.urlparse(endpoint.url).hostname
for endpoint in endpoints) for endpoint in endpoints)
for address in addresses: for address in addresses:
self.add_node(address=address, group='controller') try:
self.add_node(address=address, group='controller')
except _connection.UreachableSSHServer as ex:
LOG.debug(f"Unable to SSH to end point address '{address}'. "
f"{ex}")
def discover_compute_nodes(self): def discover_compute_nodes(self):
for hypervisor in nova.list_hypervisors(): for hypervisor in nova.list_hypervisors():