Skip to content

Creates all the objects required to build a base NetBox environment ready to add devices (does not create devices)

Notifications You must be signed in to change notification settings

sjhloco/sjhloco-netbox_env_setup

Repository files navigation

NetBox - Baseline Environment

This script will create all the objects within the NetBox environment ready for the addition of devices, it does not add the devices themselves. It is not idempotent as the purpose is to add objects rather than edit or delete existing objects. The Netbox environment is defined in YAML files that follow the hierarchical structure of the NetBox menus. The script follows this same structure allowing sub-sections of the environment to be created or additions to be made to an existing section.

This has been tested against v3.1.7, it wont work on v2.x due to the changes made to the NetBox post v2.8

API Engine

From the YAML input files Data-Models (per-menu) are built and fed into the API engine to create any objects that do not already exist. The obj_check method verifies whether an object already exists and uses obj_create to create the NetBox objects and handle errors.

Data Models

Each NetBox menu is represented by a separate data-model class (from dm.py) that is instantiated using dictionaries from the input file to create a list of dictionaries for each of the objects under that NetBox menu. These dictionaries are passed through the engine class (from netbox.py) which hold all the methods that interact with NetBox to check object existence and perform object creation.

All data-model classes are built in the same format consisting of cr_xxx methods to create object data-models and a create_xxx method to run all the cr_xxx methods and return the complete data-model. Below is an example of how Organisation objects are created by first instantiating the class using input friendly name (for stdout message), path of api call, filter (to check if object already exists) and data-model are passed into the engine.

org = Organisation(my_vars["tenant"], my_vars["rack_role"])
org_dict = org.create_tnt_site_rack()

nbox.engine("Rack Role", "dcim.rack_roles", "name", org_dict["rack_role"])
nbox.engine("Tenant", "tenancy.tenants", "name", org_dict["tnt"])
nbox.engine("Site", "dcim.sites", "name", org_dict["site"])
nbox.engine("Location (parent)", "dcim.locations", "slug", org_dict["prnt_loc"])
nbox.engine("Location (child)", "dcim.locations", "slug", org_dict["chld_loc"])
nbox.engine("Rack", "dcim.racks", "name", org_dict["rack"])

Input data

The input data can be defined in the one file or split over multiple YAML files (.yml and .yaml) of any name with the script loading only YAML files in the directory. Because of the hierarchical structure of the YAML file the mandatory dictionary elements will still be required in the file even if those objects are not being created by this script. For example, to create a rack the YAML file needs the tenant, site and location. There are a few example setups in the examples directory to show how the files are structured.

full: An example setup with all the available options defined
simple1: A more streamlined example with just the bare minimum options defined
simple2: Same as last example but VLANs are under a site rather than a VLAN group work_setup: Structured more for a corporate environment in terms of sites and the roles within IPAM

For most options the slug is optional and if not defined will be automatically generated from the name replacing any white-spaces with _. Make sure to set the slug if you have multiple objects with the same name.

Organisation - Tenants, Sites, Locations, Racks, Rack-roles

Tenants are top of the tree with optional sites that contain locations (and child locations) that in turn contain racks.

Object Description Mandatory Optional
tenant List of tenants name slug, descr, tags, site
tenant.site List of sites name slug, descr, tags, time_zone, ASN, location
tenant.site.location List of locations (like a floor) name slug, descr, tags, rack, location
tenant.site.location.rack List of racks name tags, role, height, tenant
tenant.site.location.location List of child locations (like a room) name slug, descr, tags, rack
tenant.site.location.location.rack List of racks in child locations name tags, role, height, tenant
rack-role List of rack roles name, color, slug, descr, tags

Be careful with child locations as if you are using a generic name such as Room1 although it is nested under the parent location in the GUI you need to make sure you define a unique slug as under the hood is no hierarchy.

Devices - Manufacturers, Platforms, Device-types, Device-roles

The device-types are built from pre-defined YAML files that can be downloaded from the NetBox community or custom created using that same format. By default these are expected to be stored in the device_type directory.

