Last active
November 26, 2018 13:27
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
GNS3_auto_ip_script | |
author: [email protected] | |
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)) |
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
Approved 👍