keep this script in here for now
authorBarış Metin <Talip-Baris.Metin@sophia.inria.fr>
Fri, 9 Jul 2010 09:00:20 +0000 (11:00 +0200)
committerBarış Metin <Talip-Baris.Metin@sophia.inria.fr>
Fri, 9 Jul 2010 09:00:20 +0000 (11:00 +0200)
omf_keys/get_slice_pub_keys.py [new file with mode: 0755]

diff --git a/omf_keys/get_slice_pub_keys.py b/omf_keys/get_slice_pub_keys.py
new file mode 100755 (executable)
index 0000000..b40fcb5
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+#
+# plessh will run the given shell command on all Planetlab Europe
+# nodes.
+#
+
+import sys
+import os
+import xmlrpclib
+from threading import Thread
+from getpass import getpass
+
+PLC_HOST = "www.planet-lab.eu"
+SLICE_NAME = ""
+KEY_FILE = "~/.ssh/id_rsa"
+BASE_CMD = 'ssh -q %(options)s -i %(key)s -l %(slice_name)s %(host)s "%(cmd)s" 2> /dev/null'
+THREAD_COUNT = 10
+SSH_OPTIONS = {
+    "BatchMode": "yes",
+    "StrictHostKeyChecking": "no",
+    "ConnectTimeout": 15,
+    "UserKnownHostsFile": "/dev/null",
+    "CheckHostIP": "no"
+    }
+
+class API:
+    def __init__(self, hostname, username, password):
+        self.host = hostname
+        self.api = xmlrpclib.ServerProxy("https://%s/PLCAPI/" % self.host, allow_none=True)
+        self.auth = {
+            "Username": username,
+            "AuthString": password,
+            "AuthMethod": "password"
+            }
+        # this will raise an exception if not successful
+        self.api.AuthCheck(self.auth)
+
+    def wrap(self, function):
+        def wrapper(*args):
+            args = (self.auth, ) + args
+            return function(*args)
+        return wrapper
+
+    def __getattr__(self, attr):
+        return self.wrap(getattr(self.api, attr))
+
+
+def getAPI(hostname, username=None, password=None):
+    if not username: username=raw_input("Please enter your PLC username: ")
+    if not password: password=getpass("Please enter your PLC password: ")
+    while True:
+        try:
+            return API(hostname=hostname, username=username, password=password)
+        except xmlrpclib.Fault,e:
+            print e
+            print "Please try again."
+            username=raw_input("Please enter your PLC username: ")
+            password=getpass("Please enter your PLC password: ")
+            continue
+
+
+def change_key_comment(output, hostname):
+    fields = output.split()
+    new_fields = []
+
+    in_key = False
+    in_comment = False
+    for f in fields:
+        f = f.strip()
+        if f.startswith("ssh-"):
+            in_key = True
+        elif in_key:
+            in_key = False
+            in_comment = True
+        elif in_comment:
+            f = hostname
+        new_fields.append(f)
+
+    return " ".join(new_fields)
+    
+
+
+class Command(Thread):
+    def __init__(self, cmd, hosts=[]):
+        Thread.__init__(self)
+        self.hosts = hosts
+        self.cmd = cmd
+        self.results = {}
+
+    def runCmd(self, host):
+        cmd = BASE_CMD % {'cmd': self.cmd,
+                          'host': host,
+                          'key': KEY_FILE,
+                          'slice_name': SLICE_NAME,
+                          'options':  " ".join(["-o %s=%s" % (o,v) for o,v in SSH_OPTIONS.items()])}
+        p = os.popen(cmd)
+        output = p.read().strip()
+        if output:
+            output = output.split('\n')[0] # only get the first line
+            output = change_key_comment(output, host)
+            return output
+        return None
+
+    def run(self):
+        for host in self.hosts:
+            self.results[host] = self.runCmd(host)
+
+
+def distributeHosts(num_hosts):
+    dist_list = []
+    host_per_thread = num_hosts / THREAD_COUNT
+    rest = num_hosts % THREAD_COUNT
+    for i in range(THREAD_COUNT):
+        c = host_per_thread
+        if rest:
+            c += 1
+            rest -= 1
+        dist_list.append(c)
+    return dist_list
+
+
+def main(plchost, slice_name, print_report=lambda:None):
+    ple = getAPI(plchost)
+    slice_nodes = []
+    try:
+        node_ids = ple.GetSlices(slice_name)[0]['node_ids']
+        slice_nodes = [n['hostname'] for n in ple.GetNodes(node_ids)]
+    except IndexError:
+        print "Can not get nodes for slice: %s" % slice_name
+        sys.exit(1)
+
+    dist_list = distributeHosts(len(slice_nodes))
+    thread_list = []
+    index = 0
+    cmd = "cat /home/%s/.ssh/id_rsa.pub" % slice_name
+    print "Please wait gathering public keys from %d PlanetLab nodes. This may take a while..." % len(slice_nodes)
+    for i in range(THREAD_COUNT):
+        current = Command(cmd, slice_nodes[index:index+dist_list[i]])
+        index += dist_list[i]
+        thread_list.append(current)
+        current.start()
+    for i in thread_list:
+        i.join()
+
+    results = {}
+    for i in thread_list:
+        results.update(i.results)
+
+    print_report(results)
+
+if __name__ == "__main__":
+    def save_report(results, fname="slice_keys"):
+        ok = 0
+        f = open(fname, "w")
+        for node in results.keys():
+            if results[node]:
+                f.write("%s\n" % results[node])
+                ok += 1
+        f.close()
+        print "Could get keys from %d of %d nodes" % (ok, len(results))
+        print "Please see %s file." % fname
+
+    def get_option(msg, default):
+        ret = raw_input("%s [%s] : " % (msg, default))
+        if not ret:
+            ret = default
+        return ret
+            
+    PLC_HOST=get_option("Please enter your PLC host", PLC_HOST)
+    SLICE_NAME=get_option("Please enter your slice name", SLICE_NAME)
+    KEY_FILE=get_option("Please enter the path of your key", KEY_FILE)
+    main(PLC_HOST, SLICE_NAME, print_report=save_report)
+