Object Description Mandatory Optional
manufacturer List of all device manufacturers name slug, descr, tags, platform
manufacturer.platform List of platforms (used for NAPALM) name slug, descr, tags, driver
manufacturer.device_type List of device-type yaml files device-type.yaml n/a
device_role List of device roles (to assign to device types) name, color slug, descr, tags, vm_role

IPAM - RIR, Aggregates, Prefix/VLAN roles, VLAN groups, VLANs, VRFs, Prefixes

Prefix/VLAN roles are at the top of the IPAM hierarchy grouping together VLANs and prefixes. VLAN-groups, VLANs, VRFs and prefixes are all in some way related to sites and tenants so are defined under the site with the sites tenant automatically associated or overridden on a per-VLAN group, VLAN, VRF or prefix basis.

  • A Prefix/VLAN role can only be used once in the file, it holds all VRFs and VLANs to be added beneath it.
  • A VRF or VLAN group can be used multiple times under differing prefix/VLAN roles with the attributes of the first occurrence (description, RT, RD, etc) taken.
  • VRFs (and prefixes) can be defined under the role (non-VLAN environments like clouds) or the VLAN group (to associate prefixes with VLANs). RDs are what make VRFs with the same name unique.
  • VLANs can be grouped under a VLAN group or directly under the site. If you deploy them under the site NetBox does not enforce VLAN uniqueness however the script will not redeploy a VLAN if it already exists in that site. I prefer to use VLAN groups as they enforce uniqueness and provide a better view of unused VLANs.
Object Description Mandatory Optional
rir List of governing bodies (includes RFC1918) name slug, descr, tags, is_private, aggregate
rir.aggregate List of aggregates in the RIR (your assigned PA or PI prefixes) prefix descr, tags
role List of prefix and VLAN roles name, site slug, descr, tags
role.site List of existing sites to associate VLANs, VRFs and prefixes name vlan_grp, vrf
role.site.vlan_grp List of VLAN groups name, vlan slug, descr, tags, tenant, vrf
role.site.vlan_grp.vlan List of VLANs in the VLAN group name, id descr, tags, tenant
role.site.vlan_grp.vrf VRFs in a site with VLANs (prefixes can be linked to VLANs) name, prefix descr, tags, tenant, rd, import_rt, export_rt, unique
role.site.vlan_grp.vrf.prefix List of prefixes within this VRF pfx descr, tags, status, vl, pool, tenant
role.site.vlan List of VLANs in a site (no vlan group) name, id descr, tags, tenant
role.site.vrf VRFs whose prefixes aren't associated to VLANs or are associated to site VLANs name, prefix descr, tags, tenant, rd, import_rt, export_rt, unique
role.site.vrf.prefix List of prefixes within this VRF pfx descr, tags, tenant, pool

Using Null as the VRF name will add the prefixes to the NetBox Global VRF. Using this in conjunction with a prefix status of container allows for prefixes from differing VRFs to be seen as child prefixes under this parent prefix. Null can also be used for the site to associate the prefixes with no particular site. By default all prefixes are not a pool unless specifically set as one.

Provider/ Circuit - Circuit-type, Provider, Circuit

Providers are the ISPs that hold individual circuits with pre-defined circuit-types.

Object Description Mandatory Optional
circuit_type List of circuit types name slug, descr, tags
provider List of providers name slug, comments, tags, asn, account_num, portal_url, circuit
provider.circuit List of this providers circuits cid, type descr, tags, tenant, commit_rate, comments

Virtual - Cluster-group, Cluster-type, Cluster

Clusters are groupings of resources which VMs run within. Cluster-groups and types allow further grouping of clusters based on things such as location or technology. Site, tenant, cluster-group and tags can be set globally for all members of a cluster-type or be overridden on a per-cluster basis.

Object Description Mandatory Optional
cluster_group List of groups (optional) name slug, descr, tags
cluster_type List of cluster type name slug, descr, tags, cluster
cluster_type.cluster List of clusters of this cluster type name comment, tags, tenant, site, group,

