3 # plessh will run the given shell command on all Planetlab Europe
10 from threading import Thread
11 from getpass import getpass
13 PLC_HOST = "www.planet-lab.eu"
15 KEY_FILE = "~/.ssh/id_rsa"
16 BASE_CMD = 'ssh -q %(options)s -i %(key)s -l %(slice_name)s %(host)s "%(cmd)s" 2> /dev/null'
20 "StrictHostKeyChecking": "no",
22 "UserKnownHostsFile": "/dev/null",
27 def __init__(self, hostname, username, password):
29 self.api = xmlrpclib.ServerProxy("https://%s/PLCAPI/" % self.host, allow_none=True)
32 "AuthString": password,
33 "AuthMethod": "password"
35 # this will raise an exception if not successful
36 self.api.AuthCheck(self.auth)
38 def wrap(self, function):
40 args = (self.auth, ) + args
41 return function(*args)
44 def __getattr__(self, attr):
45 return self.wrap(getattr(self.api, attr))
48 def getAPI(hostname, username=None, password=None):
49 if not username: username=raw_input("Please enter your PLC username: ")
50 if not password: password=getpass("Please enter your PLC password: ")
53 return API(hostname=hostname, username=username, password=password)
54 except xmlrpclib.Fault,e:
56 print "Please try again."
57 username=raw_input("Please enter your PLC username: ")
58 password=getpass("Please enter your PLC password: ")
62 def change_key_comment(output, hostname):
63 fields = output.split()
70 if f.startswith("ssh-"):
79 return " ".join(new_fields)
83 class Command(Thread):
84 def __init__(self, cmd, hosts=[]):
90 def runCmd(self, host):
91 cmd = BASE_CMD % {'cmd': self.cmd,
94 'slice_name': SLICE_NAME,
95 'options': " ".join(["-o %s=%s" % (o,v) for o,v in SSH_OPTIONS.items()])}
97 output = p.read().strip()
99 output = output.split('\n')[0] # only get the first line
100 # keep the comment for the keys
101 # output = change_key_comment(output, host)
106 for host in self.hosts:
107 self.results[host] = self.runCmd(host)
110 def distributeHosts(num_hosts):
112 host_per_thread = num_hosts / THREAD_COUNT
113 rest = num_hosts % THREAD_COUNT
114 for i in range(THREAD_COUNT):
123 def main(plchost, slice_name, print_report=lambda:None):
124 ple = getAPI(plchost)
127 node_ids = ple.GetSlices(slice_name)[0]['node_ids']
128 slice_nodes = [n['hostname'] for n in ple.GetNodes(node_ids)]
130 print "Can not get nodes for slice: %s" % slice_name
133 dist_list = distributeHosts(len(slice_nodes))
136 cmd = "cat /home/%s/.ssh/id_rsa.pub" % slice_name
137 print "Please wait gathering public keys from %d PlanetLab nodes. This may take a while..." % len(slice_nodes)
138 for i in range(THREAD_COUNT):
139 current = Command(cmd, slice_nodes[index:index+dist_list[i]])
140 index += dist_list[i]
141 thread_list.append(current)
143 for i in thread_list:
147 for i in thread_list:
148 results.update(i.results)
150 print_report(results)
152 if __name__ == "__main__":
153 def save_report(results, fname="slice_keys"):
156 for node in results.keys():
158 f.write("%s\n" % results[node])
161 print "Could get keys from %d of %d nodes" % (ok, len(results))
162 print "Please see %s file." % fname
164 def get_option(msg, default):
165 ret = raw_input("%s [%s] : " % (msg, default))
170 PLC_HOST=get_option("Please enter your PLC host", PLC_HOST)
171 SLICE_NAME=get_option("Please enter your slice name", SLICE_NAME)
172 KEY_FILE=get_option("Please enter the path of your key", KEY_FILE)
173 main(PLC_HOST, SLICE_NAME, print_report=save_report)