AutoNetkit API tutorial

Written for AutoNetkit 0.10

Create Network

In [1]:
import autonetkit
anm = autonetkit.NetworkModel()
In [2]:
g_in = anm.add_overlay("input")
nodes = ['r1', 'r2', 'r3', 'r4', 'r5']

g_in.add_nodes_from(nodes)
g_in.update(device_type = "router", asn=1)
g_in.update("r5", asn = 2)
In [3]:
positions = {'r1': (10, 79),
 'r2': (226, 25),
 'r3': (172, 295),
 'r4': (334, 187),
 'r5': (496, 349)}

for n in g_in:
    n.x, n.y = positions[n]

autonetkit.update_http(anm)
In [3]:
 
In [4]:
edges = [("r1", "r2"), ("r2", "r4"), ("r1", "r3"), 
         ("r3", "r4"), ("r3", "r5"), ("r4", "r5")]
g_in.add_edges_from(edges)
g_in.allocate_input_interfaces()
INFO Automatically assigning input interfaces
INFO:ANK:Automatically assigning input interfaces

In [5]:
autonetkit.update_http(anm)
In [6]:
g_phy = anm['phy']
g_phy.add_nodes_from(g_in, retain=["asn", "device_type", "x", "y"])
g_phy.update(use_ipv4 = True, host = "localhost", platform = "netkit", syntax = "quagga")

g_phy.add_edges_from(g_in.edges())
autonetkit.update_http(anm)
In [6]:
 
In [7]:
g_ospf = anm.add_overlay("ospf")
g_ospf.add_nodes_from(g_in.routers())
g_ospf.add_edges_from(e for e in g_in.edges()
                      if e.src.asn == e.dst.asn)
autonetkit.update_http(anm) 
In [7]:
 
In [8]:
g_ebgp = anm.add_overlay("ebgp_v4", directed = True)
g_ebgp.add_nodes_from(g_in.routers())
edges = [e for e in g_in.edges()
         if e.src.asn != e.dst.asn]
# Add in both directions
g_ebgp.add_edges_from(edges, bidirectional = True)
autonetkit.update_http(anm)              
In [8]:
 
In [9]:
g_ibgp = anm.add_overlay("ibgp_v4", directed = True)
g_ibgp.add_nodes_from(g_in.routers())
edges = [(s,t) for s in g_ibgp for t in g_ibgp
         # belong to same ASN, but not self-loops
         if s != t and s.asn == t.asn]

# Add in both directions
g_ibgp.add_edges_from(edges, bidirectional = True)
autonetkit.update_http(anm)
In [9]:
 
In [10]:
import autonetkit.ank as ank_utils
g_ipv4 = anm.add_overlay("ipv4")
g_ipv4.add_nodes_from(g_in)
g_ipv4.add_edges_from(g_in.edges())

# Split the point-to-point edges to add a collision domain
edges_to_split = [edge for edge in g_ipv4.edges()
    if edge.src.is_l3device() and edge.dst.is_l3device()]
for edge in edges_to_split:
    edge.split = True  # mark as split for use in building nidb
    
split_created_nodes = list(ank_utils.split(g_ipv4, edges_to_split,
    retain=['split'], id_prepend='cd'))

for node in split_created_nodes:
    # Set the co-ordinates using 'x', 'y' of g_in
    # based on neighbors in g_ipv4
    node.x = ank_utils.neigh_average(g_ipv4, node, 'x', g_in)
    node.y = ank_utils.neigh_average(g_ipv4, node, 'y', g_in)
    # Set most frequent of asn property in g_phy
    # ASN is used to allocate IPs
    node.asn = ank_utils.neigh_most_frequent(g_ipv4, node,
                                             'asn', g_phy)
    node.broadcast_domain = True
    node.allocate = True
    
# Now use allocation plugin
import autonetkit.plugins.ipv4 as ipv4
ipv4.allocate_infra(g_ipv4)
ipv4.allocate_loopbacks(g_ipv4)

autonetkit.update_http(anm)
In [10]:
 
In [11]:
# Now construct NIDB
nidb = autonetkit.DeviceModel(anm)


autonetkit.update_http(anm, nidb)
In [15]:
 
In [62]:
import autonetkit.compilers.platform.netkit as pl_netkit
host = "localhost"

platform_compiler = pl_netkit.NetkitCompiler(nidb, anm, host)
platform_compiler.compile() 
INFO Compiling Netkit for localhost
INFO:ANK:Compiling Netkit for localhost

