def plot(self, matplotlib=False): """Plot the network topology Args: None Returns: None Example usage: >>> inet = ank.internet.Internet() >>> inet.plot() """ LOG.info("Plotting") matplotlib = matplotlib or config.settings['Plotting']['matplotlib'] if matplotlib: ank.plot(self.network) ank.jsplot(self.network) ank.summarydoc(self.network) ank.dump_graph(self.network.graph, os.path.join(config.log_dir, "physical")) physical_single_edge = nx.Graph(self.network.graph) ank.dump_graph(physical_single_edge, os.path.join(config.log_dir, "physical_single_edge")) ibgp_graph = ank.get_ibgp_graph(self.network) ebgp_graph = ank.get_ebgp_graph(self.network) ank.dump_graph(ibgp_graph, os.path.join(config.log_dir, "ibgp")) ank.dump_graph(ebgp_graph, os.path.join(config.log_dir, "ebgp")) g_dns = nx.Graph(self.network.g_dns) ank.dump_graph(g_dns, os.path.join(config.log_dir, "dns")) ank.dump_graph(self.network.g_dns_auth, os.path.join(config.log_dir, "dns_auth")) ank.dump_identifiers(self.network, os.path.join(config.log_dir, "identifiers.txt"))
def configure_junos(self): """ Configures Junos""" LOG.info("Configuring Junos: %s" % self.target) junos_template = lookup.get_template("junos/junos.mako") ank_version = pkg_resources.get_distribution("AutoNetkit").version date = time.strftime("%Y-%m-%d %H:%M", time.localtime()) physical_graph = self.network.graph igp_graph = ank.igp_graph(self.network) ibgp_graph = ank.get_ibgp_graph(self.network) ebgp_graph = ank.get_ebgp_graph(self.network) #TODO: correct this router type selector for router in self.network.routers(): #check interfaces feasible if self.network.graph.in_degree(router) > self.interface_limit: LOG.warn("%s exceeds interface count: %s (max %s)" % (self.network.label(router), self.network.graph.in_degree(router), self.interface_limit)) asn = self.network.asn(router) network_list = [] lo_ip = self.network.lo_ip(router) interfaces,static_routes = self.configure_interfaces(router) igp_interfaces = self.configure_igp(router, igp_graph,ebgp_graph) (bgp_groups, policy_options) = self.configure_bgp(router, physical_graph, ibgp_graph, ebgp_graph) # advertise AS subnet adv_subnet = self.network.ip_as_allocs[asn] if not adv_subnet in network_list: network_list.append(adv_subnet) juniper_filename = router_conf_path(self.network, router) with open( juniper_filename, 'wb') as f_jun: f_jun.write( junos_template.render( hostname = router.rtr_folder_name, username = '******', interfaces=interfaces, static_routes=static_routes, igp_interfaces=igp_interfaces, igp_protocol = self.igp, asn = asn, lo_ip=lo_ip, router_id = lo_ip.ip, network_list = network_list, bgp_groups = bgp_groups, policy_options = policy_options, ank_version = ank_version, date = date, ))
def configure_ios(self): """ Configures IOS""" LOG.info("Configuring IOS") ios_template = lookup.get_template("cisco/ios.mako") ank_version = pkg_resources.get_distribution("AutoNetkit").version date = time.strftime("%Y-%m-%d %H:%M", time.localtime()) physical_graph = self.network.graph igp_graph = ank.igp_graph(self.network) ibgp_graph = ank.get_ibgp_graph(self.network) ebgp_graph = ank.get_ebgp_graph(self.network) for router in self.network.routers(): #check interfaces feasible #TODO: make in_degree a property eg link_count asn = self.network.asn(router) network_list = [] lo_ip = self.network.lo_ip(router) interfaces = self.configure_interfaces(router) igp_interfaces = self.configure_igp(router, igp_graph,ebgp_graph) (bgp_groups, policy_options) = self.configure_bgp(router, physical_graph, ibgp_graph, ebgp_graph) # advertise AS subnet adv_subnet = self.network.ip_as_allocs[asn] if not adv_subnet in network_list: network_list.append(adv_subnet) juniper_filename = router_conf_path(self.network, router) with open( juniper_filename, 'wb') as f_jun: f_jun.write( ios_template.render( hostname = router.rtr_folder_name, username = '******', interfaces=interfaces, igp_interfaces=igp_interfaces, igp_protocol = self.igp, # explicit protocol use_isis = self.igp == 'isis', asn = asn, lo_ip=lo_ip, #TODO: make router have property "identifier" which maps to lo_ip router_id = lo_ip.ip, network_list = network_list, bgp_groups = bgp_groups, policy_options = policy_options, ank_version = ank_version, date = date, ))
def plot(network, show=False, save=True): """ Plot the network """ try: import matplotlib.pyplot as plt except ImportError: LOG.warn("Matplotlib not found, not plotting using Matplotlib") return try: import numpy except ImportError: LOG.warn("Matplotlib plotting requires numpy for graph layout") return plot_dir = config.plot_dir if not os.path.isdir(plot_dir): os.mkdir(plot_dir) graph = network.graph pos=nx.spring_layout(graph) # Different node color for each AS. Use heatmap based on ASN plot_graph(graph, title="Network", pos=pos, show=show, save=save, node_color=cmap_index(network, graph)) graph = ank.get_ebgp_graph(network) labels = dict( (n, network.label(n)) for n in graph) plot_graph(graph, title="eBGP", pos=pos, labels=labels, show=show, save=save) graph = ank.get_ibgp_graph(network) labels = dict( (n, network.label(n)) for n in graph) plot_graph(graph, title="iBGP", pos=pos, labels=labels, show=show, save=save) graph = ank.get_dns_graph(network) labels = dict( (n, network.label(n)) for n in graph) plot_graph(graph, title="DNS", pos=pos, labels=labels, show=show, save=save)
def configure(self): """Configure C-BGP""" LOG.info("Configuring C-BGP") self.initialise() default_weight = 1 template = lookup.get_template("cbgp/cbgp.mako") physical_graph = self.network.graph igp_graph = ank.igp_graph(self.network) ibgp_graph = ank.get_ibgp_graph(self.network) ebgp_graph = ank.get_ebgp_graph(self.network) as_graphs = ank.get_as_graphs(self.network) ip_as_allocs = ank.get_ip_as_allocs(self.network) # Allocs for ebgp announcements physical_topology = defaultdict(dict) ibgp_topology = {} igp_topology = {} ebgp_topology = {} ebgp_prefixes = {} bgp_routers = {} # Fast lookup of loopbacks - the unique router ID for cBGP loopback = dict( (n, self.network.lo_ip(n).ip) for n in physical_graph) # Physical topology for as_graph in as_graphs: asn = as_graph.name physical_topology[asn]['nodes'] = [loopback[n] for n in as_graph] physical_topology[asn]['links'] = [ (loopback[s], loopback[t]) for (s,t) in unidirectional(as_graph.edges())] # Interdomain links interdomain_links = [ (loopback[s], loopback[t]) for (s,t) in unidirectional(ebgp_graph.edges())] #IGP configuration for as_graph in as_graphs: asn = as_graph.name igp_topology[asn] = {} # Subgraph of IGP graph for this AS as_igp_graph = igp_graph.subgraph(as_graph.nodes()) igp_topology[asn]['nodes'] = [loopback[n] for n in as_igp_graph] igp_topology[asn]['links'] = [ (loopback[s], loopback[t], data.get('weight', default_weight)) for (s,t,data) in (as_graph.edges(data=True))] # iBGP configuration #TODO: if ibgp graph is a clique then use "bgp domain 1 full-mesh" where 1 is asn # use nx.graph_clique_number(G) and compare to size of G, if same then is a clique # otherwise create ibgp session by session #TODO: add support for non full-mesh (need to find documentation on this) for as_graph in as_graphs: asn = as_graph.name for router in as_graph: if not router.is_router: continue if router not in ibgp_graph: # likely single node AS continue ibgp_topology[router] = [] for peer in ibgp_graph.neighbors(router): ibgp_topology[router].append(peer) bgp_routers[asn] = [n.lo_ip.ip for n in ank.bgp_routers(self.network) if n.asn == asn] # eBGP configuration for node in ebgp_graph.nodes(): node_id = loopback[node] peers = [] for peer in ebgp_graph.neighbors(node): peers.append( (self.network.asn(peer), loopback[peer])) ebgp_topology[node_id] = peers # Prefixes to originate adv_subnet = ip_as_allocs[self.network.asn(node)] ebgp_prefixes[node_id] = adv_subnet #TODO: see if can just do for node in ebgp_graph ie without the .nodes() on end # bgp policy bgp_policy = {} for router in self.network.routers(): for peer in self.network.g_session.neighbors(router): pol_egress = self.network.g_session[router][peer]['egress'] pol_ingress = self.network.g_session[peer][router]['ingress'] if len(pol_ingress) or len(pol_egress): try: bgp_policy[router][peer] = { 'ingress': pol_ingress, 'egress': pol_egress, } except KeyError: bgp_policy[router] = {} bgp_policy[router][peer] = { 'ingress': pol_ingress, 'egress': pol_egress, } # tags dict for mapping from tag to community value, and for prefixes tags = self.network.g_session.graph['tags'] prefixes = self.network.g_session.graph['prefixes'] with open( cbgp_file(), 'w') as f_cbgp: f_cbgp.write( template.render( physical_topology = physical_topology, interdomain_links = interdomain_links, igp_topology = igp_topology, ibgp_topology = ibgp_topology, ebgp_topology = ebgp_topology, ebgp_prefixes = ebgp_prefixes, bgp_routers = bgp_routers, bgp_policy = bgp_policy, tags = tags, prefixes = prefixes, ))
def configure_bgp(self): """Generates BGP specific configuration files""" ip_as_allocs = ank.get_ip_as_allocs(self.network) LOG.debug("Configuring BGP") template = lookup.get_template("quagga/bgp.mako") route_maps = {} ibgp_graph = ank.get_ibgp_graph(self.network) ebgp_graph = ank.get_ebgp_graph(self.network) physical_graph = self.network.graph for my_as in ank.get_as_graphs(self.network): asn = my_as.asn LOG.debug("Configuring IGP for AS %s " % asn) # get nodes ie intersection #H = nx.intersection(my_as, ibgp_graph) # get ibgp graph that contains only nodes from this AS for router in self.network.routers(asn): bgp_groups = {} route_maps = [] ibgp_neighbor_list = [] ibgp_rr_client_list = [] route_map_groups = {} if router in ibgp_graph: for src, neigh, data in ibgp_graph.edges(router, data=True): route_maps_in = self.network.g_session[neigh][router]['ingress'] rm_group_name_in = None if len(route_maps_in): rm_group_name_in = "rm_%s_in" % neigh.folder_name route_map_groups[rm_group_name_in] = [match_tuple for route_map in route_maps_in for match_tuple in route_map.match_tuples] route_maps_out = self.network.g_session[router][neigh]['egress'] rm_group_name_out = None if len(route_maps_out): rm_group_name_in = "rm_%s_out" % neigh.folder_name route_map_groups[rm_group_name_out] = [match_tuple for route_map in route_maps_out for match_tuple in route_map.match_tuples] description = data.get("rr_dir") + " to " + ank.fqdn(self.network, neigh) if data.get('rr_dir') == 'down': ibgp_rr_client_list.append( { 'id': self.network.lo_ip(neigh).ip, 'description': description, 'route_maps_in': rm_group_name_in, 'route_maps_out': rm_group_name_out, }) elif (data.get('rr_dir') in set(['up', 'over', 'peer']) or data.get('rr_dir') is None): ibgp_neighbor_list.append( { 'id': self.network.lo_ip(neigh).ip, 'description': description, 'route_maps_in': rm_group_name_in, 'route_maps_out': rm_group_name_out, }) bgp_groups['internal_peers'] = { 'type': 'internal', 'neighbors': ibgp_neighbor_list } if len(ibgp_rr_client_list): bgp_groups['internal_rr'] = { 'type': 'internal', 'neighbors': ibgp_rr_client_list, 'cluster': self.network.lo_ip(router).ip, } if router in ebgp_graph: external_peers = [] for peer in ebgp_graph.neighbors(router): route_maps_in = self.network.g_session[peer][router]['ingress'] rm_group_name_in = None if len(route_maps_in): rm_group_name_in = "rm_%s_in" % peer.folder_name route_map_groups[rm_group_name_in] = [match_tuple for route_map in route_maps_in for match_tuple in route_map.match_tuples] # Now need to update the sequence numbers for the flattened route maps route_maps_out = self.network.g_session[router][peer]['egress'] rm_group_name_out = None if len(route_maps_out): rm_group_name_out = "rm_%s_out" % peer.folder_name route_map_groups[rm_group_name_out] = [match_tuple for route_map in route_maps_out for match_tuple in route_map.match_tuples] peer_ip = physical_graph[peer][router]['ip'] external_peers.append({ 'id': peer_ip, 'route_maps_in': rm_group_name_in, 'route_maps_out': rm_group_name_out, 'peer_as': self.network.asn(peer)}) bgp_groups['external_peers'] = { 'type': 'external', 'neighbors': external_peers} # Ensure only one copy of each route map, can't use set due to list inside tuples (which won't hash) # Use dict indexed by name, and then extract the dict items, dict hashing ensures only one route map per name community_lists = {} prefix_lists = {} node_bgp_data = self.network.g_session.node.get(router) if node_bgp_data: community_lists = node_bgp_data.get('tags') prefix_lists = node_bgp_data.get('prefixes') policy_options = { 'community_lists': community_lists, 'prefix_lists': prefix_lists, 'route_maps': route_map_groups, } f_handle = open(os.path.join(zebra_dir(self.network, router), "bgpd.conf"),'wb') #TODO: remove community_lists and prefix_lists as they are put into policy_options f_handle.write(template.render( hostname = router.device_hostname, asn = self.network.asn(router), password = self.zebra_password, enable_password = self.zebra_password, router_id = self.network.lo_ip(router).ip, community_lists = community_lists, policy_options = policy_options, prefix_lists = prefix_lists, #TODO: see how this differs to router_id identifying_loopback = self.network.lo_ip(router), bgp_groups = bgp_groups, ibgp_neighbor_list = ibgp_neighbor_list, ibgp_rr_client_list = ibgp_rr_client_list, route_maps = route_maps, logfile = "/var/log/zebra/bgpd.log", debug=True, use_debug=True, dump=False, snmp=False, interfaces = self.configure_interfaces(router) ))
def plot(network, show=False, save=True): """ Plot the network """ try: import matplotlib.pyplot as plt except ImportError: LOG.warn("Matplotlib not found, not plotting using Matplotlib") return try: import numpy except ImportError: LOG.warn("Matplotlib plotting requires numpy for graph layout") return plot_dir = config.plot_dir if not os.path.isdir(plot_dir): os.mkdir(plot_dir) graph = network.graph try: #Extract co-ordinates to normalize (needed for PathDrawer, desired for neatness in plots) x, y = zip(*[(d['x'], d['y']) for n, d in network.graph.nodes(data=True)]) x = numpy.asarray(x, dtype=float) y = numpy.asarray(y, dtype=float) #TODO: combine these two operations together x -= x.min() x *= 1.0/x.max() y -= y.min() y *= -1.0/y.max() # invert y += 1 # rescale from 0->1 not 1->0 #TODO: see if can use reshape-type commands here co_ords = zip(list(x), list(y)) co_ords = [numpy.array([x, y]) for x, y in co_ords] nodes = [n for n in network.graph.nodes()] pos = dict( zip(nodes, co_ords)) except: pos=nx.spring_layout(graph) # Different node color for each AS. Use heatmap based on ASN paths = [] #paths.append( nx.shortest_path(network.graph, network.find("1a.AS1"), network.find("1c.AS1"))) #paths.append( nx.shortest_path(network.graph, network.find("1b.AS1"), network.find("1c.AS1"))) #paths.append(nx.shortest_path(network.graph, network.find("1a.AS1"), network.find("2c.AS2"))) #paths.append( nx.shortest_path(network.graph, network.find("as100r3.AS100"), network.find("as300r1.AS300"))) #paths.append(nx.shortest_path(network.graph, network.find("as100r2.AS100"), network.find("as30r1.AS30"))) #Node colors legend = { 'shapes': [], 'labels': [], } colormap = cm.jet unique_asn = sorted(list(set(d.asn for d in network.devices()))) asn_norm = colors.normalize(0, len(unique_asn)) asn_colors = dict.fromkeys(unique_asn) for index, asn in enumerate(asn_colors.keys()): asn_color = colormap(asn_norm(index)) #allocate based on index position asn_colors[asn] = asn_color legend['shapes'].append( plt.Rectangle((0, 0), 0.51, 0.51, fc = asn_color)) legend['labels'].append( asn) node_colors = [asn_colors[device.asn] for device in network.devices()] plot_graph(graph, title="Network", pos=pos, show=show, save=save, node_color=node_colors) plot_graph(graph, title="Paths", pos=pos, show=show, save=save, legend_data = legend, paths = paths, node_color=node_colors) graph = ank.get_ebgp_graph(network) labels = dict( (n, network.label(n)) for n in graph) plot_graph(graph, title="eBGP", pos=pos, labels=labels, show=show, save=save) graph = ank.get_ibgp_graph(network) labels = dict( (n, network.label(n)) for n in graph) plot_graph(graph, title="iBGP", pos=pos, labels=labels, show=show, save=save) graph = ank.get_dns_graph(network) labels = dict( (n, network.label(n)) for n in graph) plot_graph(graph, title="DNS", pos=pos, labels=labels, show=show, save=save)
def jsplot(network): """ Plot the network """ plot_dir = config.plot_dir if not os.path.isdir(plot_dir): os.mkdir(plot_dir) jsplot_dir = os.path.join(plot_dir, "jsplot") if not os.path.isdir(jsplot_dir): os.mkdir(jsplot_dir) js_template = lookup.get_template("arborjs/main_js.mako") css_template = lookup.get_template("arborjs/style_css.mako") html_template = lookup.get_template("arborjs/index_html.mako") ank_css_template = lookup.get_template("autonetkit/style_css.mako") #TODO: tidy these up with the embedded network in node name node_list = ( (node.fqdn, {'label': network.fqdn(node)}) for node in network.graph.nodes()) edge_list = list( (src.fqdn, dst.fqdn, {}) for (src, dst, data) in network.graph.edges(data=True)) js_files = [] timestamp = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime()) js_filename = os.path.join(jsplot_dir, "main.js") js_files.append("main.js") with open( js_filename, 'w') as f_js: f_js.write( js_template.render( node_list = node_list, edge_list = edge_list, physical_graph = True, )) js_filename = os.path.join(jsplot_dir, "ip.js") js_files.append("ip.js") node_list = [] for node in network.graph.nodes(): # Set label to be FQDN, so don't have multiple "Router A" nodes etc data = { 'label': "%s %s" % (ank.fqdn(network, node), network.lo_ip(node).ip)} node_list.append( (node.fqdn, data)) edge_list = list( (src.fqdn, dst.fqdn, data['sn']) for (src, dst, data) in network.graph.edges(data=True)) with open( js_filename, 'w') as f_js: f_js.write( js_template.render( node_list = node_list, edge_list = edge_list, physical_graph = True, )) js_filename = os.path.join(jsplot_dir, "igp.js") js_files.append("igp.js") node_list = [] for node in network.graph.nodes(): if not node.igp_link_count: # no IGP links, don't add to plot continue # Set label to be FQDN, so don't have multiple "Router A" nodes etc data = { 'label': "%s" % node.fqdn} node_list.append( (node.fqdn, data)) edge_list = list( (src.fqdn, dst.fqdn, data.get('weight')) for (src, dst, data) in network.graph.edges(data=True) if src.asn == dst.asn) with open( js_filename, 'w') as f_js: f_js.write( js_template.render( node_list = node_list, edge_list = edge_list, physical_graph = True, )) #TODO: work out how to do multiple on one page ebgp_graph = ank.get_ebgp_graph(network) labels = dict( (n, network.label(n)) for n in ebgp_graph) nx.relabel_nodes(ebgp_graph, labels, copy=False) ebgp_filename = os.path.join(jsplot_dir, "ebgp.js") js_files.append("ebgp.js") with open( ebgp_filename, 'w') as f_js: f_js.write( js_template.render( node_list = ebgp_graph.nodes(data=True), edge_list = ebgp_graph.edges(data=True), overlay_graph = True, )) ibgp_graph = ank.get_ibgp_graph(network) node_list = [] for node in ibgp_graph.nodes(): # Set label to be FQDN, so don't have multiple "Router A" nodes etc data = { 'label': "%s (%s)" % (node.fqdn, network.graph.node[node].get("ibgp_level"))} node_list.append( (node.fqdn, data)) edge_list = ibgp_graph.edges(data=True) edge_list = list( (src.fqdn, dst.fqdn, data.get("rr_dir")) for (src, dst, data) in edge_list) ibgp_filename = os.path.join(jsplot_dir, "ibgp.js") js_files.append("ibgp.js") with open( ibgp_filename, 'w') as f_js: f_js.write( js_template.render( node_list = node_list, edge_list = edge_list, physical_graph = True, )) #TODO: clarify difference of physical_graph and overlay_graph #TODO: see if js_files ever used dns_graph = ank.get_dns_graph(network) node_list = [] for node in dns_graph.nodes(): # Set label to be FQDN, so don't have multiple "Router A" nodes etc data = { 'label': "%s (%s)" % (node.fqdn, dns_graph.node[node].get("level"))} node_list.append( (node.fqdn, data)) dns_filename = os.path.join(jsplot_dir, "dns.js") edge_list = dns_graph.edges(data=True) #edge_list = list( (src.fqdn, dst.fqdn, data.get('dns_dir')) for (src, dst, data) in edge_list) edge_list = list( (src.fqdn, dst.fqdn, '') for (src, dst, data) in edge_list) js_files.append("dns.js") with open( dns_filename, 'w') as f_js: f_js.write( js_template.render( node_list = node_list, edge_list = edge_list, physical_graph = True, )) dns_auth_graph = ank.get_dns_auth_graph(network) node_list = [] for node in dns_auth_graph.nodes(): # Set label to be FQDN, so don't have multiple "Router A" nodes etc data = { 'label': "%s" % node.label} node_list.append( (node.fqdn, data)) dns_filename = os.path.join(jsplot_dir, "dns_auth.js") edge_list = dns_auth_graph.edges(data=True) edge_list = list( (src.fqdn, dst.fqdn, data) for (src, dst, data) in edge_list) js_files.append("dns_auth.js") with open( dns_filename, 'w') as f_js: f_js.write( js_template.render( node_list = node_list, edge_list = edge_list, physical_graph = True, )) #TODO: add timestamps to plots # put html file in main plot directory #TODO: parameterised/variable the css location plot_width = config.settings['Plotting']['jsplot width'] plot_height = config.settings['Plotting']['jsplot height'] html_filename = os.path.join(plot_dir, "plot.html") with open( html_filename, 'w') as f_html: f_html.write( html_template.render( js_file = "main.js", timestamp=timestamp, plot_width = plot_width, plot_height = plot_height, title = "Physical Network", css_filename = "./ank_style.css",)) html_filename = os.path.join(plot_dir, "ip.html") with open( html_filename, 'w') as f_html: f_html.write( html_template.render( js_file = "ip.js", timestamp=timestamp, plot_width = plot_width, plot_height = plot_height, title = "IP", css_filename = "./ank_style.css",)) html_filename = os.path.join(plot_dir, "igp.html") with open( html_filename, 'w') as f_html: f_html.write( html_template.render( js_file = "igp.js", timestamp=timestamp, plot_width = plot_width, plot_height = plot_height, title = "IGP", css_filename = "./ank_style.css",)) html_filename = os.path.join(plot_dir, "ibgp.html") with open( html_filename, 'w') as f_html: f_html.write( html_template.render( js_file = "ibgp.js", timestamp=timestamp, plot_width = plot_width, plot_height = plot_height, title = "iBGP", css_filename = "./ank_style.css",)) html_filename = os.path.join(plot_dir, "ebgp.html") with open( html_filename, 'w') as f_html: f_html.write( html_template.render( js_file = "ebgp.js", timestamp=timestamp, plot_width = plot_width, plot_height = plot_height, title = "eBGP", css_filename = "./ank_style.css",)) html_filename = os.path.join(plot_dir, "dns.html") with open( html_filename, 'w') as f_html: f_html.write( html_template.render( js_file = "dns.js", timestamp=timestamp, plot_width = plot_width, plot_height = plot_height, title = "DNS Hierarchy", css_filename = "./ank_style.css",)) html_filename = os.path.join(plot_dir, "dns_auth.html") with open( html_filename, 'w') as f_html: f_html.write( html_template.render( js_file = "dns_auth.js", timestamp=timestamp, plot_width = plot_width, plot_height = plot_height, title = "DNS Authority", css_filename = "./ank_style.css",)) css_filename = os.path.join(jsplot_dir, "style.css") with open( css_filename, 'w') as f_css: f_css.write( css_template.render()) # and ank css_template css_filename = os.path.join(plot_dir, "ank_style.css") with open( css_filename, 'w') as f_css: f_css.write( ank_css_template.render()) arbor_js_src_filename = os.path.join(template_dir, "arborjs", "arbor.js") arbor_js_dst_filename = os.path.join(jsplot_dir, "arbor.js") shutil.copy(arbor_js_src_filename, arbor_js_dst_filename)
def configure_rpki(self): """ Configures RPKI servers""" LOG.info("Configuring RPKI servers: %s" % self.target) rpki_template = lookup.get_template("junos/rpki.mako") yaml_template = lookup.get_template("junos/yaml.mako") ank_version = pkg_resources.get_distribution("AutoNetkit").version date = time.strftime("%Y-%m-%d %H:%M", time.localtime()) physical_graph = self.network.graph igp_graph = ank.igp_graph(self.network) ibgp_graph = ank.get_ibgp_graph(self.network) ebgp_graph = ank.get_ebgp_graph(self.network) as_prefixes = defaultdict(list) rpki_tree = defaultdict(dict) rpki_server_list = [] for router in self.network.graph.nodes(): # collect prefixes of the AS as_number = str(self.network.asn(router)) lo_ip = self.network.lo_ip(router) lo_ip_ip = str(lo_ip.ip) lo_ip_prefixlen = str(lo_ip.prefixlen) loopback_ip = str(lo_ip_ip+"/"+lo_ip_prefixlen) as_prefixes[as_number].append(loopback_ip) for src, dst, data in self.network.graph.edges(router, data=True): subnet = str(data['sn']) if not subnet in as_prefixes[as_number]: as_prefixes[as_number].append(subnet) rpki_root_lst = [n for n in self.network.g_rpki.nodes() if 'root' in self.network.rpki_root(n)] if len(rpki_root_lst) > 1: LOG.warn("%s rpki_root servers configured, only one is allowed" %len(rpki_root_lst)) rpki_root_str = ', '.join(rpki_root_lst) rpki_root_folder = ''.join([n if not "." in n else "_" for n in rpki_root_str]) for rpki_server in self.network.rpki_servers(): #check interfaces feasible rpki_children = {} asn = self.network.asn(rpki_server) rpki_aggregate = self.network.ip_as_allocs[asn] rpki_server_list.append(rpki_server) rpki_tree[rpki_server] = defaultdict(dict) rpki_tree[rpki_server]['fqdn'] = rpki_server for neighbor in self.network.g_rpki.neighbors(str(rpki_server)): nbr_list = [n for n in neighbor] # # check the relationships between rpki nodes relationship = self.network.g_rpki.get_edge_data(str(rpki_server), str(neighbor)) if 'children' in relationship['relation']: rpki_tree[rpki_server]['children'][neighbor] = defaultdict(dict) rpki_tree[rpki_server]['children'][neighbor]['asn'] = self.network.asn(neighbor) rpki_tree[rpki_server]['children'][neighbor]['rtr_folder'] = ''.join([n if not "." in n else "_" for n in nbr_list]) rpki_tree[rpki_server]['children'][neighbor]['fqdn'] = neighbor rpki_tree[rpki_server]['children'][neighbor]['aggregate'] = self.network.ip_as_allocs[self.network.asn(neighbor)] rpki_tree[rpki_server]['children'][neighbor]['prefixes'] = as_prefixes[str(self.network.asn(neighbor))] def find_children(parent): for node in rpki_tree: if str(parent) in str(node): tmp_dict = rpki_tree[node] for i in tmp_dict: if 'children' in i: return [j for j in tmp_dict[i]] # write yaml file for yamltest.py # TODO: write this in mako yaml_file = yaml_path() with open( yaml_file, 'wb' ) as f_yaml: yaml_string = "" yaml_string += ("name: %s\ncrl_interval: 5m\nregen_margin: 2m\nvalid_for: 2d\nkids:" %rpki_root_folder) tree_iter = rpki_tree.items() for node, data in tree_iter: if rpki_root_str in str(data['fqdn']): indent = " " count = 1 root_iter = data.items() for key, value in root_iter: if isinstance(value,dict): for i in value: yaml_string += "\n%s- name: %s" % (indent,value[i]['rtr_folder']) yaml_string += "\n%s asn: %s" % (indent, value[i]['asn']) yaml_string += "\n%s ipv4: %s" % (indent, value[i]['aggregate']) yaml_string += "\n%s roa_request:" % indent for prefix in value[i]['prefixes']: yaml_string += "\n%s- asn: %s" % (indent*3, value[i]['asn']) yaml_string += "\n%s ipv4: %s" % (indent*3, prefix) composer = ank.ChildComposer(value[i]['fqdn'], indent*3*count, rpki_tree) child_entries = composer.search() if len(child_entries): yaml_string += "\n%s kids:" %indent yaml_string += child_entries # print yaml_string f_yaml.write(yaml_string) # for rpki_server in self.network.rpki_servers(): #check interfaces feasible if self.network.graph.in_degree(rpki_server) > self.interface_limit: LOG.warn("%s exceeds interface count: %s (max %s)" % (self.network.label(rpki_server), self.network.graph.in_degree(rpki_server), self.interface_limit)) asn = self.network.asn(rpki_server) network_list = [] lo_ip = self.network.lo_ip(rpki_server) interfaces,static_routes = self.configure_interfaces(rpki_server) igp_interfaces = self.configure_igp(rpki_server, igp_graph, ebgp_graph) (bgp_groups, policy_options) = self.configure_bgp(rpki_server, physical_graph, ibgp_graph, ebgp_graph) # advertise AS subnet adv_subnet = self.network.ip_as_allocs[asn] if not adv_subnet in network_list: network_list.append(adv_subnet) server_filename = router_conf_path(self.network, rpki_server) with open( server_filename, 'wb') as f_jun: f_jun.write( rpki_template.render( hostname = rpki_server.hostname, username = '******', interfaces=interfaces, static_routes=static_routes, igp_interfaces=igp_interfaces, igp_protocol = self.igp, asn = asn, lo_ip=lo_ip, router_id = lo_ip.ip, network_list = network_list, bgp_groups = bgp_groups, policy_options = policy_options, ank_version = ank_version, date = date, ))
def summarydoc(network): """ Plot the network """ ank_main_dir = config.ank_main_dir html_template = lookup.get_template("autonetkit/summary_html.mako") ank_css_template = lookup.get_template("autonetkit/style_css.mako") ebgp_graph = ank.get_ebgp_graph(network) ibgp_graph = ank.get_ibgp_graph(network) # Network wide stats network_stats = {} network_stats['device_count'] = len(list(network.devices())) network_stats['router_count'] = len(list(network.routers())) network_stats['server_count'] = len(list(network.servers())) network_stats['edge_count'] = network.graph.number_of_edges() as_graphs = ank.get_as_graphs(network) network_stats['as_count'] = len(as_graphs) as_stats = {} for my_as in as_graphs: #print single_as.nodes(data=True) # Get ASN of first node asn = my_as.asn #print asn node_list = {} loopbacks = [] virtual_nodes = {} for router in network.routers(asn): node_label = network.fqdn(router) loopbacks.append( (node_label, network.lo_ip(router).ip)) node_list[node_label] = {} interface_list = [] ibgp_list = [] ebgp_list = [] for _, dst, data in network.graph.edges(router, data=True): interface_list.append( (ank.fqdn(network, dst), data['sn'])) node_list[node_label]['interface_list'] = interface_list for _, dst, data in ebgp_graph.edges(router, data=True): ebgp_list.append( (ank.fqdn(network, dst), network.lo_ip(dst).ip)) node_list[node_label]['ebgp_list'] = ebgp_list for _, dst, data in ibgp_graph.edges(router, data=True): ibgp_list.append( (ank.fqdn(network, dst), network.lo_ip(dst).ip)) node_list[node_label]['ibgp_list'] = ibgp_list for virtual_node in network.virtual_nodes(asn): links = [] for link in network.links(virtual_node): links.append( (link.local_ip, link.remote_ip, link.dst)) virtual_nodes[virtual_node] = { 'links': links, } as_stats[my_as.name] = { 'asn': asn, 'loopbacks': loopbacks, 'node_list': node_list, 'virtual_nodes': virtual_nodes, } plot_dir = config.plot_dir if not os.path.isdir(plot_dir): os.mkdir(plot_dir) timestamp = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime()) css_filename = os.path.join(plot_dir, "ank_style.css") with open( css_filename, 'w') as f_css: f_css.write( ank_css_template.render()) # put html file in main plot directory html_filename = os.path.join(plot_dir, "summary.html") #print html_filename with open( html_filename, 'w') as f_html: f_html.write( html_template.render( network_stats = network_stats, as_stats = as_stats, timestamp=timestamp, css_filename = "./ank_style.css", ) )