Merge from trunk
[plcapi.git] / trunk / tests / regrtests.py
diff --git a/trunk/tests/regrtests.py b/trunk/tests/regrtests.py
new file mode 100644 (file)
index 0000000..602a145
--- /dev/null
@@ -0,0 +1,308 @@
+#!/usr/bin/python
+
+import time, sys, urllib, os, tempfile, random
+
+# set up the api
+import xmlrpclib
+api = xmlrpclib.Server('https://www.planet-lab.org/PLCAPI/')
+
+# create auth struct
+auth = {}
+auth['Username'] = "USERNAME GOES HERE"
+auth['AuthMethod'] = "password"
+auth['AuthString'] = "PASSWORD GOES HERE"
+auth['Role'] = "user"
+
+multiquery_path = "PATH/TO/CODEPLOY/multiquery"
+gnuplot_path = "/PATH/TO/gnuplot"
+
+# create plots
+def make_plots():
+       plot_fill_empty()
+       plot_keys()
+       #os.system("cp plots/*.png ~/public_html/planetlab/tests")
+
+
+# get formatted tic string for gnuplot
+def getTimeTicString(t1, t2, step):
+       first_hour = list(time.localtime(t1))
+       if not first_hour[4] == first_hour[5] == 0:
+               first_hour[4] = 0
+               first_hour[5] = 0
+       
+       first_hour_time = int(time.mktime(first_hour))
+       first_hour_time += 3600
+       
+       backsteps = (first_hour_time - t1)
+       backsteps /= step
+       start = first_hour_time - backsteps * step
+       
+       tics = []
+       thistime = start
+       while thistime < t2:
+               tics.append("\"%s\" %d" % \
+                       (time.strftime("%H:%M", time.localtime(thistime)), thistime))
+               thistime += step
+       
+       ticstr = ", ".join(tics)
+       return ticstr
+
+
+# count total number of nodes in PlanetLab, according to the api
+def count_nodes_by_api():
+       all_nodes = [row['node_id'] for row in api.GetNodes(auth, {}, ['node_id'])]
+       print "%d\t%d" % (round(time.time()), len(all_nodes))
+
+
+# count total number of nodes in slice, according to the api
+def count_nodes_in_slice_by_api(slice=None):
+       if slice is None:
+               return
+       
+       slice_id = [row['slice_id'] for row in \
+               api.GetSlices(auth, {'name': slice}, ['slice_id'])][0]
+               
+       all_nodes = [row['node_id'] for row in \
+               api.GetNodes(auth, {}, ['node_id', 'slice_ids']) \
+               if slice_id in row['slice_ids']]
+       
+       print "%d\t%d" % (round(time.time()), len(all_nodes))
+
+
+# count total number of "good" nodes, according to CoMon
+def count_nodes_good_by_comon():
+       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)'")
+       good_nodes = comon.readlines()
+
+       print "%d\t%d" % (round(time.time()), len(good_nodes))
+       
+# estimate total number of nodes reachable by ssh
+def count_nodes_can_ssh(slice=None, key=None):
+       if slice is None:
+               return
+       if key is None:
+               return
+               
+       pollnum = 20
+       
+       all_nodes = ["%s\n" % row['hostname'] for row in \
+               api.GetNodes(auth, {}, ['hostname'])]
+
+       rand_nodes = []
+       for i in range(pollnum):
+               rand_nodes.append(all_nodes[random.randint(0,len(all_nodes)-1)])
+
+       tmpfilename = tempfile.mktemp()
+       tmpfile = open(tmpfilename, 'w')
+       tmpfile.writelines(rand_nodes)
+       tmpfile.close()
+       
+       tmpfilename2 = tempfile.mktemp()
+       tmpfile2 = open(tmpfilename2, 'w')
+       tmpfile2.writelines("""
+       export MQ_SLICE="$1"
+       export MQ_NODES="$2"
+       
+       eval `ssh-agent` >/dev/null 2>&1
+       trap "kill $SSH_AGENT_PID" 0
+       ssh-add ./keys/$3 >/dev/null 2>&1
+       
+       %s 'uname' 2>/dev/null |
+       grep "bytes" |
+       grep -v ": 0 bytes" |
+       wc -l   
+       """ % multiquery_path)
+       tmpfile2.close()
+       
+       ssh_result = os.popen("bash %s %s %s %s 2>/dev/null" % (tmpfilename2, slice, tmpfilename, key)).readlines()
+       if len(ssh_result) > 0:
+               ssh_count = float(ssh_result[0].strip()) * len(all_nodes) / pollnum
+               print "%d\t%d" % (round(time.time()), round(ssh_count))
+       
+       if os.path.exists(tmpfilename):
+               os.unlink(tmpfilename)
+
+       
+       
+       
+# remove all nodes from a slice
+def empty_slice(slice=None):
+       if slice is None:
+               return
+       
+       all_nodes = [row['node_id'] for row in api.GetNodes(auth, {}, ['node_id'])]
+       api.DeleteSliceFromNodes(auth, slice, all_nodes)
+
+       
+# add all nodes to a slice
+def fill_slice(slice=None):
+       all_nodes = [row['node_id'] for row in api.GetNodes(auth, {}, ['node_id'])]
+       api.AddSliceToNodes(auth, slice, all_nodes)
+
+       
+# add a key to a user
+def add_key(key=None):
+       if key is None:
+               return
+       
+       key_value = open("keys/%s.pub" % key).readline()
+               
+       api.AddPersonKey(auth, auth['Username'], {'key_type': 'ssh', 'key': key_value})
+
+       
+# update a user's key
+def update_key(oldkey=None, newkey=None):
+       if oldkey is None:
+               return
+       if newkey is None:
+               return
+       
+       oldkeyval = open("keys/%s.pub" % oldkey).readline()
+       newkeyval = open("keys/%s.pub" % newkey).readline()
+       keyid = [row['key_id'] for row in api.GetKeys(auth) if row['key'] == oldkeyval]
+       if len(keyid) == 0:
+               return
+       keyid = keyid[0]
+       api.UpdateKey(auth, keyid, {'key_type': 'ssh', 'key': newkeyval})       
+
+
+# delete a key from the user
+def delete_key(delkey=None):
+       if delkey is None:
+               return
+       
+       delkeyval = open("keys/%s.pub" % delkey).readline()
+       delkeyid = [row['key_id'] for row in api.GetKeys(auth) if row['key'] == delkeyval]
+       if len(delkeyid) == 0:
+               return
+       delkeyid = delkeyid[0]
+       api.DeleteKey(auth, delkeyid)
+
+       
+# create the fill/empty plot
+def plot_fill_empty():
+       #ticstep = 3600 # 1 hour
+       #plotlength = 36000 # 10 hours
+       ticstep = 1800
+       plotlength = 10800
+       
+       tmpfilename = tempfile.mktemp()
+       tmpfile = open(tmpfilename, 'w')
+       
+       starttime = -1
+       stoptime = -1
+       for datafilename in ['data/nodes', 'data/nodes_in_slice', \
+                       'data/nodes_can_ssh', 'data/nodes_good']:
+               datafile = open(datafilename, 'r')
+               line1 = datafile.readline()
+               datafile.seek(-32,2)
+               line2 = datafile.readlines().pop()
+               thisstarttime = int(line1.split("\t")[0])
+               if starttime == -1 or thisstarttime < starttime:
+                       starttime = thisstarttime
+               thisstoptime = int(line2.split("\t")[0])
+               if stoptime == -1 or thisstoptime > stoptime:
+                       stoptime = thisstoptime
+       
+       stopx = stoptime
+       startx = max(starttime, stopx - plotlength)
+       starttime = startx
+       
+       tics = getTimeTicString(starttime, stoptime, ticstep)
+       
+       startdate = time.strftime("%b %m, %Y - %H:%M", time.localtime(startx))
+       stopdate = time.strftime("%H:%M", time.localtime(stopx))
+       
+       tmpfile.write("""
+       set term png
+       set output "plots/fill_empty.png"
+       
+       set title "Number of Nodes / Time - %s to %s"
+       set xlabel "Time"
+       set ylabel "Number of Nodes"
+       
+       set xtics (%s)
+       set xrange[%d:%d]
+       set yrange[0:950]
+       
+       plot "data/nodes" u 1:2 w lines title "Total Nodes", \
+               "data/nodes_in_slice" u 1:2 w lines title "Nodes in Slice", \
+               "data/nodes_good" u 1:2 w lines title \
+                       "Healthy Nodes (according to CoMon)", \
+               "data/nodes_can_ssh" u 1:2 w lines title "Nodes Reachable by SSH"
+       
+       """ % (startdate, stopdate, tics, startx, stopx))
+       
+       tmpfile.close()
+       
+       os.system("%s %s" % (gnuplot_path, tmpfilename))
+       
+       if os.path.exists(tmpfilename):
+               os.unlink(tmpfilename)
+
+
+
+# create the keys plot
+def plot_keys():
+       #ticstep = 3600 # 1 hour
+       #plotlength = 36000 # 10 hours
+       ticstep = 1800
+       plotlength = 10800
+       
+       tmpfilename = tempfile.mktemp()
+       tmpfile = open(tmpfilename, 'w')
+
+       starttime = -1
+       stoptime = -1
+       for datafilename in ['data/nodes', 'data/nodes_in_slice2', \
+                       'data/nodes_good', 'data/nodes_can_ssh2_key0', 'data/nodes_can_ssh2_key1', \
+                       'data/nodes_can_ssh2_key2']:
+               datafile = open(datafilename, 'r')
+               line1 = datafile.readline()
+               datafile.seek(-32,2)
+               line2 = datafile.readlines().pop()
+               thisstarttime = int(line1.split("\t")[0])
+               if starttime == -1 or thisstarttime < starttime:
+                       starttime = thisstarttime
+               thisstoptime = int(line2.split("\t")[0])
+               if stoptime == -1 or thisstoptime > stoptime:
+                       stoptime = thisstoptime
+
+       stopx = stoptime
+       startx = max(starttime, stopx - plotlength)
+       starttime = startx
+
+       tics = getTimeTicString(starttime, stoptime, ticstep)
+
+       startdate = time.strftime("%b %m, %Y - %H:%M", time.localtime(startx))
+       stopdate = time.strftime("%H:%M", time.localtime(stopx))
+
+       tmpfile.write("""
+       set term png
+       set output "plots/keys.png"
+
+       set title "Number of Nodes / Time - %s to %s"
+       set xlabel "Time"
+       set ylabel "Number of Nodes"
+
+       set xtics (%s)
+       set xrange[%d:%d]
+       set yrange[0:1000]
+
+       plot "data/nodes" u 1:2 w lines title "Total Nodes", \
+               "data/nodes_in_slice2" u 1:2 w lines title "Nodes in Slice", \
+               "data/nodes_good" u 1:2 w lines title \
+                       "Healthy Nodes (according to CoMon)", \
+               "data/nodes_can_ssh2_key0" u 1:2 w lines title "Nodes Accepting Key 0", \
+               "data/nodes_can_ssh2_key1" u 1:2 w lines title "Nodes Accepting Key 1", \
+               "data/nodes_can_ssh2_key2" u 1:2 w lines title "Nodes Accepting Key 2"
+
+       """ % (startdate, stopdate, tics, startx, stopx))
+
+       tmpfile.close()
+
+       os.system("%s %s" % (gnuplot_path, tmpfilename))
+       
+       if os.path.exists(tmpfilename):
+               os.unlink(tmpfilename)
+