In [63]:
for node in nidb:
    print node
    print node.dump()
r4
{'Network': None,
 '_ports': {0: {'category': 'loopback',
                'custom_config': None,
                'description': 'Loopback',
                'id': 'lo:1',
                'id_brief': 'lo:1',
                'ipv4_address': IPAddress('192.168.0.4'),
                'ipv4_netmask': '255.255.255.255',
                'ipv4_subnet': IPNetwork('192.168.0.4/32'),
                'use_ipv4': False},
            1: {'category': 'physical',
                'custom_config': None,
                'description': 'r4 to r2',
                'id': 'eth0',
                'id_brief': 'eth0',
                'ipv4_address': IPAddress('10.0.0.10'),
                'ipv4_cidr': IPNetwork('10.0.0.10/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.8/30'),
                'numeric_id': 0,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True},
            2: {'category': 'physical',
                'custom_config': None,
                'description': 'r4 to r3',
                'id': 'eth1',
                'id_brief': 'eth1',
                'ipv4_address': IPAddress('10.0.0.14'),
                'ipv4_cidr': IPNetwork('10.0.0.14/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.12/30'),
                'numeric_id': 1,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True},
            3: {'category': 'physical',
                'custom_config': None,
                'description': 'r4 to r5',
                'id': 'eth2',
                'id_brief': 'eth2',
                'ipv4_address': IPAddress('10.0.128.1'),
                'ipv4_cidr': IPNetwork('10.0.128.1/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.128.0/30'),
                'numeric_id': 2,
                'physical': True,
                'use_ipv4': True}},
 'asn': 1,
 'bgp': [('ebgp_neighbors', [[('update_source', None), ('loopback', IPAddress('192.168.0.9')), ('md5_password', None), ('dst_int_ip', IPAddress('10.0.128.2')), ('multihop', None), ('use_ipv4', True), ('neighbor', 'r5'), ('use_ipv6', False), ('local_int_ip', IPAddress('10.0.128.1')), ('asn', 2)]]), ('ibgp_neighbors', [[('update_source', None), ('loopback', IPAddress('192.168.0.1')), ('use_ipv4', True), ('neighbor', 'r1'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.2')), ('use_ipv4', True), ('neighbor', 'r2'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.3')), ('use_ipv4', True), ('neighbor', 'r3'), ('use_ipv6', False), ('asn', 1)]]), ('custom_config', ''), ('ipv4_advertise_subnets', [IPNetwork('10.0.0.0/16')]), ('ipv6_advertise_subnets', []), ('ibgp_rr_clients', []), ('ibgp_rr_parents', []), ('debug', True)],
 'device_subtype': None,
 'device_type': 'router',
 'do_render': True,
 'global_custom_config': None,
 'graphics': [('x', 334), ('y', 187), ('device_type', 'router'), ('device_subtype', None)],
 'host': 'localhost',
 'hostname': 'r4',
 'input_label': 'r4',
 'interfaces': [],
 'ip': [('use_ipv4', True), ('use_ipv6', False)],
 'ipv4_static_routes': [],
 'ipv6_static_routes': [],
 'label': 'r4',
 'loopback': IPAddress('192.168.0.4'),
 'loopback_subnet': IPNetwork('192.168.0.4/32'),
 'ospf': [('process_id', None), ('ospf_links', [[('interface', r4.r4 to r2), ('network', IPNetwork('10.0.0.8/30')), ('area', None)], [('interface', r4.r4 to r3), ('network', IPNetwork('10.0.0.12/30')), ('area', None)], [('network', IPNetwork('10.0.128.0/30')), ('area', 0)]]), ('custom_config', None), ('ipv4_mpls_te', False), ('loopback_area', 0), ('lo_interface', 'lo:1'), ('interfaces_by_area', [('None', [[('passive', False), ('cost', 1), ('id', 'eth0'), ('ipv4_address', IPAddress('10.0.0.10')), ('ipv4_subnet', IPNetwork('10.0.0.8/30'))], [('passive', False), ('cost', 1), ('id', 'eth1'), ('ipv4_address', IPAddress('10.0.0.14')), ('ipv4_subnet', IPNetwork('10.0.0.12/30'))], [('passive', True), ('cost', 0), ('id', 'lo:1')]])]), ('passive_interfaces', [[('id', 'eth2')]])],
 'platform': 'netkit',
 'render': [('template', 'templates/netkit_startup.mako'), ('dst_folder', 'rendered/localhost/netkit'), ('dst_file', 'r4.startup'), ('base', 'templates/quagga'), ('base_dst_folder', 'rendered/localhost/netkit/r4'), ('custom', {'abc': 'def.txt'})],
 'render2': <autonetkit.render2.NodeRender object at 0x105799c50>,
 'ssh': [('use_key', True)],
 'tap': [('id', 'eth3'), ('ip', IPAddress('172.16.0.6'))],
 'update': None,
 'x': 324,
 'y': 162,
 'zebra': [('password', '1234'), ('static_routes', [])]}
