--- /dev/null
+#!/usr/bin/python
+
+import commands
+import os
+import sys
+import re
+import socket
+import struct
+import time
+
+#import ctypes
+# TODO: maybe when there's more time; for better readability.
+#class History(Structure):
+# _fields_ = [ ("version", c_int),
+# ("index", c_int),
+# ("history", c_float * HISTORY_LENGTH), ]
+
+# allocate fixed space on disk to save persistent state.
+# what to store in this file?
+# slice_history : x,x,x,x,x,...
+# root_history : y,y,y,y,y,y...
+
+HISTORY_LENGTH = 24*30 # 30 days, if checked once an hour
+HISTORY_fmt = ('ii', 'f'*HISTORY_LENGTH )
+HISTORY_version = 1
+
+
+def get_network_bytes(interface):
+ for line in open('/proc/net/dev', 'r'):
+ if interface in line:
+ data = line.split('%s:' % interface)[1].split()
+ rx_bytes, tx_bytes = (data[0], data[8])
+ return (float(rx_bytes), float(tx_bytes))
+ return None
+
+def get_uptime():
+ for line in open('/proc/uptime', 'r'):
+ data = line.split()[0]
+ return float(data)
+ return None
+
+def read_safe_history(filename):
+ """
+ This function guarantees that space is preserved.
+ If one of the file operations fail, it will throw an exception.
+ """
+ if os.path.exists(filename):
+ # read existing data
+ fd = os.open(filename, os.O_RDONLY)
+ a = os.read(fd, os.path.getsize(filename))
+ try:
+ (version, i) = struct.unpack_from(HISTORY_fmt[0], a, 0)
+ assert version == HISTORY_version
+ history = struct.unpack_from(HISTORY_fmt[1], a, struct.calcsize(HISTORY_fmt[0]))
+ history = [ h for h in history ]
+ except:
+ # TODO: in the future a more clever version migration might be nice.
+ os.remove(filename) # just nuke the old version
+ # create for the first time, with empty data
+ (i, history) = (0, [0]*HISTORY_LENGTH)
+ write_safe_history(filename, (i, history), False)
+
+ os.close(fd)
+
+ else:
+ # create for the first time, with empty data
+ (i, history) = (0, [0]*HISTORY_LENGTH)
+ write_safe_history(filename, (i, history), False)
+
+ return (i, history)
+
+def write_safe_history(filename, (i, history), check_for_file=True):
+ # length should match, and the file should already exist
+ assert len(history) == HISTORY_LENGTH
+ if check_for_file:
+ assert os.path.exists(filename)
+
+ # open without TRUNC nor APPEND, then seek to beginning to preserve space on disk
+ fd = os.open(filename, os.O_WRONLY|os.O_CREAT)
+ os.lseek(fd, 0, 0)
+ ret = os.write(fd, struct.pack(HISTORY_fmt[0], HISTORY_version, i ))
+ ret += os.write(fd, struct.pack(HISTORY_fmt[1], *history))
+ os.close(fd)
+ return ret
+
+def add_to_history((i, history), data):
+ try:
+ assert data > 0.0
+ history[i] = data
+ i += 1
+ i = i % HISTORY_LENGTH
+ except:
+ # do not record data if data <= 0
+ pass
+ return (i, history)
+
+def record_data(filename, data):
+ rh = read_safe_history(filename)
+ return write_safe_history(filename, add_to_history(rh, data))
+
+def get_avg_uptime(filename):
+ (idx, history) = read_safe_history(filename)
+ summary = history[idx:] + history[:idx]
+ measured = filter(lambda x: x != 0, summary)
+ if len(measured) == 0:
+ return 0
+ return float(sum(measured))/float(len(measured))
+
+def timed(method):
+
+ def timeit(*args, **kw):
+ ts = time.time()
+ result = method(*args, **kw)
+ te = time.time()
+
+ #print '%r (%r, %r) %2.2f sec' % \
+ # (method.__name__, args, kw, te-ts)
+ return (result, te-ts)
+
+ return timeit
+
+@timed
+def check_dns(ip, protocol='udp'):
+ try:
+ #ip = ip[:-1] + "0"
+ ro = DNS.Request(name="www.yahoo.com", qtype="A", server=ip)
+ r = ro.req(protocol=protocol)
+ r = "OK"
+ except DNS.Base.DNSError, e:
+ r = "Error: %s" % e
+ return r
+
+def get_nameserver_ips(filename):
+ ip_re = re.compile("\d+\.\d+\.\d+\.\d+")
+ ret = {}
+ if not os.path.exists(filename):
+ return ret
+
+ f = open(filename, 'r')
+
+ if 'resolv' in filename:
+ for l in f:
+ for field in l.strip().split():
+ if ip_re.match(field) and field not in ret:
+ ret[field] = 0
+
+ if 'ifcfg' in filename:
+ for l in f:
+ if 'DNS' not in l:
+ continue
+ for field in l.strip().split('='):
+ field = field.replace('"', '')
+ field = field.replace("'", '')
+ if ip_re.match(field) and field not in ret:
+ ret[field] = 0
+ return ret
+
+def main():
+
+ ut = get_uptime()
+ if ut == None:
+ # massive fail. cannot continue.
+ sys.exit(1)
+
+ record_data("uptime_history.dat", ut)
+
+ print get_avg_uptime("uptime_history.dat"),
+
+ print ""
+
+
+if __name__ == "__main__":
+ main()
+
+
+# TODO: comon?
+#url = """http://comon.cs.princeton.edu/status/tabulator.cgi?table=table_nodeviewshort&select='dns1udp>80 && dns2udp>80&&name=="%s"'&format=formatcsv&dumpcols='dns1udp,dns1tcp,dns2udp,dns2tcp'""" % os.popen("hostname").read().strip()