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