None
r5
{'Network': None,
 '_ports': {0: {'category': 'loopback',
                'custom_config': None,
                'description': 'Loopback',
                'id': 'lo:1',
                'id_brief': 'lo:1',
                'ipv4_address': IPAddress('192.168.0.9'),
                'ipv4_netmask': '255.255.255.255',
                'ipv4_subnet': IPNetwork('192.168.0.9/32'),
                'use_ipv4': False},
            1: {'category': 'physical',
                'custom_config': None,
                'description': 'r5 to r4',
                'id': 'eth0',
                'id_brief': 'eth0',
                'ipv4_address': IPAddress('10.0.128.2'),
                'ipv4_cidr': IPNetwork('10.0.128.2/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.128.0/30'),
                'numeric_id': 0,
                'physical': True,
                'use_ipv4': True},
            2: {'category': 'physical',
                'custom_config': None,
                'description': 'r5 to r3',
                'id': 'eth1',
                'id_brief': 'eth1',
                'ipv4_address': IPAddress('10.1.0.2'),
                'ipv4_cidr': IPNetwork('10.1.0.2/16'),
                'ipv4_netmask': IPAddress('255.255.0.0'),
                'ipv4_subnet': IPNetwork('10.1.0.0/16'),
                'numeric_id': 1,
                'physical': True,
                'use_ipv4': True}},
 'asn': 2,
 'bgp': [('ebgp_neighbors', [[('update_source', None), ('loopback', IPAddress('192.168.0.3')), ('md5_password', None), ('dst_int_ip', IPAddress('10.1.0.1')), ('multihop', None), ('use_ipv4', True), ('neighbor', 'r3'), ('use_ipv6', False), ('local_int_ip', IPAddress('10.1.0.2')), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.4')), ('md5_password', None), ('dst_int_ip', IPAddress('10.0.128.1')), ('multihop', None), ('use_ipv4', True), ('neighbor', 'r4'), ('use_ipv6', False), ('local_int_ip', IPAddress('10.0.128.2')), ('asn', 1)]]), ('ibgp_neighbors', []), ('custom_config', ''), ('ipv4_advertise_subnets', [IPNetwork('10.1.0.0/16')]), ('ipv6_advertise_subnets', []), ('ibgp_rr_clients', []), ('ibgp_rr_parents', []), ('debug', True)],
 'device_subtype': None,
 'device_type': 'router',
 'do_render': True,
 'global_custom_config': None,
 'graphics': [('x', 496), ('y', 349), ('device_type', 'router'), ('device_subtype', None)],
 'host': 'localhost',
 'hostname': 'r5',
 'input_label': 'r5',
 'interfaces': [],
 'ip': [('use_ipv4', True), ('use_ipv6', False)],
 'ipv4_static_routes': [],
 'ipv6_static_routes': [],
 'label': 'r5',
 'loopback': IPAddress('192.168.0.9'),
 'loopback_subnet': IPNetwork('192.168.0.9/32'),
 'ospf': [('process_id', None), ('ospf_links', [[('network', IPNetwork('10.0.128.0/30')), ('area', 0)], [('network', IPNetwork('10.1.0.0/16')), ('area', 0)]]), ('custom_config', None), ('ipv4_mpls_te', False), ('loopback_area', 0), ('lo_interface', 'lo:1'), ('interfaces_by_area', [('None', [[('passive', True), ('cost', 0), ('id', 'lo:1')]])]), ('passive_interfaces', [[('id', 'eth0')], [('id', 'eth1')]])],
 'platform': 'netkit',
 'render': [('template', 'templates/netkit_startup.mako'), ('dst_folder', 'rendered/localhost/netkit'), ('dst_file', 'r5.startup'), ('base', 'templates/quagga'), ('base_dst_folder', 'rendered/localhost/netkit/r5'), ('custom', {'abc': 'def.txt'})],
 'render2': <autonetkit.render2.NodeRender object at 0x105799fd0>,
 'ssh': [('use_key', True)],
 'tap': [('id', 'eth2'), ('ip', IPAddress('172.16.0.7'))],
 'update': None,
 'x': 486,
 'y': 324,
 'zebra': [('password', '1234'), ('static_routes', [])]}
None
r1
{'Network': None,
 '_ports': {0: {'category': 'loopback',
                'custom_config': None,
                'description': 'Loopback',
                'id': 'lo:1',
                'id_brief': 'lo:1',
                'ipv4_address': IPAddress('192.168.0.1'),
                'ipv4_netmask': '255.255.255.255',
                'ipv4_subnet': IPNetwork('192.168.0.1/32'),
                'use_ipv4': False},
            1: {'category': 'physical',
                'custom_config': None,
                'description': 'r1 to r2',
                'id': 'eth0',
                'id_brief': 'eth0',
                'ipv4_address': IPAddress('10.0.0.1'),
                'ipv4_cidr': IPNetwork('10.0.0.1/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.0/30'),
                'numeric_id': 0,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True},
            2: {'category': 'physical',
                'custom_config': None,
                'description': 'r1 to r3',
                'id': 'eth1',
                'id_brief': 'eth1',
                'ipv4_address': IPAddress('10.0.0.5'),
                'ipv4_cidr': IPNetwork('10.0.0.5/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.4/30'),
                'numeric_id': 1,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True}},
 'asn': 1,
 'bgp': [('ebgp_neighbors', []), ('ibgp_neighbors', [[('update_source', None), ('loopback', IPAddress('192.168.0.2')), ('use_ipv4', True), ('neighbor', 'r2'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.3')), ('use_ipv4', True), ('neighbor', 'r3'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.4')), ('use_ipv4', True), ('neighbor', 'r4'), ('use_ipv6', False), ('asn', 1)]]), ('custom_config', ''), ('ipv4_advertise_subnets', [IPNetwork('10.0.0.0/16')]), ('ipv6_advertise_subnets', []), ('ibgp_rr_clients', []), ('ibgp_rr_parents', []), ('debug', True)],
 'device_subtype': None,
 'device_type': 'router',
 'do_render': True,
 'global_custom_config': None,
 'graphics': [('x', 10), ('y', 79), ('device_type', 'router'), ('device_subtype', None)],
 'host': 'localhost',
 'hostname': 'r1',
 'input_label': 'r1',
 'interfaces': [],
 'ip': [('use_ipv4', True), ('use_ipv6', False)],
 'ipv4_static_routes': [],
 'ipv6_static_routes': [],
 'label': 'r1',
 'loopback': IPAddress('192.168.0.1'),
 'loopback_subnet': IPNetwork('192.168.0.1/32'),
 'ospf': [('process_id', None), ('ospf_links', [[('interface', r1.r1 to r2), ('network', IPNetwork('10.0.0.0/30')), ('area', None)], [('interface', r1.r1 to r3), ('network', IPNetwork('10.0.0.4/30')), ('area', None)]]), ('custom_config', None), ('ipv4_mpls_te', False), ('loopback_area', 0), ('lo_interface', 'lo:1'), ('interfaces_by_area', [('None', [[('passive', False), ('cost', 1), ('id', 'eth0'), ('ipv4_address', IPAddress('10.0.0.1')), ('ipv4_subnet', IPNetwork('10.0.0.0/30'))], [('passive', False), ('cost', 1), ('id', 'eth1'), ('ipv4_address', IPAddress('10.0.0.5')), ('ipv4_subnet', IPNetwork('10.0.0.4/30'))], [('passive', True), ('cost', 0), ('id', 'lo:1')]])]), ('passive_interfaces', [])],
 'platform': 'netkit',
 'render': [('template', 'templates/netkit_startup.mako'), ('dst_folder', 'rendered/localhost/netkit'), ('dst_file', 'r1.startup'), ('base', 'templates/quagga'), ('base_dst_folder', 'rendered/localhost/netkit/r1'), ('custom', {'abc': 'def.txt'})],
 'render2': <autonetkit.render2.NodeRender object at 0x10566b090>,
 'ssh': [('use_key', True)],
 'tap': [('id', 'eth2'), ('ip', IPAddress('172.16.0.3'))],
 'update': None,
 'x': 0,
 'y': 54,
 'zebra': [('password', '1234'), ('static_routes', [])]}
None
r2
{'Network': None,
 '_ports': {0: {'category': 'loopback',
                'custom_config': None,
                'description': 'Loopback',
                'id': 'lo:1',
                'id_brief': 'lo:1',
                'ipv4_address': IPAddress('192.168.0.2'),
                'ipv4_netmask': '255.255.255.255',
                'ipv4_subnet': IPNetwork('192.168.0.2/32'),
                'use_ipv4': False},
            1: {'category': 'physical',
                'custom_config': None,
                'description': 'r2 to r1',
                'id': 'eth0',
                'id_brief': 'eth0',
                'ipv4_address': IPAddress('10.0.0.2'),
                'ipv4_cidr': IPNetwork('10.0.0.2/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.0/30'),
                'numeric_id': 0,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True},
            2: {'category': 'physical',
                'custom_config': None,
                'description': 'r2 to r4',
                'id': 'eth1',
                'id_brief': 'eth1',
                'ipv4_address': IPAddress('10.0.0.9'),
                'ipv4_cidr': IPNetwork('10.0.0.9/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.8/30'),
                'numeric_id': 1,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True}},
 'asn': 1,
 'bgp': [('ebgp_neighbors', []), ('ibgp_neighbors', [[('update_source', None), ('loopback', IPAddress('192.168.0.1')), ('use_ipv4', True), ('neighbor', 'r1'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.3')), ('use_ipv4', True), ('neighbor', 'r3'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.4')), ('use_ipv4', True), ('neighbor', 'r4'), ('use_ipv6', False), ('asn', 1)]]), ('custom_config', ''), ('ipv4_advertise_subnets', [IPNetwork('10.0.0.0/16')]), ('ipv6_advertise_subnets', []), ('ibgp_rr_clients', []), ('ibgp_rr_parents', []), ('debug', True)],
 'device_subtype': None,
 'device_type': 'router',
 'do_render': True,
 'global_custom_config': None,
 'graphics': [('x', 226), ('y', 25), ('device_type', 'router'), ('device_subtype', None)],
 'host': 'localhost',
 'hostname': 'r2',
 'input_label': 'r2',
 'interfaces': [],
 'ip': [('use_ipv4', True), ('use_ipv6', False)],
 'ipv4_static_routes': [],
 'ipv6_static_routes': [],
 'label': 'r2',
 'loopback': IPAddress('192.168.0.2'),
 'loopback_subnet': IPNetwork('192.168.0.2/32'),
 'ospf': [('process_id', None), ('ospf_links', [[('interface', r2.r2 to r1), ('network', IPNetwork('10.0.0.0/30')), ('area', None)], [('interface', r2.r2 to r4), ('network', IPNetwork('10.0.0.8/30')), ('area', None)]]), ('custom_config', None), ('ipv4_mpls_te', False), ('loopback_area', 0), ('lo_interface', 'lo:1'), ('interfaces_by_area', [('None', [[('passive', False), ('cost', 1), ('id', 'eth0'), ('ipv4_address', IPAddress('10.0.0.2')), ('ipv4_subnet', IPNetwork('10.0.0.0/30'))], [('passive', False), ('cost', 1), ('id', 'eth1'), ('ipv4_address', IPAddress('10.0.0.9')), ('ipv4_subnet', IPNetwork('10.0.0.8/30'))], [('passive', True), ('cost', 0), ('id', 'lo:1')]])]), ('passive_interfaces', [])],
 'platform': 'netkit',
 'render': [('template', 'templates/netkit_startup.mako'), ('dst_folder', 'rendered/localhost/netkit'), ('dst_file', 'r2.startup'), ('base', 'templates/quagga'), ('base_dst_folder', 'rendered/localhost/netkit/r2'), ('custom', {'abc': 'def.txt'})],
 'render2': <autonetkit.render2.NodeRender object at 0x10566be90>,
 'ssh': [('use_key', True)],
 'tap': [('id', 'eth2'), ('ip', IPAddress('172.16.0.4'))],
 'update': None,
 'x': 216,
 'y': 0,
 'zebra': [('password', '1234'), ('static_routes', [])]}
None
r3
{'Network': None,
 '_ports': {0: {'category': 'loopback',
                'custom_config': None,
                'description': 'Loopback',
                'id': 'lo:1',
                'id_brief': 'lo:1',
                'ipv4_address': IPAddress('192.168.0.3'),
                'ipv4_netmask': '255.255.255.255',
                'ipv4_subnet': IPNetwork('192.168.0.3/32'),
                'use_ipv4': False},
            1: {'category': 'physical',
                'custom_config': None,
                'description': 'r3 to r1',
                'id': 'eth0',
                'id_brief': 'eth0',
                'ipv4_address': IPAddress('10.0.0.6'),
                'ipv4_cidr': IPNetwork('10.0.0.6/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.4/30'),
                'numeric_id': 0,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True},
            2: {'category': 'physical',
                'custom_config': None,
                'description': 'r3 to r4',
                'id': 'eth1',
                'id_brief': 'eth1',
                'ipv4_address': IPAddress('10.0.0.13'),
                'ipv4_cidr': IPNetwork('10.0.0.13/30'),
                'ipv4_netmask': IPAddress('255.255.255.252'),
                'ipv4_subnet': IPNetwork('10.0.0.12/30'),
                'numeric_id': 1,
                'ospf_cost': 1,
                'physical': True,
                'use_ipv4': True},
            3: {'category': 'physical',
                'custom_config': None,
                'description': 'r3 to r5',
                'id': 'eth2',
                'id_brief': 'eth2',
                'ipv4_address': IPAddress('10.1.0.1'),
                'ipv4_cidr': IPNetwork('10.1.0.1/16'),
                'ipv4_netmask': IPAddress('255.255.0.0'),
                'ipv4_subnet': IPNetwork('10.1.0.0/16'),
                'numeric_id': 2,
                'physical': True,
                'use_ipv4': True}},
 'asn': 1,
 'bgp': [('ebgp_neighbors', [[('update_source', None), ('loopback', IPAddress('192.168.0.9')), ('md5_password', None), ('dst_int_ip', IPAddress('10.1.0.2')), ('multihop', None), ('use_ipv4', True), ('neighbor', 'r5'), ('use_ipv6', False), ('local_int_ip', IPAddress('10.1.0.1')), ('asn', 2)]]), ('ibgp_neighbors', [[('update_source', None), ('loopback', IPAddress('192.168.0.1')), ('use_ipv4', True), ('neighbor', 'r1'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.2')), ('use_ipv4', True), ('neighbor', 'r2'), ('use_ipv6', False), ('asn', 1)], [('update_source', None), ('loopback', IPAddress('192.168.0.4')), ('use_ipv4', True), ('neighbor', 'r4'), ('use_ipv6', False), ('asn', 1)]]), ('custom_config', ''), ('ipv4_advertise_subnets', [IPNetwork('10.0.0.0/16')]), ('ipv6_advertise_subnets', []), ('ibgp_rr_clients', []), ('ibgp_rr_parents', []), ('debug', True)],
 'device_subtype': None,
 'device_type': 'router',
 'do_render': True,
 'global_custom_config': None,
 'graphics': [('x', 172), ('y', 295), ('device_type', 'router'), ('device_subtype', None)],
 'host': 'localhost',
 'hostname': 'r3',
 'input_label': 'r3',
 'interfaces': [],
 'ip': [('use_ipv4', True), ('use_ipv6', False)],
 'ipv4_static_routes': [],
 'ipv6_static_routes': [],
 'label': 'r3',
 'loopback': IPAddress('192.168.0.3'),
 'loopback_subnet': IPNetwork('192.168.0.3/32'),
 'ospf': [('process_id', None), ('ospf_links', [[('interface', r3.r3 to r1), ('network', IPNetwork('10.0.0.4/30')), ('area', None)], [('interface', r3.r3 to r4), ('network', IPNetwork('10.0.0.12/30')), ('area', None)], [('network', IPNetwork('10.1.0.0/16')), ('area', 0)]]), ('custom_config', None), ('ipv4_mpls_te', False), ('loopback_area', 0), ('lo_interface', 'lo:1'), ('interfaces_by_area', [('None', [[('passive', False), ('cost', 1), ('id', 'eth0'), ('ipv4_address', IPAddress('10.0.0.6')), ('ipv4_subnet', IPNetwork('10.0.0.4/30'))], [('passive', False), ('cost', 1), ('id', 'eth1'), ('ipv4_address', IPAddress('10.0.0.13')), ('ipv4_subnet', IPNetwork('10.0.0.12/30'))], [('passive', True), ('cost', 0), ('id', 'lo:1')]])]), ('passive_interfaces', [[('id', 'eth2')]])],
 'platform': 'netkit',
 'render': [('template', 'templates/netkit_startup.mako'), ('dst_folder', 'rendered/localhost/netkit'), ('dst_file', 'r3.startup'), ('base', 'templates/quagga'), ('base_dst_folder', 'rendered/localhost/netkit/r3'), ('custom', {'abc': 'def.txt'})],
 'render2': <autonetkit.render2.NodeRender object at 0x10566b290>,
 'ssh': [('use_key', True)],
 'tap': [('id', 'eth3'), ('ip', IPAddress('172.16.0.5'))],
 'update': None,
 'x': 162,
 'y': 270,
 'zebra': [('password', '1234'), ('static_routes', [])]}
None

In [64]:
import autonetkit.render
autonetkit.render.render(nidb)

The output files are put

into rendered/localhost/netkit

For instance:

├── lab.conf
├── r1
│   ├── etc
│   │   ├── hostname
│   │   ├── shadow
│   │   ├── ssh
│   │   │   └── sshd_config
│   │   └── zebra
│   │       ├── bgpd.conf
│   │       ├── daemons
│   │       ├── isisd.conf
│   │       ├── motd.txt
│   │       ├── ospfd.conf
│   │       └── zebra.conf
│   └── root
├── r1.startup
├── r2
│   ├── etc
│   │   ├── hostname
│   │   ├── shadow
│   │   ├── ssh
│   │   │   └── sshd_config
│   │   └── zebra
│   │       ├── bgpd.conf
│   │       ├── daemons
│   │       ├── isisd.conf
│   │       ├── motd.txt
│   │       ├── ospfd.conf
│   │       └── zebra.conf
│   └── root
├── r2.startup

Can also write our own compiler and templates:

In [65]:
# AutoNetkit renderer expects filenames for templates
# uses the Mako template format
router_template_str = """Router rendered on ${date} by ${version_banner}
% for interface in node.interfaces:
interface ${interface.id}
    description ${interface.description}
    ip address ${interface.ipv4_address} netmask ${interface.ipv4_netmask}
% endfor
!
router ospf ${node.ospf.process_id}
    % for link in node.ospf.ospf_links:
    network ${link.network.cidr} area ${link.area}
    % endfor
!
router bgp ${node.asn}
% for neigh in node.bgp.ibgp_neighbors:
  ! ${neigh.neighbor}
  neighbor ${neigh.loopback} remote-as ${neigh.asn}
  neighbor ${neigh.loopback} update-source ${node.loopback_zero.ipv4_address}
  neighbor ${neigh.loopback} next-hop-self
% endfor
!
% for neigh in node.bgp.ebgp_neighbors:
  ! ${neigh.neighbor}
  neighbor ${neigh.dst_int_ip} remote-as ${neigh.asn}
  neighbor ${neigh.dst_int_ip} update-source ${neigh.local_int_ip}
% endfor
!    
"""

router_template = "router.mako"
with open(router_template, "w") as fh:
    fh.write(router_template_str)
In [75]:
from autonetkit.compilers.device import router_base
from autonetkit.nidb import ConfigStanza
class simple_router_compiler(router_base.RouterCompiler):
    lo_interface = 'lo:1'
    
    def compile(self, node):
        self.interfaces(node)
        self.ospf(node)
        self.bgp(node)
        node.do_render = True

    def interfaces(self, node):
        # Append attributes to the interface, rather than add a stanza
        ipv4_node = self.anm['ipv4'].node(node)
        if node.is_l3device:
            node.loopback_zero.id = self.lo_interface
            node.loopback_zero.description = 'Loopback'
            node.loopback_zero.ipv4_address = ipv4_node.loopback
            node.loopback_zero.ipv4_netmask = "255.255.255.255" 

        for interface in node.physical_interfaces():
            ipv4_int = ipv4_node.interface(interface)
            interface.ipv4_address = ipv4_int.ip_address
            interface.ipv4_netmask = ipv4_int.subnet.netmask
                                                                    
    def ospf(self, node):
        node.add_stanza("ospf", process_id = 1)
        ospf_links = []
        for interface in node.physical_interfaces():
            ipv4_int = self.anm['ipv4'].interface(interface)
            ospf_links.append(ConfigStanza(network=ipv4_int.subnet,
                                            area=0))
        node.ospf.ospf_links = ospf_links
    
    def bgp(self, node):
        node.add_stanza("bgp")
        g_ebgp = self.anm["ebgp_v4"]
        ebgp_neighbors = []
        ibgp_neighbors = []
        for session in g_ebgp.edges(node):
            neighbor = session.dst # remote node
            stanza = ConfigStanza(neighbor = neighbor,
                                   asn = neighbor.asn)
            # Can obtain the dst int, as created bgp session
            # from physical links
            stanza.local_int_ip = session.src_int['ipv4'].ip_address
            stanza.dst_int_ip = session.dst_int['ipv4'].ip_address
            ebgp_neighbors.append(stanza)
            
        for session in g_ibgp.edges(node):
            neighbor = session.dst # remote node
            stanza = ConfigStanza(neighbor = neighbor,
                                   asn = neighbor.asn)
            stanza.loopback = neighbor['ipv4'].loopback
            ibgp_neighbors.append(stanza)
            
        node.bgp.ebgp_neighbors = ebgp_neighbors
        node.bgp.ibgp_neighbors = ibgp_neighbors
In [76]:
topology_template_str = """Topology rendered on ${date} by ${version_banner}
% for host in topology.hosts:
host: ${host}
% endfor
"""

topology_template = "topology.mako"
with open(topology_template, "w") as fh:
    fh.write(topology_template_str)
In [77]:
from autonetkit.compilers.platform import platform_base
import netaddr
from autonetkit.nidb import ConfigStanza

class simple_platform_compiler(platform_base.PlatformCompiler):
    def compile(self):        
        rtr_comp = simple_router_compiler(self.nidb, self.anm)
        
        for node in nidb.routers(host=host):
            for index, interface in enumerate(node.physical_interfaces()):
                interface.id = "eth%s" % index
            
            # specify router template
            node.add_stanza("render")
            node.render.template = router_template
            node.render.dst_folder = "rendered"
            node.render.dst_file = "%s.conf" % node
            # and compile
            rtr_comp.compile(node)            
                
        # and the topology
        lab_topology = self.nidb.topology(self.host)
        # template settings for the renderer
        lab_topology.render_template = topology_template
        lab_topology.render_dst_folder = "rendered"
        lab_topology.render_dst_file = "lab.conf"
        
        lab_topology.hosts = []
        for node in nidb.routers(host=host):
            lab_topology.hosts.append(node)
In [78]:
# rebuild the NIDB clean
nidb = autonetkit.DeviceModel(anm)
In [79]:
sim_plat = simple_platform_compiler(nidb, anm, "localhost")
sim_plat.compile()
autonetkit.update_http(anm, nidb)
In [80]:
import autonetkit.render
autonetkit.render.render(nidb)
In [81]:
with open("rendered/lab.conf") as fh:
    print fh.read()
Topology rendered on 2014-11-04 17:20 by VIRL Configuration Engine 0.10.4
host: r4
host: r5
host: r1
host: r2
host: r3


In [82]:
with open("rendered/r1.conf") as fh:
    print fh.read()
Router rendered on 2014-11-04 17:20 by VIRL Configuration Engine 0.10.4
interface lo:1
    description Loopback
    ip address 192.168.0.1 netmask 255.255.255.255
interface eth0
    description r1 to r2
    ip address 10.0.0.1 netmask 255.255.255.252
interface eth1
    description r1 to r3
    ip address 10.0.0.5 netmask 255.255.255.252
!
router ospf 1
    network 10.0.0.0/30 area 0
    network 10.0.0.4/30 area 0
!
router bgp 1
  ! r4
  neighbor 192.168.0.4 remote-as 1
  neighbor 192.168.0.4 update-source 192.168.0.1
  neighbor 192.168.0.4 next-hop-self
  ! r2
  neighbor 192.168.0.2 remote-as 1
  neighbor 192.168.0.2 update-source 192.168.0.1
  neighbor 192.168.0.2 next-hop-self
  ! r3
  neighbor 192.168.0.3 remote-as 1
  neighbor 192.168.0.3 update-source 192.168.0.1
  neighbor 192.168.0.3 next-hop-self
!
!    


In [83]:
with open("rendered/r5.conf") as fh:
    print fh.read()
Router rendered on 2014-11-04 17:20 by VIRL Configuration Engine 0.10.4
interface lo:1
    description Loopback
    ip address 192.168.0.9 netmask 255.255.255.255
interface eth0
    description r5 to r4
    ip address 10.0.128.2 netmask 255.255.255.252
interface eth1
    description r5 to r3
    ip address 10.1.0.2 netmask 255.255.0.0
!
router ospf 1
    network 10.0.128.0/30 area 0
    network 10.1.0.0/16 area 0
!
router bgp 2
!
  ! r4
  neighbor 10.0.128.1 remote-as 1
  neighbor 10.0.128.1 update-source 10.0.128.2
  ! r3
  neighbor 10.1.0.1 remote-as 1
  neighbor 10.1.0.1 update-source 10.1.0.2
!