added --tmp_dir to specify download directory and --no_geo to skip geolocation data

This commit is contained in:
ayeowch 2013-01-12 00:37:27 +08:00
commit 033fe8d54e

View file

@ -8,7 +8,7 @@ for each hop for a specified host from geographically distant source(s).
__author__ = 'Dazzlepod (info@dazzlepod.com)' __author__ = 'Dazzlepod (info@dazzlepod.com)'
__copyright__ = 'Copyright (c) 2013 Dazzlepod' __copyright__ = 'Copyright (c) 2013 Dazzlepod'
__version__ = '$Revision: #7 $' __version__ = '$Revision: #11 $'
import datetime import datetime
import json import json
@ -24,9 +24,11 @@ from subprocess import Popen, PIPE
class Traceroute(object): class Traceroute(object):
"""Traceroute instance.""" """Traceroute instance."""
def __init__(self, ip_address='8.8.8.8', debug=False): def __init__(self, ip_address='8.8.8.8', tmp_dir='/tmp', no_geo=False, debug=False):
super(Traceroute, self).__init__() super(Traceroute, self).__init__()
self.ip_address = ip_address self.ip_address = ip_address
self.tmp_dir = tmp_dir
self.no_geo = no_geo
self.debug = debug self.debug = debug
# cache geocoded IP addresses during the lifetime of this instance # cache geocoded IP addresses during the lifetime of this instance
self.locations = {} self.locations = {}
@ -34,17 +36,17 @@ class Traceroute(object):
def traceroute(self): def traceroute(self):
"""Instead of running the actual traceroute command, we will fetch """Instead of running the actual traceroute command, we will fetch
standard traceroute results from several publicly available webpages standard traceroute results from several publicly available webpages
that are listed at traceroute.org. that are listed at traceroute.org. For each hop, we will then attach
geolocation information to it."""
For each hop, we will then attach geolocation information to it."""
self.print_debug("ip_address = %s" % self.ip_address) self.print_debug("ip_address = %s" % self.ip_address)
if not os.path.exists('%s.txt' % self.ip_address): txt = os.path.join(self.tmp_dir, '%s.txt' % self.ip_address)
if not os.path.exists(txt):
(status_code, traceroute) = self.get_traceroute_output() (status_code, traceroute) = self.get_traceroute_output()
f = open('%s.txt' % self.ip_address, 'w') f = open(txt, 'w')
f.write(traceroute) f.write(traceroute)
f.close() f.close()
traceroute = open('%s.txt' % self.ip_address, 'r').read() traceroute = open(txt, 'r').read()
# hops = dicts with keys: hop_num, hosts # hops = dicts with keys: hop_num, hosts
hops = self.get_hops(traceroute) hops = self.get_hops(traceroute)
@ -52,11 +54,9 @@ class Traceroute(object):
# hops = dicts with keys: hop_num, hostname, ip_address, rtt # hops = dicts with keys: hop_num, hostname, ip_address, rtt
hops = self.get_formatted_hops(hops) hops = self.get_formatted_hops(hops)
# hops = dicts with keys: hop_num, hostname, ip_address, rtt, location if not self.no_geo:
hops = self.get_geocoded_hops(hops) # hops = dicts with keys: hop_num, hostname, ip_address, rtt, latitude, longitude
hops = self.get_geocoded_hops(hops)
# hops = dicts with keys: hop_num, ip_address, latitude, longitude, rtt
hops = self.get_stripped_hops(hops)
return hops return hops
@ -119,36 +119,29 @@ class Traceroute(object):
def get_geocoded_hops(self, hops): def get_geocoded_hops(self, hops):
"""Return hops from get_formatted_hops() with geolocation information """Return hops from get_formatted_hops() with geolocation information
for each hop.""" for each hop."""
geocoded_hops = []
for hop in hops: for hop in hops:
ip_address = hop['ip_address'] ip_address = hop['ip_address']
location = None location = None
if self.locations.has_key(ip_address): if self.locations.has_key(ip_address):
location = self.locations[ip_address] location = self.locations[ip_address]
else: else:
location = self.get_location(ip_address) location = self.get_location(ip_address)
self.locations[ip_address] = location self.locations[ip_address] = location
hop['location'] = location
return hops if location:
geocoded_hops.append({
def get_stripped_hops(self, hops):
""" Return hops from get_geocoded_hops() with each dict containing
data ready for plotting with e.g. Google Maps JavaScript API."""
stripped_hops = []
for hop in hops:
if hop['location']:
lat = hop['location']['latitude']
lon = hop['location']['longitude']
stripped_hops.append({
'hop_num': hop['hop_num'], 'hop_num': hop['hop_num'],
'hostname': hop['hostname'],
'ip_address': hop['ip_address'], 'ip_address': hop['ip_address'],
'latitude': lat,
'longitude': lon,
'rtt': hop['rtt'], 'rtt': hop['rtt'],
'latitude': location['latitude'],
'longitude': location['longitude'],
}) })
return stripped_hops return geocoded_hops
def get_location(self, ip_address): def get_location(self, ip_address):
"""Return geolocation information for the specified IP address, e.g.: """Return geolocation information for the specified IP address, e.g.:
@ -171,7 +164,7 @@ class Traceroute(object):
location = tmp_location location = tmp_location
return location return location
def urlopen(self, url, context = None): def urlopen(self, url, context=None):
"""Perform HTTP GET/POST on the specified URL and return the resultant """Perform HTTP GET/POST on the specified URL and return the resultant
status code and response. status code and response.
""" """
@ -208,15 +201,16 @@ class Traceroute(object):
def main(): def main():
usage = """%prog --ip_address=IP_ADDRESS""" usage = """%prog --ip_address=IP_ADDRESS"""
cmdparser = optparse.OptionParser(usage, version=("traceroute " + __version__)) cmdparser = optparse.OptionParser(usage, version=("traceroute " + __version__))
cmdparser.add_option("-i", "--ip_address", type="string", default="", help="IP address of destination host") cmdparser.add_option("-i", "--ip_address", type="string", default="8.8.8.8", help="IP address of destination host (default: 8.8.8.8)")
cmdparser.add_option("-d", "--debug", action="store_true", default=False, help="Show debug output") cmdparser.add_option("-t", "--tmp_dir", type="string", default="/tmp", help="Temporary directory to store downloaded traceroute results (default: /tmp)")
cmdparser.add_option("-n", "--no_geo", action="store_true", default=False, help="No geolocation data (default: False)")
cmdparser.add_option("-d", "--debug", action="store_true", default=False, help="Show debug output (default: False)")
(options, args) = cmdparser.parse_args() (options, args) = cmdparser.parse_args()
if options.ip_address: if options.ip_address:
traceroute = Traceroute(ip_address=options.ip_address, debug=options.debug) traceroute = Traceroute(ip_address=options.ip_address, tmp_dir=options.tmp_dir, no_geo=options.no_geo, debug=options.debug)
hops = traceroute.traceroute() hops = traceroute.traceroute()
hops = json.dumps(hops, indent=2)
print hops print hops
else: else:
cmdparser.print_usage() cmdparser.print_usage()