10 args['known_hosts'] = os.environ['HOME'] + os.sep + ".ssh" + os.sep + "known_hosts"
11 args['XMLRPC_SERVER'] = 'https://boot.planet-lab.org/PLCAPI/'
14 def __init__(self, args = args):
16 self.read_knownhosts()
18 self.auth['AuthMethod'] = "anonymous"
19 self.api = xmlrpclib.Server(args['XMLRPC_SERVER'], verbose=False, allow_none=True)
20 self.nodenetworks = {}
22 def _split_kh_entry(self, line):
25 (host,ip) = s[0].split(',')
30 key = ' '.join(s[1:3])
31 comment = ' '.join(s[3:])
32 return (host, ip, key, comment)
34 def _get_index(self, host, ip):
37 index = "%s,%s" % (host,ip)
42 def read_knownhosts(self):
43 kh_read = open(self.args["known_hosts"], 'r')
47 (host, ip, key, comment) = self._split_kh_entry(line[:-1])
48 rec = { self._get_index(host, ip) : "%s %s" % (key, comment) }
49 if 'PlanetLab' in comment:
50 self.pl_keys.update(rec)
52 self.other_keys.update(rec)
54 #for i in self.pl_keys:
56 # print self.pl_keys[i]
61 self.write_knownhosts()
63 def write_knownhosts(self):
64 f = open(self.args['known_hosts'], 'w')
65 for index in self.pl_keys:
66 print >>f, "%s %s" % (index, self.pl_keys[index])
67 for index in self.other_keys:
68 print >>f, "%s %s" % (index, self.other_keys[index])
72 l_nodes = self.getNodes()
76 name = node['hostname']
81 (host, ip, key, comment) = self._record_from_node(node, nokey_list)
82 rec = { "%s,%s" % (host,ip) : "%s %s" % (key, comment) }
83 self.pl_keys.update(rec)
87 def delete(self, host):
88 node = self.getNodes(host)
90 (host, ip, _, _) = self._record_from_node(node[0])
91 index = "%s,%s" % (host,ip)
92 if index in self.pl_keys:
93 del self.pl_keys[index]
94 if index in self.other_keys:
95 del self.other_keys[index]
98 def updateDirect(self, host):
99 cmd = os.popen("/usr/bin/ssh-keyscan -t rsa %s 2>/dev/null" % host)
101 (h, ip, key, comment) = self._split_kh_entry(line[:-1])
102 node = self.getNodes(host)
103 (host2, ip2, x, x) = self._record_from_node(node[0])
104 rec = { self._get_index(host2, ip2) : "%s %s" % (key, "DIRECT") }
107 self.other_keys.update(rec)
109 def update(self, host):
110 node = self.delete(host)
111 #node = self.getNodes(host)
113 ret = self._record_from_node(node[0])
114 (host, ip, key, comment) = ret
116 self.updateDirect(host)
118 rec = { "%s,%s" % (host,ip) : "%s %s" % (key, comment) }
119 self.pl_keys.update(rec)
121 def getNodes(self, host=None):
122 if type(host) == type(""): host = [host]
124 # get the node(s) info
125 nodes = self.api.GetNodes(self.auth,host,["hostname","ssh_rsa_key","nodenetwork_ids"])
127 # for each node's node network, update the self.nodenetworks cache
130 for net in node["nodenetwork_ids"]:
131 nodenetworks.append(net)
133 plcnodenetworks = self.api.GetNodeNetworks(self.auth,nodenetworks,["nodenetwork_id","ip"])
134 for n in plcnodenetworks:
135 self.nodenetworks[n["nodenetwork_id"]]=n
138 def _record_from_node(self, node, nokey_list=None):
139 host = node['hostname']
140 key = node['ssh_rsa_key']
142 nodenetworks = node['nodenetwork_ids']
143 if len(nodenetworks)==0: return (host, None, None, None)
145 # the [0] subscript to node['nodenetwork_ids'] means
146 # that this function wont work with multihomed nodes
147 l_nw = self.nodenetworks.get(nodenetworks[0],None)
148 if l_nw is None: return (host, None, None, None)
152 if nokey_list is not None: nokey_list += [node]
153 return (host, ip, None, None)
156 # TODO: check for '==' at end of key.
157 if len(key) > 0 and key[-1] != '=':
158 print "Host with corrupt key! for %s %s" % (node['boot_state'], node['hostname'])
160 s_date = time.strftime("%Y/%m/%d_%H:%M:%S",time.gmtime(time.time()))
161 #rec = { "%s,%s" % (host,ip) : "%s %s" % (key, "PlanetLab_%s" % (s_date)) }
163 return (host, ip, key, "PlanetLab_%s" % s_date)
175 if __name__ == '__main__':