Contacts - Contact-role, Contact-group, Contact Assignment

Contacts are actually in the organisation menu but are defined separately as they can be assigned to a tenant, site, location, rack, manufacturer, cluster-group, cluster, provider or circuit (in GUI you can also assign Device, PowerPanel, Region, SiteGroup, and VirtualMachine).

Object Description Mandatory Optional
contact_role List of contact roles name slug, descr, tags
contact_group List of contact groups name slug, descr, tags
contact_group.contact List of contacts (can only be member of 1 group) name comments, tags, phone, email, addr
contact_assign Assign contacts to roles assign_to, role, contact priority

Installation and Prerequisites

Clone the repository and create a virtual environment.

git clone https://github.com/sjhloco/sjhloco-netbox_env_setup.git
python -m venv ~/venv/nbox/
source ~/venv/nbox/bin/activate

Install the required packages.

cd sjhloco-netbox_env_setup
pip install -r requirements.txt

The first section of the script holds customisable values for the default base directory and folder name (used if not defined at run time), device-type template directory, disabling SSL verification and SSL cert location (if using HTTPS with a self-signed certificate).

dvc_type_dir = os.path.join(os.getcwd(), "device_type")
base_dir = os.getcwd()
input_dir = "full_example"

netbox_url = config.netbox_url
api_token = config.api_token
ssl = False
os.environ['REQUESTS_CA_BUNDLE'] = '/Users/user1/Documents/nbox_py_scripts/myCA.pem'

The token and NetBox API URL is set in a separate config.py variable file that I .gitignore so as not to share with the rest of the world. This is imported with import config so you either need to add this file or remove the import line and add the token and URL directly in the script. All that config.py holds is a single token variable:

netbox_url = "http://10.30.10.104:8000/"
api_token = 'my_token_got_from_netbox'

Usage

Before running nbox_env_setup.py it is recommended to use input_validate.py to verify the contents of input YAML files. It is an offline script (doesn't connect to NetBox) that verifies things such as:

  • All parent dictionaries (tenant, manufacturer, rir, role, crt_type, provider, cluster_type, contact_role, contact_group, contact_assign) are present and the key is a list (can be an empty list if not used)
  • All mandatory dictionaries are present
  • All Dictionary keys that are meant to be a list, integer, boolean or IPv4 address are of the correct format
  • No duplicate object names
  • All referenced objects such as tenant, site, rack_role, etc, exist within the input file. If you are not running all tests (for example don't have organisation defined) you will get dependency warnings as it will look for objects such as sites and tenants which don't exist. Can either ignore these or add them to the all_site, all_tnt and all_obj lists to stop the warnings
python input_validate.py simple_example

The script can be run with no flags to create all objects or with flags to only create specific section objects.

Flag Description
-o or --organisation Create Organisation objects (Circuit-type, Provider, Circuit)
-d or --device Create Device objects (Manufacturers, Platforms, Device-types, Device-roles)
-i or --ipam Create IPAM objects (RIR, Aggregates, Prefix/VLAN roles, VLAN groups, VLANs, VRFs, Prefixes)
-p or --provider Create Provider objects (Circuit-type, Provider, Circuit)
-c or --contact Create Contact objects (Cluster-group, Cluster-type, Cluster)
-v or --virtual Create Virtualisation objects (Contact-role, Contact-group, Contact Assignment)
none Create everything
python nbox_env_setup.py simple_example

There are three possible outcomes from the attempt to create each object which are relayed back in stdout:
✅ Object created
⚠️ Object already exists
❌ Object can’t be created due to the defined error

run_example_video

Unit test

Unit-testing uses pytest test the majority of situations for the data-modeling (test_dm.py) and netbox api calls (test_netbox.py). The netbox testing script requires a netbox URL and API as it will build and destroy a test netbox setup to run the tests against.

pytest -vv
pytest tests/test_dm.py -vv
pytest tests/test_netbox.py -vv

About

Creates all the objects required to build a base NetBox environment ready to add devices (does not create devices)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages