From bba4c4cb870c381f45f0a233f87c14034380a978 Mon Sep 17 00:00:00 2001 From: Federico Ressi Date: Tue, 12 Nov 2019 17:14:35 +0100 Subject: [PATCH] Update Nova client Change-Id: I8ab987c95004703458cc80e169295814a7641a92 --- tobiko/openstack/nova/__init__.py | 10 ++- tobiko/openstack/nova/_client.py | 20 ++++- tobiko/openstack/nova/_server.py | 117 +++++++++++++++++++++++------- 3 files changed, 115 insertions(+), 32 deletions(-) diff --git a/tobiko/openstack/nova/__init__.py b/tobiko/openstack/nova/__init__.py index 99ef56c6b..2c44f8c82 100644 --- a/tobiko/openstack/nova/__init__.py +++ b/tobiko/openstack/nova/__init__.py @@ -19,17 +19,19 @@ from tobiko.openstack.nova import _server CLIENT_CLASSES = _client.CLIENT_CLASSES +get_console_output = _client.get_console_output get_nova_client = _client.get_nova_client +get_server = _client.get_server +find_hypervisor = _client.find_hypervisor +find_server = _client.find_server +HasNovaClientMixin = _client.HasNovaClientMixin list_hypervisors = _client.list_hypervisors list_servers = _client.list_servers -find_server = _client.find_server nova_client = _client.nova_client NovaClientFixture = _client.NovaClientFixture -find_hypervisor = _client.find_hypervisor -get_console_output = _client.get_console_output -get_server = _client.get_server skip_if_missing_hypervisors = _hypervisor.skip_if_missing_hypervisors find_server_ip_address = _server.find_server_ip_address +HasServerMixin = _server.HasServerMixin list_server_ip_addresses = _server.list_server_ip_addresses diff --git a/tobiko/openstack/nova/_client.py b/tobiko/openstack/nova/_client.py index 766a3ddef..47218032e 100644 --- a/tobiko/openstack/nova/_client.py +++ b/tobiko/openstack/nova/_client.py @@ -94,14 +94,18 @@ def find_server(client=None, unique=False, **params): return servers.first -def get_server(server, client=None): - return nova_client(client).servers.get(server) +def get_server(server, client=None, **params): + return nova_client(client).servers.get(server, **params) + + +MAX_SERVER_CONSOLE_OUTPUT_LENGTH = 1024 * 256 def get_console_output(server, timeout=None, interval=1., length=None, client=None): client = nova_client(client) start_time = time.time() + length = length or MAX_SERVER_CONSOLE_OUTPUT_LENGTH while True: try: output = client.servers.get_console_output(server=server, @@ -124,3 +128,15 @@ def get_console_output(server, timeout=None, interval=1., length=None, time.sleep(interval) return output + + +class HasNovaClientMixin(object): + + nova_client = None + + def get_server(self, server, **params): + return get_server(server=server, client=self.nova_client, **params) + + def get_server_console_output(self, server, **params): + return get_console_output(server=server, client=self.nova_client, + **params) diff --git a/tobiko/openstack/nova/_server.py b/tobiko/openstack/nova/_server.py index f2c1a00ab..cea68eff6 100644 --- a/tobiko/openstack/nova/_server.py +++ b/tobiko/openstack/nova/_server.py @@ -17,6 +17,8 @@ from oslo_log import log import netaddr import tobiko +from tobiko.openstack.nova import _client +from tobiko.shell import ssh from tobiko.shell import ping @@ -25,43 +27,106 @@ LOG = log.getLogger(__name__) def list_server_ip_addresses(server, network_name=None, ip_version=None, address_type=None, check_connectivity=False, - ssh_client=None): - selected_addresses = [] + ssh_client=None, count=None): + ips = tobiko.Selection() for _network_name, addresses in server.addresses.items(): + if count and len(ips) == count: + break + # check network name if network_name and network_name != _network_name: continue for address in addresses: - # check IP address version - _ip_version = address['version'] - if ip_version and ip_version != _ip_version: - continue + if check_server_ip_address(address, + ip_version=ip_version, + address_type=address_type): + ips.append(netaddr.IPAddress(address['addr'], + version=address['version'])) - # check IP address type - _address_type = address.get('OS-EXT-IPS:type') - if address_type and address_type != _address_type: - if _address_type is None: - LOG.warning('Unable to get address type of address %r', - address) - continue + # check ICMP connectivity + if check_connectivity: + ips = ping.list_reachable_hosts(ips, ssh_client=ssh_client) - ip_address = netaddr.IPAddress(address['addr'], - version=_ip_version) + return ips - # check ICMP connectivity - if check_connectivity and not ping.ping( - host=ip_address, ssh_client=ssh_client).received: - continue - selected_addresses.append(ip_address) +def check_server_ip_address(address, ip_version=None, address_type=None): + if ip_version and ip_version != address['version']: + return False - return tobiko.Selection(selected_addresses) + # check IP address type + if address_type: + try: + if address_type != address['OS-EXT-IPS:type']: + return False + except KeyError: + message = ("Unable to get IP type from server address {!r}" + ).format(address) + raise ValueError(message) + + return True def find_server_ip_address(server, unique=False, **kwargs): - addresses = list_server_ip_addresses(server=server, **kwargs) - if unique: - return addresses.unique - else: - return addresses.first + count = unique and 2 or 1 + addresses = list_server_ip_addresses(server=server, count=count, **kwargs) + return unique and addresses.unique or addresses.first + + +class HasServerMixin(_client.HasNovaClientMixin): + + @property + def server_id(self): + raise NotImplementedError + + @property + def server(self): + return _client.get_server(self.server_id) + + @property + def server_name(self): + return self.server.name + + @property + def server_ips(self): + return self.list_server_ips() + + def list_server_ips(self, **kwargs): + return list_server_ip_addresses(server=self.server, **kwargs) + + @property + def server_fixed_ips(self): + return self.list_server_ips(address_type='fixed', check=True) + + @property + def server_floating_ip(self): + floating_ips = self.list_server_ips(address_type='floating', count=1) + if floating_ips: + return floating_ips.first + else: + return None + + @property + def has_floating_ip(self): + return bool(self.server_floating_ip) + + @property + def server_console_output(self): + return super(HasServerMixin, self).get_server_console_output( + server=self.server_id) + + @property + def server_public_ip(self): + return self.server_floating_ip or self.server_fixed_ips.first + + @property + def ssh_client(self): + return ssh.ssh_client(host=self.server_public_ip, + username=self.ssh_username, + password=self.ssh_password, + proxy_client=self.ssh_proxy_client) + + ssh_proxy_client = None + ssh_username = None + ssh_password = None