def traceroute(self, src_dst_list): LOG.info("Performing Netkit traceroutes for %s" % self.server.host) shell = self.server.get_shell() shell.setecho(False) resultant_paths = defaultdict(dict) #indexed format for presenting/analysis paths = [] # list format for plotting template_dir = resource_filename("AutoNetkit","lib/templates") linux_traceroute_template = open(os.path.join(template_dir, "textfsm", "linux_traceroute"), "r") # build reverse-IP lookup #TODO: move this into seperate helper function ip_mappings = {} #TODO: see if netaddr has a better way other than casting to string ip_mappings.update( dict( (str(device.lo_ip.ip), device) for device in self.network.devices())) for link in self.network.links(): ip_mappings[str(link.local_ip)] = link.local_host ip_mappings[str(link.remote_ip)] = link.remote_host #convert pairs list into 2-tuples, eg [1, 2, 3, 4, ...] -> (1, 2), (3, 4), ... label_pairs = [ (src_dst_list[i], src_dst_list[i+1]) for i in range(0, len(src_dst_list), 2)] for src_label, dst_label in label_pairs: try: src = self.network.find(src_label) except ank.network.DeviceNotFoundException: LOG.warn("Unable to find device %s" % src_label) continue try: dst = self.network.find(dst_label) except ank.network.DeviceNotFoundException: LOG.warn("Unable to find device %s" % dst_label) continue LOG.info("Tracing from %s to %s" % (src_label, dst_label)) self.server.connect_vm(src.tap_ip, shell) #TODO: make this handle appropriate ID for servers (no lo_ip) # TODO: probably be st to integrate into the device namedtuple for consistency shell.sendline("traceroute -n %s" % dst.lo_ip.ip) shell.expect(self.server.NETKIT_PROMPT) command_output = shell.before self.server.disconnect_vm(shell) shell.prompt() re_table = textfsm.TextFSM(linux_traceroute_template) route = re_table.ParseText(command_output) # conver to just the returned IPs route = [result[0] for result in route] # try lookups #TODO: put a try/except here, KeyError? resolved_route = [ip_mappings[host] for host in route] print "resolved route", resolved_route resultant_paths[src_label][dst_label] = resolved_route resolved_route.insert(0, src) paths.append(resolved_route) #pprint.pprint( resultant_paths) # format for plotting #TODO: enable/disable this from command line/function default print "plotting paths", paths ank.plot_paths(self.network, paths = paths)