12 # TODO: maybe when there's more time; for better readability.
13 #class History(Structure):
14 # _fields_ = [ ("version", c_int),
16 # ("history", c_float * HISTORY_LENGTH), ]
18 # allocate fixed space on disk to save persistent state.
19 # what to store in this file?
20 # slice_history : x,x,x,x,x,...
21 # root_history : y,y,y,y,y,y...
23 HISTORY_LENGTH = 24*30 # 30 days, if checked once an hour
24 HISTORY_fmt = ('iif', 'f'*HISTORY_LENGTH )
28 def get_network_bytes(interface):
29 for line in open('/proc/net/dev', 'r'):
31 data = line.split('%s:' % interface)[1].split()
32 rx_bytes, tx_bytes = (data[0], data[8])
33 return (float(rx_bytes), float(tx_bytes))
36 def read_safe_history(filename):
38 This function guarantees that space is preserved.
39 If one of the file operations fail, it will throw an exception.
41 if os.path.exists(filename):
43 fd = os.open(filename, os.O_RDONLY)
44 a = os.read(fd, os.path.getsize(filename))
46 (version, i, last_value) = struct.unpack_from(HISTORY_fmt[0], a, 0)
47 assert version == HISTORY_version
48 history = struct.unpack_from(HISTORY_fmt[1], a, struct.calcsize(HISTORY_fmt[0]))
49 history = [ h for h in history ]
51 # TODO: in the future a more clever version migration might be nice.
52 os.remove(filename) # just nuke the old version
53 # create for the first time, with empty data
54 (i, last_value, history) = (0, 0.0, [0]*HISTORY_LENGTH)
55 write_safe_history(filename, (i, last_value, history), False)
60 # create for the first time, with empty data
61 (i, last_value, history) = (0, 0.0, [0]*HISTORY_LENGTH)
62 write_safe_history(filename, (i, last_value, history), False)
64 return (i, last_value, history)
66 def write_safe_history(filename, (i, last_value, history), check_for_file=True):
67 # length should match, and the file should already exist
68 assert len(history) == HISTORY_LENGTH
70 assert os.path.exists(filename)
72 # open without TRUNC nor APPEND, then seek to beginning to preserve space on disk
73 fd = os.open(filename, os.O_WRONLY|os.O_CREAT)
75 ret = os.write(fd, struct.pack(HISTORY_fmt[0], HISTORY_version, i, last_value))
76 ret += os.write(fd, struct.pack(HISTORY_fmt[1], *history))
80 def add_to_history((i, last_value, history), data):
82 # note, this won't be the case when reboot occurs, or on first run.
83 assert last_value > 0.0
84 assert data > last_value
85 #print "Recording: %s"% (data-last_value)
86 history[i] = data-last_value
88 i = i % HISTORY_LENGTH
90 # on init when last_value is 0, or reboot when counter resets.
91 # do not record data except for last_value, do not increment index
95 return (i, last_value, history)
97 def record_data(filename, data):
98 rh = read_safe_history(filename)
99 return write_safe_history(filename, add_to_history(rh, data))
101 def get_percentile(filename, percentile):
102 (idx,last_version, history) = read_safe_history(filename)
103 summary = history[idx:] + history[:idx]
104 measured = filter(lambda x: x != 0, summary)
105 if len(measured) == 0:
108 # convert bytes to bw
109 bw = map(lambda x: x/(60*60*24.0), measured)
112 pct = bw[int(l*percentile)]
119 def timeit(*args, **kw):
121 result = method(*args, **kw)
124 #print '%r (%r, %r) %2.2f sec' % \
125 # (method.__name__, args, kw, te-ts)
126 return (result, te-ts)
131 def check_dns(ip, protocol='udp'):
134 ro = DNS.Request(name="www.yahoo.com", qtype="A", server=ip)
135 r = ro.req(protocol=protocol)
137 except DNS.Base.DNSError, e:
141 def get_nameserver_ips(filename):
142 ip_re = re.compile("\d+\.\d+\.\d+\.\d+")
144 if not os.path.exists(filename):
147 f = open(filename, 'r')
149 if 'resolv' in filename:
151 for field in l.strip().split():
152 if ip_re.match(field) and field not in ret:
155 if 'ifcfg' in filename:
159 for field in l.strip().split('='):
160 field = field.replace('"', '')
161 field = field.replace("'", '')
162 if ip_re.match(field) and field not in ret:
168 for interface in ['eth0', 'eth1', 'eth2', 'eth3']:
169 t_bytes = get_network_bytes(interface)
173 # massive fail. cannot continue.
176 # take diff b/t sum(t_bytes) and last_value
177 record_data("bw_history.dat", sum(t_bytes))
178 record_data("bw_history_rx.dat", t_bytes[0])
179 record_data("bw_history_tx.dat", t_bytes[1])
181 print get_percentile("bw_history.dat", 0.90),
182 print get_percentile("bw_history_rx.dat", 0.90),
183 print get_percentile("bw_history_tx.dat", 0.90),
188 if __name__ == "__main__":
193 #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()