- made progress on self hop parser

This commit is contained in:
Brian Martin 2015-07-14 11:10:17 -04:00
commit 1d168d48f6

View file

@ -41,7 +41,7 @@ class Traceroute(object):
self.timeout = timeout self.timeout = timeout
self.debug = debug self.debug = debug
self.locations = {} self.locations = {}
self.hops = [] self.hops = {}
self.country = country self.country = country
# Localhost Specific operations happen here # Localhost Specific operations happen here
@ -81,15 +81,11 @@ class Traceroute(object):
open(filepath, "w").write(traceroute) open(filepath, "w").write(traceroute)
traceroute = open(filepath, "r").read() traceroute = open(filepath, "r").read()
# hop_num, hosts self.__get_hops(traceroute)
hops = self.__get_hops(traceroute)
# hop_num, hostname, ip_address, rtt
self.hops = self.__get_formatted_hops()
if not self.no_geo: #if not self.no_geo:
# hop_num, hostname, ip_address, rtt, latitude, longitude # self.__get_geocoded_hops()
self.hops = self.__get_geocoded_hops()
#self.hops = map(lambda h: {h.pop("hop_num") : h}, self.hops) #self.hops = map(lambda h: {h.pop("hop_num") : h}, self.hops)
@ -121,70 +117,73 @@ class Traceroute(object):
""" """
Returns hops from traceroute output in an array of dicts each Returns hops from traceroute output in an array of dicts each
with hop number and the associated hosts data. with hop number and the associated hosts data.
"""
regex = r'^(?P<hop_num>\d+)(?P<hosts>.*?)$'
lines = traceroute.split("\n")
for line in lines:
line = line.strip()
hop = {}
if not line:
continue
try:
hop = re.match(regex, line).groupdict()
except AttributeError:
continue
self.print_debug(hop)
self.hops.append(hop)
def __get_formatted_hops(self):
"""
Hosts data from get_hops() is represented in a single string.
We use this function to better represent the hosts data in a dict.
"""
formatted_hops = []
regex = r'(?P<h>[\w.-]+) \((?P<i>[\d.]+)\) (?P<r>\d{1,4}.\d{1,4} ms)'
for hop in self.hops:
hop_num = int(hop['hop_num'].strip())
hosts = hop['hosts'].replace(" ", " ").strip()
# Using re.findall(), we split the hosts, then for each host,
# we store a tuple of hostname, IP address and the first RTT.
hosts = re.findall(regex, hosts)
for host in hosts:
hop_context = { hop_context = {
'hop_num': hop_num, 'hop_num': hop_num,
'hostname': host[0], 'hostname': host[0],
'ip_address': host[1], 'ip_address': host[1],
'rtt': host[2], 'rtt': host[2],
} }
self.print_debug(hop_context) """
formatted_hops.append(hop_context) # This breaks up the line into hop num => host data
return formatted_hops #hop_pattern = '^(?P<hop_num>\w+)\s+(?P<hosts>.*)'
hop_pattern = '^(?P<hop_num>[0-9]+)\s+(?P<hosts>.*)'
# This matches hosts which are ip or dns mapped
host_pattern = '([\d\w.]+\s+\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)\s+\d+\.\d+ ms)'
# This is essentially the same as the previous pattern but breaks into usable chunks
hop_element_pattern = '([\d\w.]+)\s+\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\)\s+(\d+\.\d+ ms)'
hp = re.compile(hop_element_pattern)
for entry in traceroute.split('\n'):
entry = entry.strip()
result = re.match(hop_pattern,entry)
if result is None: # should only fail on first line
continue
hop = result.groupdict()
hop_num = int(hop['hop_num'])
hop_hosts = re.findall(host_pattern, hop['hosts'])
self.hops[hop_num] = []
for host in hop_hosts:
m = hp.search(host)
(hostname, ip, ping_time) = m.groups()
if self.no_geo:
self.hops[hop_num].append(
{
'hostname' : hostname,
'ip_address' : ip,
'rtt' : ping_time
}
)
else:
location = self.__get_geocoded_data(ip)
if location:
self.hops[hop_num].append(
{
'hostname' : hostname,
'ip_address' : ip,
'rtt' : ping_time,
'latitude' : location['latitude'],
'longitude' : location['longitude']
}
)
def __get_geocoded_hops(self):
def __get_geocoded_data(self, ip_address):
""" """
Returns hops from get_formatted_hops() with geolocation information Returns a location hash with long/lat for a particular IP address
for each hop.
""" """
geocoded_hops = [] location = None
for hop in self.hops: if ip_address in self.locations:
ip_address = hop['ip_address'] location = self.locations[ip_address]
location = None else:
if ip_address in self.locations: location = self.get_location(ip_address)
location = self.locations[ip_address] self.locations[ip_address] = location
else:
location = self.get_location(ip_address) return location
self.locations[ip_address] = location
if location:
geocoded_hops.append({
'hop_num': hop['hop_num'],
'hostname': hop['hostname'],
'ip_address': hop['ip_address'],
'rtt': hop['rtt'],
'latitude': location['latitude'],
'longitude': location['longitude'],
})
return geocoded_hops
def get_location(self, ip_address): def get_location(self, ip_address):
""" """