2.0 refactoring:

    * Add type for most of functions
    * Remove old fio run code, move to RPC/pluggable
    * Remove most of sensors code, will move then to RPC
    * Other refactoring
diff --git a/wally/discover/openstack.py b/wally/discover/openstack.py
index 32b4629..bb128c3 100644
--- a/wally/discover/openstack.py
+++ b/wally/discover/openstack.py
@@ -1,42 +1,63 @@
 import socket
 import logging
+from typing import Iterable, Dict, Any
 
 
 from novaclient.client import Client
 
-from .node import Node
+from ..node import NodeInfo
 from wally.utils import parse_creds
 
 
-logger = logging.getLogger("io-perf-tool.discover")
+logger = logging.getLogger("wally.discover")
 
 
-def get_floating_ip(vm):
-    addrs = vm.addresses
-    for net_name, ifaces in addrs.items():
+def get_floating_ip(vm) -> str:
+    """Get VM floating IP address"""
+
+    for net_name, ifaces in vm.addresses.items():
         for iface in ifaces:
             if iface.get('OS-EXT-IPS:type') == "floating":
                 return iface['addr']
 
+    raise ValueError("VM {} has no floating ip".format(vm))
 
-def discover_vms(client, search_opts):
+
+def get_ssh_url(user: str, password: str, ip: str, key: str) -> str:
+    """Get ssh connection URL from parts"""
+
+    if password is not None:
+        assert key is None, "Both key and password provided"
+        return "ssh://{}:{}@{}".format(user, password, ip)
+    else:
+        assert key is not None, "None of key/password provided"
+        return "ssh://{}@{}::{}".format(user, ip, key)
+
+
+def discover_vms(client: Client, search_opts) -> Iterable[NodeInfo]:
+    """Discover virtual machines"""
     user, password, key = parse_creds(search_opts.pop('auth'))
 
     servers = client.servers.list(search_opts=search_opts)
     logger.debug("Found %s openstack vms" % len(servers))
-    return [Node(get_floating_ip(server), ["test_vm"], username=user,
-                 password=password, key_path=key)
-            for server in servers if get_floating_ip(server)]
+
+    nodes = []
+    for server in servers:
+        ip = get_floating_ip(server)
+        nodes.append(NodeInfo(get_ssh_url(user, password, ip, key), ["test_vm"]))
+
+    return nodes
 
 
-def discover_services(client, opts):
+def discover_services(client: Client, opts: Dict[str, Any]) -> Iterable[NodeInfo]:
+    """Discover openstack services for given cluster"""
     user, password, key = parse_creds(opts.pop('auth'))
 
     services = []
     if opts['service'] == "all":
         services = client.services.list()
     else:
-        if isinstance(opts['service'], basestring):
+        if isinstance(opts['service'], str):
             opts['service'] = [opts['service']]
 
         for s in opts['service']:
@@ -50,21 +71,25 @@
 
     logger.debug("Found %s openstack service nodes" %
                  len(host_services_mapping))
-    return [Node(host, services, username=user,
-                 password=password, key_path=key) for host, services in
-            host_services_mapping.items()]
+    nodes = []
+    for host, services in host_services_mapping.items():
+        ssh_url = get_ssh_url(user, password, host, key)
+        nodes.append(NodeInfo(ssh_url, services))
+
+    return nodes
 
 
-def discover_openstack_nodes(conn_details, conf):
+def discover_openstack_nodes(conn_details: Dict[str, str], conf: Dict[str, Any]) -> Iterable[NodeInfo]:
     """Discover vms running in openstack
-    :param conn_details - dict with openstack connection details -
+    conn_details - dict with openstack connection details -
         auth_url, api_key (password), username
+    conf - test configuration object
     """
     client = Client(version='1.1', **conn_details)
-    nodes = []
+
     if conf.get('discover'):
         services_to_discover = conf['discover'].get('nodes')
         if services_to_discover:
-            nodes.extend(discover_services(client, services_to_discover))
+            return discover_services(client, services_to_discover)
 
-    return nodes
+    return []