3 # can't probe comon directly from node.
4 # http://comon.cs.princeton.edu/status/tabulator.cgi?table=table_nodeviewshort&select='dns1udp>80 && dns2udp>80&&name=="planetlab-01.cs.princeton.edu"'&format=formatcsv&dumpcols='dns1udp,dns1tcp,dns2udp,dns2tcp'
14 # TODO: maybe when there's more time; for better readability.
15 #class History(Structure):
16 # _fields_ = [ ("version", c_int),
18 # ("history", c_float * HISTORY_LENGTH), ]
20 # allocate fixed space on disk to save persistent state.
21 # what to store in this file?
22 # slice_history : x,x,x,x,x,...
23 # root_history : y,y,y,y,y,y...
25 HISTORY_LENGTH = 24*30 # 30 days, if checked once an hour
26 HISTORY_fmt = ('ii', 'f'*HISTORY_LENGTH )
29 def read_safe_history(filename):
31 This function guarantees that space is preserved.
32 If one of the file operations fail, it will throw an exception.
34 if os.path.exists(filename):
36 fd = os.open(filename, os.O_RDONLY)
37 a = os.read(fd, os.path.getsize(filename))
39 (version, i) = struct.unpack_from(HISTORY_fmt[0], a, 0)
40 assert version == HISTORY_version
41 history = struct.unpack_from(HISTORY_fmt[1], a, struct.calcsize(HISTORY_fmt[0]))
42 history = [ h for h in history ]
44 # TODO: in the future a more clever version migration might be nice.
45 os.remove(filename) # just nuke the old version
46 # create for the first time, with empty data
47 (i, history) = (0, [0]*HISTORY_LENGTH)
48 write_safe_history(filename, (i, history), False)
53 # create for the first time, with empty data
54 (i, history) = (0, [0]*HISTORY_LENGTH)
55 write_safe_history(filename, (i, history), False)
59 def write_safe_history(filename, (i, history), check_for_file=True):
60 # length should match, and the file should already exist
61 assert len(history) == HISTORY_LENGTH
63 assert os.path.exists(filename)
65 # open without TRUNC nor APPEND, then seek to beginning to preserve space on disk
66 fd = os.open(filename, os.O_WRONLY|os.O_CREAT)
68 ret = os.write(fd, struct.pack(HISTORY_fmt[0], HISTORY_version, i))
69 ret += os.write(fd, struct.pack(HISTORY_fmt[1], *history))
73 def add_to_history((i, history), data):
76 i = i % HISTORY_LENGTH
79 def record_status_record(filename, status):
80 rh = read_safe_history(filename)
81 return write_safe_history(filename, add_to_history(rh, status))
83 def get_success_ratio(filename):
84 rh = read_safe_history(filename)
86 summary = rh[1][idx:] + rh[1][:idx]
87 measured = filter(lambda x: x != 0, summary)
88 if len(measured) == 0:
91 return float(len(filter(lambda x: x > 0, measured)))/float(len(measured))
95 def timeit(*args, **kw):
97 result = method(*args, **kw)
100 #print '%r (%r, %r) %2.2f sec' % \
101 # (method.__name__, args, kw, te-ts)
102 return (result, te-ts)
107 def check_dns(ip, protocol='udp'):
110 ro = DNS.Request(name="www.yahoo.com", qtype="A", server=ip)
111 r = ro.req(protocol=protocol)
113 except DNS.Base.DNSError, e:
117 def get_nameserver_ips(filename):
118 ip_re = re.compile("\d+\.\d+\.\d+\.\d+")
120 if not os.path.exists(filename):
123 f = open(filename, 'r')
125 if 'resolv' in filename:
127 for field in l.strip().split():
128 if ip_re.match(field) and field not in ret:
131 if 'ifcfg' in filename:
135 for field in l.strip().split('='):
136 field = field.replace('"', '')
137 field = field.replace("'", '')
138 if ip_re.match(field) and field not in ret:
144 root_ips = get_nameserver_ips('/etc/resolv.conf')
145 slice_ips = get_nameserver_ips( '/vservers/princeton_comon/etc/resolv.conf')
147 for i,ip in enumerate(root_ips.keys()):
148 (s,t) = check_dns(ip, 'udp')
149 if "Error" in s: t = -1
150 record_status_record("dns_history_root_udp%s.dat" % i, t)
152 (s,t) = check_dns(ip, 'tcp')
153 if "Error" in s: t = -1
154 record_status_record("dns_history_root_tcp%s.dat" % i, t)
156 for i,ip in enumerate(slice_ips.keys()):
157 (s,t) = check_dns(ip, 'udp')
158 if "Error" in s: t = -1
159 record_status_record("dns_history_slice_udp%s.dat" % i, t)
161 (s,t) = check_dns(ip, 'tcp')
162 if "Error" in s: t = -1
163 record_status_record("dns_history_slice_tcp%s.dat" % i, t)
165 if set(root_ips.keys()) == set(slice_ips.keys()):
166 print "CONF-ROOT_SLICE-MATCH",
168 print "CONF-ROOT_SLICE-MISMATCH",
169 #if set(root_ips.keys()) != set(slice_ips.keys()):
170 #if set(root_ips.keys()) != set(ifcfg_ips.keys()) and len(set(ifcfg_ips.keys())) > 0:
171 # print "CONF-IFCFG_ROOT-MISMATCH",
173 print get_success_ratio('dns_history_root_udp0.dat'),
174 print get_success_ratio('dns_history_root_udp1.dat'),
175 print get_success_ratio('dns_history_slice_udp0.dat'),
176 print get_success_ratio('dns_history_slice_udp1.dat'),
177 c_dns = os.popen("curl -s http://localhost:3121 | grep -a DNSFail").read().strip()
178 if len(c_dns) > 9 and "DNS" in c_dns:
179 c_dns = "cm " + c_dns[9:]
187 if __name__ == "__main__":
192 #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()