discovering
diff --git a/nodes/ceph.py b/nodes/ceph.py
index 871b834..c5a9288 100644
--- a/nodes/ceph.py
+++ b/nodes/ceph.py
@@ -16,21 +16,21 @@
     for ip in osd_ips:
         url = "ssh://%s" % ip
         if url in ips:
-            ips[url].add("ceph-osd")
+            ips[url].append("ceph-osd")
         else:
-            ips[url] = ("ceph-osd")
+            ips[url] = ["ceph-osd"]
     for ip in mon_ips:
         url = "ssh://%s" % ip
         if url in ips:
-            ips[url].add("ceph-mon")
+            ips[url].append("ceph-mon")
         else:
-            ips[url] = ("ceph-mon")
+            ips[url] = ["ceph-mon"]
     for ip in mds_ips:
         url = "ssh://%s" % ip
         if url in ips:
-            ips[url].add("ceph-mds")
+            ips[url].append("ceph-mds")
         else:
-            ips[url] = ("ceph-mds")
+            ips[url] = ["ceph-mds"]
 
     res = []
     for url, roles in ips:
diff --git a/nodes/discover.py b/nodes/discover.py
new file mode 100644
index 0000000..17aa1e7
--- /dev/null
+++ b/nodes/discover.py
@@ -0,0 +1,39 @@
+import logging
+
+import openstack
+import ceph
+import fuel
+
+
+logger = logging.getLogger("io-perf-tool")
+
+
+def discover(cluster_conf):
+    if not cluster_conf:
+        logger.error("No nodes configured")
+
+    nodes_to_run = []
+    for cluster, cluster_info in cluster_conf.items():
+        if cluster == "openstack":
+            conn = cluster_info.get('connection')
+            if not conn:
+                logger.error("No connection provided for %s. Skipping"
+                             % cluster)
+                continue
+            logger.debug("Discovering openstack nodes "
+                         "with connection details: %r" %
+                         conn)
+
+            nodes_to_run.extend(openstack.discover_openstack_nodes(
+                conn, cluster_info))
+        if cluster == "fuel":
+            url = cluster_info['connection'].pop('url')
+            creads = cluster_info['connection']
+            roles = cluster_info['discover']
+            if isinstance(roles, basestring):
+                roles = [roles]
+            nodes_to_run.extend(fuel.discover_fuel_nodes(url, creads, roles))
+
+        if cluster == "ceph":
+            nodes_to_run.extend(ceph.discover_ceph_node())
+    return nodes_to_run
diff --git a/nodes/fuel.py b/nodes/fuel.py
index 76dedcd..c828793 100644
--- a/nodes/fuel.py
+++ b/nodes/fuel.py
@@ -1,10 +1,17 @@
 import node
 import fuel_rest_api
+import logging
 
 
-def discover_fuel_nodes(root_url, credentials):
+logger = logging.getLogger("io-perf-tool")
+
+
+def discover_fuel_nodes(root_url, credentials, roles):
     """Discover Fuel nodes"""
     connection = fuel_rest_api.KeystoneAuth(root_url, credentials)
     fi = fuel_rest_api.FuelInfo(connection)
-
-    return [node.Node(n.ip, n.get_roles()) for n in fi.nodes]
\ No newline at end of file
+    nodes = []
+    for role in roles:
+        nodes.extend(getattr(fi.nodes, role))
+    logger.debug("Found %s fuel nodes" % len(fi.nodes))
+    return [node.Node(n.ip, n.get_roles()) for n in nodes]
\ No newline at end of file
diff --git a/nodes/node.py b/nodes/node.py
index 4ee2109..03efd34 100644
--- a/nodes/node.py
+++ b/nodes/node.py
@@ -9,11 +9,14 @@
         self.port = port
         self.key_path = key_path
 
+    def __repr__(self):
+        return "<Node: %s %s>" % (self.ip, self.roles)
+
     def set_conn_attr(self, name, value):
         setattr(self, name, value)
 
     @property
-    def connection(self):
+    def connection_url(self):
         connection = []
 
         if self.username:
diff --git a/nodes/openstack.py b/nodes/openstack.py
index 7444e46..ed3d8ea 100644
--- a/nodes/openstack.py
+++ b/nodes/openstack.py
@@ -1,33 +1,104 @@
+import logging
 import node
-
+from starts_vms import create_vms_mt
 from novaclient.client import Client
 
 
+logger = logging.getLogger("io-perf-tool")
+
+
 def get_floating_ip(vm):
     addrs = vm.addresses
     for net_name, ifaces in addrs.items():
         for iface in ifaces:
             if iface.get('OS-EXT-IPS:type') == "floating":
                 return iface['addr']
-    raise Exception("No floating ip found for VM %s" % repr(vm))
 
 
-def discover_openstack_vms(conn_details):
+def discover_vms(client, search_opts):
+    auth = search_opts.pop('auth', {})
+    user = auth.get('user')
+    password = auth.get('password')
+    key = auth.get('key_file')
+    servers = client.servers.list(search_opts=search_opts)
+    logger.debug("Found %s openstack vms" % len(servers))
+    return [node.Node(get_floating_ip(server), ["test_vm"], username=user,
+                      password=password, key_path=key)
+            for server in servers if get_floating_ip(server)]
+
+
+def discover_services(client, opts):
+    auth = opts.pop('auth', {})
+    user = auth.get('user')
+    password = auth.get('password')
+    key = auth.get('key_file')
+    services = []
+    if opts['service'] == "all":
+        services = client.services.list()
+    else:
+        if isinstance(opts['service'], basestring):
+            opts['service'] = [opts['service']]
+
+        for s in opts['service']:
+            services.extend(client.services.list(binary=s))
+
+    host_services_mapping = {}
+    for service in services:
+        if host_services_mapping.get(service.host):
+            host_services_mapping[service.host].append(service.binary)
+        else:
+            host_services_mapping[service.host] = [service.binary]
+    logger.debug("Found %s openstack service nodes" %
+                 len(host_services_mapping))
+    return [node.Node(host, services, username=user,
+                      password=password, key_path=key) for host, services in
+            host_services_mapping.items()]
+
+
+def discover_openstack_nodes(conn_details, conf):
     """Discover vms running in openstack
     :param conn_details - dict with openstack connection details -
         auth_url, api_key (password), username
     """
     client = Client(version='1.1', **conn_details)
-    servers = client.servers.list(search_opts={"all_tenant": True})
-    return [node.Node(get_floating_ip(server), ["test_vm"])
-            for server in servers]
+    nodes = []
+    if conf.get('discover'):
+        vms_to_discover = conf['discover'].get('vm')
+        if vms_to_discover:
+            nodes.extend(discover_vms(client, vms_to_discover))
+        services_to_discover = conf['discover'].get('nodes')
+        if services_to_discover:
+            nodes.extend(discover_services(client, services_to_discover))
+    if conf.get('start'):
+        vms = start_test_vms(client, conf['start'])
+        nodes.extend(vms)
+
+    return nodes
 
 
-def discover_openstack_nodes(conn_details):
-    """Discover openstack nodes
-    :param conn_details - dict with openstack connection details -
-        auth_url, api_key (password), username
-    """
-    client = Client(version='1.1', **conn_details)
-    services = client.services.list()
-    return [node.Node(server.ip, ["test_vm"]) for server in services]
+def start_test_vms(client, opts):
+
+    user = opts.pop("user", None)
+    key_file = opts.pop("key_file", None)
+    aff_group = opts.pop("aff_group", None)
+    raw_count = opts.pop('count')
+
+    if raw_count.startswith("x"):
+        logger.debug("Getting amount of compute services")
+        count = len(client.services.list(binary="nova-compute"))
+        count *= int(raw_count[1:])
+    else:
+        count = int(raw_count)
+
+    if aff_group is not None:
+        scheduler_hints = {'group': aff_group}
+    else:
+        scheduler_hints = None
+
+    opts['scheduler_hints'] = scheduler_hints
+
+    logger.debug("Will start {0} vms".format(count))
+
+    nodes = create_vms_mt(client, count, **opts)
+    return [node.Node(get_floating_ip(server), ["test_vm"], username=user,
+                      key_path=key_file) for server in nodes]