3 import time, sys, urllib, os, tempfile, random
7 api = xmlrpclib.Server('https://www.planet-lab.org/PLCAPI/')
11 auth['Username'] = "USERNAME GOES HERE"
12 auth['AuthMethod'] = "password"
13 auth['AuthString'] = "PASSWORD GOES HERE"
16 multiquery_path = "PATH/TO/CODEPLOY/multiquery"
17 gnuplot_path = "/PATH/TO/gnuplot"
23 #os.system("cp plots/*.png ~/public_html/planetlab/tests")
26 # get formatted tic string for gnuplot
27 def getTimeTicString(t1, t2, step):
28 first_hour = list(time.localtime(t1))
29 if not first_hour[4] == first_hour[5] == 0:
33 first_hour_time = int(time.mktime(first_hour))
34 first_hour_time += 3600
36 backsteps = (first_hour_time - t1)
38 start = first_hour_time - backsteps * step
43 tics.append("\"%s\" %d" % \
44 (time.strftime("%H:%M", time.localtime(thistime)), thistime))
47 ticstr = ", ".join(tics)
51 # count total number of nodes in PlanetLab, according to the api
52 def count_nodes_by_api():
53 all_nodes = [row['node_id'] for row in api.GetNodes(auth, {}, ['node_id'])]
54 print "%d\t%d" % (round(time.time()), len(all_nodes))
57 # count total number of nodes in slice, according to the api
58 def count_nodes_in_slice_by_api(slice=None):
62 slice_id = [row['slice_id'] for row in \
63 api.GetSlices(auth, {'name': slice}, ['slice_id'])][0]
65 all_nodes = [row['node_id'] for row in \
66 api.GetNodes(auth, {}, ['node_id', 'slice_ids']) \
67 if slice_id in row['slice_ids']]
69 print "%d\t%d" % (round(time.time()), len(all_nodes))
72 # count total number of "good" nodes, according to CoMon
73 def count_nodes_good_by_comon():
74 comon = urllib.urlopen("http://summer.cs.princeton.edu/status/tabulator.cgi?table=table_nodeviewshort&format=nameonly&select='resptime%20%3E%200%20&&%20((drift%20%3E%201m%20||%20(dns1udp%20%3E%2080%20&&%20dns2udp%20%3E%2080)%20||%20gbfree%20%3C%205%20||%20sshstatus%20%3E%202h)%20==%200)'")
75 good_nodes = comon.readlines()
77 print "%d\t%d" % (round(time.time()), len(good_nodes))
79 # estimate total number of nodes reachable by ssh
80 def count_nodes_can_ssh(slice=None, key=None):
88 all_nodes = ["%s\n" % row['hostname'] for row in \
89 api.GetNodes(auth, {}, ['hostname'])]
92 for i in range(pollnum):
93 rand_nodes.append(all_nodes[random.randint(0,len(all_nodes)-1)])
95 tmpfilename = tempfile.mktemp()
96 tmpfile = open(tmpfilename, 'w')
97 tmpfile.writelines(rand_nodes)
100 tmpfilename2 = tempfile.mktemp()
101 tmpfile2 = open(tmpfilename2, 'w')
102 tmpfile2.writelines("""
106 eval `ssh-agent` >/dev/null 2>&1
107 trap "kill $SSH_AGENT_PID" 0
108 ssh-add ./keys/$3 >/dev/null 2>&1
110 %s 'uname' 2>/dev/null |
112 grep -v ": 0 bytes" |
114 """ % multiquery_path)
117 ssh_result = os.popen("bash %s %s %s %s 2>/dev/null" % (tmpfilename2, slice, tmpfilename, key)).readlines()
118 if len(ssh_result) > 0:
119 ssh_count = float(ssh_result[0].strip()) * len(all_nodes) / pollnum
120 print "%d\t%d" % (round(time.time()), round(ssh_count))
122 if os.path.exists(tmpfilename):
123 os.unlink(tmpfilename)
128 # remove all nodes from a slice
129 def empty_slice(slice=None):
133 all_nodes = [row['node_id'] for row in api.GetNodes(auth, {}, ['node_id'])]
134 api.DeleteSliceFromNodes(auth, slice, all_nodes)
137 # add all nodes to a slice
138 def fill_slice(slice=None):
139 all_nodes = [row['node_id'] for row in api.GetNodes(auth, {}, ['node_id'])]
140 api.AddSliceToNodes(auth, slice, all_nodes)
143 # add a key to a user
144 def add_key(key=None):
148 key_value = open("keys/%s.pub" % key).readline()
150 api.AddPersonKey(auth, auth['Username'], {'key_type': 'ssh', 'key': key_value})
153 # update a user's key
154 def update_key(oldkey=None, newkey=None):
160 oldkeyval = open("keys/%s.pub" % oldkey).readline()
161 newkeyval = open("keys/%s.pub" % newkey).readline()
162 keyid = [row['key_id'] for row in api.GetKeys(auth) if row['key'] == oldkeyval]
166 api.UpdateKey(auth, keyid, {'key_type': 'ssh', 'key': newkeyval})
169 # delete a key from the user
170 def delete_key(delkey=None):
174 delkeyval = open("keys/%s.pub" % delkey).readline()
175 delkeyid = [row['key_id'] for row in api.GetKeys(auth) if row['key'] == delkeyval]
176 if len(delkeyid) == 0:
178 delkeyid = delkeyid[0]
179 api.DeleteKey(auth, delkeyid)
182 # create the fill/empty plot
183 def plot_fill_empty():
184 #ticstep = 3600 # 1 hour
185 #plotlength = 36000 # 10 hours
189 tmpfilename = tempfile.mktemp()
190 tmpfile = open(tmpfilename, 'w')
194 for datafilename in ['data/nodes', 'data/nodes_in_slice', \
195 'data/nodes_can_ssh', 'data/nodes_good']:
196 datafile = open(datafilename, 'r')
197 line1 = datafile.readline()
199 line2 = datafile.readlines().pop()
200 thisstarttime = int(line1.split("\t")[0])
201 if starttime == -1 or thisstarttime < starttime:
202 starttime = thisstarttime
203 thisstoptime = int(line2.split("\t")[0])
204 if stoptime == -1 or thisstoptime > stoptime:
205 stoptime = thisstoptime
208 startx = max(starttime, stopx - plotlength)
211 tics = getTimeTicString(starttime, stoptime, ticstep)
213 startdate = time.strftime("%b %m, %Y - %H:%M", time.localtime(startx))
214 stopdate = time.strftime("%H:%M", time.localtime(stopx))
218 set output "plots/fill_empty.png"
220 set title "Number of Nodes / Time - %s to %s"
222 set ylabel "Number of Nodes"
228 plot "data/nodes" u 1:2 w lines title "Total Nodes", \
229 "data/nodes_in_slice" u 1:2 w lines title "Nodes in Slice", \
230 "data/nodes_good" u 1:2 w lines title \
231 "Healthy Nodes (according to CoMon)", \
232 "data/nodes_can_ssh" u 1:2 w lines title "Nodes Reachable by SSH"
234 """ % (startdate, stopdate, tics, startx, stopx))
238 os.system("%s %s" % (gnuplot_path, tmpfilename))
240 if os.path.exists(tmpfilename):
241 os.unlink(tmpfilename)
245 # create the keys plot
247 #ticstep = 3600 # 1 hour
248 #plotlength = 36000 # 10 hours
252 tmpfilename = tempfile.mktemp()
253 tmpfile = open(tmpfilename, 'w')
257 for datafilename in ['data/nodes', 'data/nodes_in_slice2', \
258 'data/nodes_good', 'data/nodes_can_ssh2_key0', 'data/nodes_can_ssh2_key1', \
259 'data/nodes_can_ssh2_key2']:
260 datafile = open(datafilename, 'r')
261 line1 = datafile.readline()
263 line2 = datafile.readlines().pop()
264 thisstarttime = int(line1.split("\t")[0])
265 if starttime == -1 or thisstarttime < starttime:
266 starttime = thisstarttime
267 thisstoptime = int(line2.split("\t")[0])
268 if stoptime == -1 or thisstoptime > stoptime:
269 stoptime = thisstoptime
272 startx = max(starttime, stopx - plotlength)
275 tics = getTimeTicString(starttime, stoptime, ticstep)
277 startdate = time.strftime("%b %m, %Y - %H:%M", time.localtime(startx))
278 stopdate = time.strftime("%H:%M", time.localtime(stopx))
282 set output "plots/keys.png"
284 set title "Number of Nodes / Time - %s to %s"
286 set ylabel "Number of Nodes"
292 plot "data/nodes" u 1:2 w lines title "Total Nodes", \
293 "data/nodes_in_slice2" u 1:2 w lines title "Nodes in Slice", \
294 "data/nodes_good" u 1:2 w lines title \
295 "Healthy Nodes (according to CoMon)", \
296 "data/nodes_can_ssh2_key0" u 1:2 w lines title "Nodes Accepting Key 0", \
297 "data/nodes_can_ssh2_key1" u 1:2 w lines title "Nodes Accepting Key 1", \
298 "data/nodes_can_ssh2_key2" u 1:2 w lines title "Nodes Accepting Key 2"
300 """ % (startdate, stopdate, tics, startx, stopx))
304 os.system("%s %s" % (gnuplot_path, tmpfilename))
306 if os.path.exists(tmpfilename):
307 os.unlink(tmpfilename)