blob: 88e8656316163af5c246227e9b3e74604cc2f35e [file] [log] [blame]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +03001import socket
2import logging
koder aka kdanilov73084622016-11-16 21:51:08 +02003from typing import Dict, Any, List
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +03004
5
6from novaclient.client import Client
7
koder aka kdanilov73084622016-11-16 21:51:08 +02008from ..node_interfaces import NodeInfo
9from ..config import ConfigBlock
10from ..utils import parse_creds
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030011
12
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030013logger = logging.getLogger("wally.discover")
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030014
15
koder aka kdanilov73084622016-11-16 21:51:08 +020016def get_floating_ip(vm: Any) -> str:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030017 """Get VM floating IP address"""
18
19 for net_name, ifaces in vm.addresses.items():
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030020 for iface in ifaces:
21 if iface.get('OS-EXT-IPS:type') == "floating":
22 return iface['addr']
23
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030024 raise ValueError("VM {} has no floating ip".format(vm))
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030025
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030026
27def get_ssh_url(user: str, password: str, ip: str, key: str) -> str:
28 """Get ssh connection URL from parts"""
29
30 if password is not None:
31 assert key is None, "Both key and password provided"
32 return "ssh://{}:{}@{}".format(user, password, ip)
33 else:
34 assert key is not None, "None of key/password provided"
35 return "ssh://{}@{}::{}".format(user, ip, key)
36
37
koder aka kdanilov73084622016-11-16 21:51:08 +020038def discover_vms(client: Client, search_opts: Dict) -> List[NodeInfo]:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030039 """Discover virtual machines"""
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030040 user, password, key = parse_creds(search_opts.pop('auth'))
41
42 servers = client.servers.list(search_opts=search_opts)
43 logger.debug("Found %s openstack vms" % len(servers))
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030044
koder aka kdanilov73084622016-11-16 21:51:08 +020045 nodes = [] # type: List[NodeInfo]
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030046 for server in servers:
47 ip = get_floating_ip(server)
koder aka kdanilov73084622016-11-16 21:51:08 +020048 nodes.append(NodeInfo(get_ssh_url(user, password, ip, key), roles={"test_vm"}))
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030049 return nodes
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030050
51
koder aka kdanilov73084622016-11-16 21:51:08 +020052def discover_services(client: Client, opts: Dict[str, Any]) -> List[NodeInfo]:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030053 """Discover openstack services for given cluster"""
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030054 user, password, key = parse_creds(opts.pop('auth'))
55
56 services = []
57 if opts['service'] == "all":
58 services = client.services.list()
59 else:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030060 if isinstance(opts['service'], str):
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030061 opts['service'] = [opts['service']]
62
63 for s in opts['service']:
64 services.extend(client.services.list(binary=s))
65
koder aka kdanilov73084622016-11-16 21:51:08 +020066 host_services_mapping = {} # type: Dict[str, [str]]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030067
68 for service in services:
69 ip = socket.gethostbyname(service.host)
koder aka kdanilov73084622016-11-16 21:51:08 +020070 host_services_mapping.get(ip, []).append(service.binary)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030071
72 logger.debug("Found %s openstack service nodes" %
73 len(host_services_mapping))
koder aka kdanilov73084622016-11-16 21:51:08 +020074
75 nodes = [] # type: List[NodeInfo]
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030076 for host, services in host_services_mapping.items():
77 ssh_url = get_ssh_url(user, password, host, key)
78 nodes.append(NodeInfo(ssh_url, services))
79
80 return nodes
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030081
82
koder aka kdanilov73084622016-11-16 21:51:08 +020083def discover_openstack_nodes(conn_details: Dict[str, str], conf: ConfigBlock) -> List[NodeInfo]:
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030084 """Discover vms running in openstack
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030085 conn_details - dict with openstack connection details -
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030086 auth_url, api_key (password), username
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030087 conf - test configuration object
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030088 """
89 client = Client(version='1.1', **conn_details)
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030090
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030091 if conf.get('discover'):
92 services_to_discover = conf['discover'].get('nodes')
93 if services_to_discover:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030094 return discover_services(client, services_to_discover)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030095
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030096 return []