Fixing issues with serialization
[nepi.git] / src / nepi / data / processing / ping / parser.py
1 #!/usr/bin/env python
2
3 ###############################################################################
4 #
5 #    CCNX benchmark
6 #    Copyright (C) 2014 INRIA
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 #
22 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
23 #
24 ###############################################################################
25
26 #
27 # This library contains functions to parse log files generated using ping. 
28 #
29
30 import re
31
32 # RE to match line starting "traceroute to"
33 _rre = re.compile("\d+ bytes from ((?P<hostname>[^\s]+) )?\(?(?P<ip>[^\s]+)\)??: icmp_.eq=\d+ ttl=\d+ time=(?P<time>[^\s]+) ms")
34
35 def parse_file(filename):
36     """
37         filename: path to traceroute file
38
39     """
40
41     f = open(filename, "r")
42
43     # Traceroute info
44     target_ip = None
45     target_hostname = None
46    
47     data = []
48
49     for line in f:
50         # match traceroute to ...
51         m = re.match(_rre, line)
52         if not m:
53             continue
54
55         target_ip = m.groupdict()["ip"]
56         # FIX THIS: Make sure the regular expression does not inlcude 
57         # the ')' in the ip group 
58         target_ip = target_ip.replace(")","")
59         target_hostname = m.groupdict()["hostname"]
60         time = m.groupdict()["time"]
61         data.append((target_ip, target_hostname, time))
62
63     f.close()
64
65     return data
66
67 def annotate_cn_node(graph, nid1, ips2nids, data):
68     for (target_ip, target_hostname, time) in data:
69         nid2 = ips2nid[target_ip]
70
71         if "delays" not in graph.edge[nid1][nid2]:
72             graph.edge[nid1][nid2]["delays"] = []
73
74         time = float(time.replace("ms", "").replace(" ",""))
75
76         graph.edge[nid1][nid2]["delays"].append(time)
77
78 def annotate_cn_graph(logs_dir, graph): 
79     """ Add delay inormation to graph using data collected using
80     ping.
81
82     """
83     ips2nids = dict()
84
85     for nid in graph.nodes():
86         ips = graph.node[nid]["ips"]
87         for ip in ips:
88             ips2nids[ip] = nid
89
90     # Walk through the ping logs...
91     for dirpath, dnames, fnames in os.walk(logs_dir):
92         # continue if we are not at the leaf level (if there are subdirectories)
93         if dnames: 
94             continue
95         
96         # Each dirpath correspond to a different host
97         nid = os.path.basename(dirpath)
98     
99         for fname in fnames:
100             if fname.endswith(".ping"):
101                 filename = os.path.join(dirpath, fname)
102                 data = parse_file(filename)
103                 annotate_cn_node(graph, nid, ips2nids, data)
104
105     # Take as weight the most frequent value
106     for nid1, nid2 in graph.edges():
107         delays = collections.Counter(graph.edge[nid1][nid2]["delays"])
108         weight = delays.most_common(1)[0][0]
109         del graph.edge[nid1][nid2]["delays"]
110         graph.edge[nid1][nid2]["weight"] = weight
111
112     return graph
113
114