Skip to content

Instantly share code, notes, and snippets.

@plucena24
Last active November 26, 2018 13:27
Show Gist options
  • Save plucena24/7aa3d2727d5a76c0230b to your computer and use it in GitHub Desktop.
Save plucena24/7aa3d2727d5a76c0230b to your computer and use it in GitHub Desktop.
Automatically generate and apply basic IP addressing config for a GNS3 dynamips topology.
'''
GNS3_auto_ip_script
author: plucena24@gmail.com
Automatically generate and apply basic IP addressing config for a GNS3 dynamips topology.
Example: a network consisting of R1---R2---R3.
Using the script, the links will be numbered as:
R1 to R2 link:
R1--10.1.12.1/24--10.1.12.2/24--R2
R1--2001:10:1:12::1/64--2001:10:1:12::1/64--R2
R2 to R3 link:
R2--10.1.23.2/24--10.1.23.3/24--R3
R2--2001:10:1:23::2/64--2001:10:1:23::3/64--R3
Loopbacks are generated as /32 and /128 as follows:
R1:
1.1.1.1/32
2001::1/128
R2:
2.2.2.2/32
2001::2/128
R3:
3.3.3.3/32
2001::3/128
The purpose of this script is to facilitate booting a numbered topology with
addressing that is easy to use when labbing. Having the links numbered
following this approach makes show outputs much more readable if you just want
to lab and not have to figure out what IP goes where.
The script will automatically detect what types of interfaces are being used,
and will generate config for them (Ethernet, FastE, GigE, Serial, etc).
At this point, only point-to-point links are supported. However this simple
algorithm can be modified to support segments with more than 2 routers.
To use, pass in the required command line arguments:
--base-dir: base directory where your GNS3 project is stored:
example: /Users/plucena/GNS3/projects/test_project/
required: yes
--project-files: directory holding the GNS3/Dynamips files for the project
example: project-files/dynamips/
required: no
default: 'project-files/dynamips/'
--topology: .gns3 topology file
example: test_topology.gns3
required: yes
--v4: base IPv4 prefix to be used for link numbering
example: 10.1 (links will be numbered 10.1.X.X/24)
required: no
default: 10.1
--v6: base IPv6 prefix to be used for link numbering
example: 2001:10:1 (links will be numbered 2001:10:1:X:X::X/64)
required: no
default: 2001:10:1
--debug: enable printing of built config and data structures. No changes will be made to config files.
required: no
default: False
## How to use:
Steps:
1) Create a topology in GNS3. Power on routers so that they generate a base
config. Save the router's config, power them off, and save the topology. This
will generate base startup configs for your routers. (hostname, available
interfaces, IOS specific configs, etc).
2) Run the script - if the --debug flag is not passed in, it will modify each
router's config file with the new addressing.
example:
python gns3_config_generator.py -bd /Users/plucena/GNS3/projects/test_topo/ -t test_topo.gns3
3) Boot the routers again, and enjoy an automatically numbered network =).
'''
import json
import os
import itertools
import sys
import argparse
def parse():
"""Parse arguments
example:
python gns3_config_generator.py -bd /Users/plucena/GNS3/projects/test/ -t test_topo.gns3
"""
parser = argparse.ArgumentParser(description='GNS3_auto_ip_script')
parser.add_argument("--debug", "-d",
action="store_true",
default=False,
help="enable debugging")
parser.add_argument("--base-dir", "-bd",
type=str,
dest='base_dir',
help="base directory for GNS3 project")
parser.add_argument("--project-files", "-pf",
type=str,
default='project-files/dynamips/',
dest='project_files',
help="dynamips project files dir")
parser.add_argument("--topology", "-t",
type=str,
dest='topology_file',
help="GNS3 topology file")
parser.add_argument("--v4", "-4",
type=str,
default='10.1',
dest='ipv4_base',
help="IPv4 base prefix")
parser.add_argument("--v6", "-6",
type=str,
default='2001:10:1',
dest='ipv6_base',
help="IPv6 base prefix")
args = parser.parse_args()
return args
def configure_nodes(node):
'''generate and apply IP addressing config for link endpoints'''
node_id = node['node_id']
config = ['! config added by GNS3_auto_ip_script', '!']
lo_cfg = [lo.format(node_id) for lo in (lo0_v4, lo0_v6)]
loopback = 'interface Loopback0\n {}\n {}'.format(*lo_cfg)
config.extend(loopback.splitlines())
# simple algorithm. Take link endpoint's and create an IP subnet based on their ID
# R1-R2 becomes X.X.12.1/24 and X.X.12.2/24
# R6-R4 becomes X.X.46.6/24 and X.X.46.4/24
for port in node['ports']:
src, dst = links[port['link_id']]
if src > dst:
base = ''.join(map(str, (dst, src)))
else:
base = ''.join(map(str, (src, dst)))
po_cfg = [po.format(base, node_id) for po in (base_v4, base_v6)]
int_config = 'interface {}\n {} \n {}\n no shut'.format(port['name'], *po_cfg)
config.extend(int_config.splitlines())
cfg_file = os.path.join(CFG_DIR, node['config'])
with open(cfg_file, 'r+') as fh:
new_cfg = fh.read().splitlines()[:-1]
new_cfg.extend(config)
if options.debug:
print('\n'.join(new_cfg))
else:
fh.write('!\n!\n')
fh.write('\n'.join(config))
if __name__ == '__main__':
options = parse()
#### base_prefixes ####
base_v4 = 'ip address {ipv4_base}.{{0}}.{{1}} 255.255.255.0'
base_v6 = 'ipv6 address {ipv6_base}:{{0}}::{{1}}/64'
lo0_v4 = 'ip address {0}.{0}.{0}.{0} 255.255.255.255'
lo0_v6 = 'ipv6 address 2001:{0}:{0}:{0}::{0}/128'
#### base_prefixes ####
#### Constants ####
BASE_DIR = options.base_dir
CFG_DIR = os.path.join(BASE_DIR, options.project_files)
TOPO_FILE = os.path.join(BASE_DIR, options.topology_file)
IPV4_BASE = options.ipv4_base.strip('.')
IPV6_BASE = options.ipv6_base.strip(':')
base_v4 = base_v4.format(ipv4_base=IPV4_BASE)
base_v6 = base_v6.format(ipv6_base=IPV6_BASE)
#### Constants ####
data = json.load(open(TOPO_FILE))
nodes = [dict(node_id = node['dynamips_id'],
node_name = node['label']['text'],
config = node['properties']['startup_config'],
ports = [{'port_id' : port['id'],
'link_id' : port['link_id'],
'name' : port['name']}
for port in node['ports'] if 'link_id' in port])
for node in data['topology']['nodes']]
links = {link['id'] : (link['source_node_id'], link['destination_node_id'])
for link in data['topology']['links']}
for node in nodes:
configure_nodes(node)
if options.debug:
print(json.dumps(nodes, indent=4))
print(json.dumps(links, indent=4))
@julien-duponchelle
Copy link

Approved 👍

@routejunkie
Copy link

Can a similar python script be created to load different INE configs etc. Would be using a vmware esxi environment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment