Complete Example of Ansible Deployment for NetBox

Example

In my previous posts in this project, I have explained how to setup NetBox and a couple of the Ansible collection features. In this post, I want to demonstrate what is possible using this approach.

I have created multiple Ansible roles with different vars files containing a lot of configuration parameters.
The repo for this example can be found in my GitLab.

Ensure that there are environment vars or similar such as the Ansible Vault to pass in the NetBox URL and API Key

I will first start with an almost empty NetBox environment. I will require the devices created and the rack created. I need the devices created due to the NetBox API changing, and the rack is to be created as the NetBox API is looking for the rack ID dcim.rack:3 and not the name.

$ ansible-playbook site.yml 

PLAY [Playbook for configuring NetBox] ***************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [localhost]

TASK [customisation : SETUP CUSTOM FIELDS] ***********************************************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'bankfx_id', 'content_types': ['dcim.site', 'tenancy.tenant'], 'type': 'text', 'label': 'BankFX ID'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'route_leaking', 'content_types': ['ipam.vrf'], 'type': 'text', 'label': 'Route Leaking Info', 'description': 'Route leaking data in JSON format'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'bgp_local_asn', 'content_types': ['ipam.ipaddress'], 'type': 'integer', 'label': 'Local ASN', 'description': 'Local AS to use with peer'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'bgp_peer_asn', 'content_types': ['ipam.ipaddress'], 'type': 'integer', 'label': 'BGP Peer ASN', 'description': 'ASN of BGP Peers on this subnet'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_acl', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'Edge ACL', 'description': 'Inbound ACL to apply (must already exist)'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_as_prepend', 'content_types': ['ipam.ipaddress'], 'type': 'boolean', 'label': 'BGP AS Prepending', 'description': 'Prepend secondary AS Path or not'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_lp_inbound', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'BFP Local Pref', 'description': 'Applies appropriate local-pref to inbound prefixes'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_multihop', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'Enable EBGP Multihop', 'description': 'Enable EBGP Multihop 2 hops? (required for GCP)'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_password', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'BGP MD5 Password', 'description': 'Unencrypted (or prefixed/encrypted) password'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_peer_ip', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'Edge BGP Peer IP', 'description': 'Edge BGP Peer IP (optional for /30 or /31)'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_prefix_adv', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'BGP Advertised Prefixes', 'description': 'BGP Prefixes to advertise to peers from this IP (multiples allowed, comma separated), need to already be in BGP'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_prefix_agg', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'Edge BGP Prefixes to Aggregate', 'description': 'BGP Prefixes to aggregate to peers from this IP (multiples allowed, comma separated). Must add to edge_bgp_prefix_adv'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_prefix_recv', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'BGP Allowed Received Prefixes', 'description': 'Prefixes to allow from peer (prefix-list style) (multiples allowed, comma separated)'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_set_med', 'content_types': ['ipam.ipaddress'], 'type': 'boolean', 'label': 'BGP Set MED', 'description': 'Set MED on outbound prefixes'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'edge_bgp_timers', 'content_types': ['ipam.ipaddress'], 'type': 'text', 'label': 'BGP Timers', 'description': '[keepalive] [hold timer]'}, 'state': 'present'})

TASK [customisation : SETUP TAGS] ********************************************************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'XC', 'color': '673ab7', 'description': 'Cross Connect'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'DMZ', 'color': 'ff00ff'}, 'state': 'present'})

TASK [organisation : SETUP REGION] *******************************************************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'EMEA'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'APAC'}, 'state': 'present'})

TASK [organisation : SETUP SITES] ********************************************************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'uk1', 'time_zone': 'Europe/London', 'status': 'Active', 'region': 'EMEA', 'facility': 'DC1', 'slug': 'uk1', 'custom_fields': {'bankfx_id': '10'}}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'uk2', 'time_zone': 'Europe/London', 'status': 'Active', 'region': 'EMEA', 'facility': 'DC2', 'slug': 'uk2', 'custom_fields': {'bankfx_id': '128'}}, 'state': 'present'})

TASK [organisation : Create location within NetBox with a parent location] ***************************************************************************************************
ok: [localhost] => (item={'data': {'name': 'location1', 'site': 'uk1'}, 'state': 'present'})

TASK [organisation : Create rack role within NetBox with only required information] ******************************************************************************************
ok: [localhost] => (item={'data': {'name': 'LabRack', 'color': 'ffc107'}, 'state': 'present'})

TASK [organisation : Create rack within NetBox with only required information] ***********************************************************************************************
ok: [localhost] => (item={'data': {'name': 1, 'site': 'uk1', 'location': 'location1', 'status': 'active', 'facility_id': 'facilityid1', 'rack_role': 'LabRack'}, 'state': 'present'})

TASK [organisation : Create tenant within NetBox with only required information] *********************************************************************************************
ok: [localhost] => (item={'data': {'name': 'LPs', 'description': 'Liquidity Providers'}, 'state': 'present'})

TASK [organisation : Create tenant within NetBox with only required information] *********************************************************************************************
changed: [localhost] => (item={'data': {'name': 'Bank1', 'tenant_group': 'LPs', 'custom_fields': {'bankfx_id': 'SN123456789'}}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'Bank2', 'tenant_group': 'LPs', 'custom_fields': {'bankfx_id': 'SN987654321'}}, 'state': 'present'})

TASK [devices : Create Device Roles] *****************************************************************************************************************************************
ok: [localhost] => (item={'data': {'name': 'Leaf Switch', 'color': '9e9e9e', 'vm_role': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Edge Switch', 'color': '9e9e9e', 'vm_role': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Patch Panel', 'color': '673ab7', 'vm_role': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Virtualisation Host', 'color': '2196f3', 'vm_role': False}, 'state': 'present'})

TASK [devices : Create Manufacturers] ****************************************************************************************************************************************
ok: [localhost] => (item={'data': {'name': 'Arista'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Cisco'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Juniper'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Equinix'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Dell'}, 'state': 'present'})

TASK [devices : Create Device Types] *****************************************************************************************************************************************
ok: [localhost] => (item={'data': {'model': 'ASAv', 'manufacturer': 'Cisco', 'slug': 'asav', 'part_number': 'asav', 'is_full_depth': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'model': 'CSR1000v', 'manufacturer': 'Cisco', 'slug': 'csr1000v', 'part_number': 'csr1000v', 'is_full_depth': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'model': 'vEOS', 'manufacturer': 'Arista', 'slug': 'veos', 'part_number': 'veos', 'is_full_depth': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'model': '7060X', 'manufacturer': 'Arista', 'slug': '7060X', 'part_number': '7060X', 'is_full_depth': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'model': 'vSRX', 'manufacturer': 'Juniper', 'slug': 'vsrx', 'part_number': 'vsrx', 'is_full_depth': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'model': 'demarc', 'manufacturer': 'Equinix', 'slug': 'demarc', 'part_number': 'demarc', 'is_full_depth': False}, 'state': 'present'})
ok: [localhost] => (item={'data': {'model': 'R640', 'manufacturer': 'Dell', 'is_full_depth': True}, 'state': 'present'})

TASK [devices : Create Devices] **********************************************************************************************************************************************
ok: [localhost] => (item={'data': {'name': 'ld4leaf1', 'device_role': 'Leaf Switch', 'device_type': '7060X', 'site': 'UK1', 'status': 'staged'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'ld4leaf2', 'device_role': 'Leaf Switch', 'site': 'UK1', 'status': 'active'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'ld4leaf3', 'device_role': 'Leaf Switch', 'site': 'UK1', 'status': 'active'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'PP:0000:1219408', 'device_role': 'Patch Panel', 'location': 'location1', 'rack': 3, 'device_type': 'demarc', 'site': 'UK1', 'status': 'active'}, 'state': 'present'})
ok: [localhost] => (item={'data': {'name': 'Server1', 'device_role': 'Virtualisation Host', 'location': 'location1', 'rack': 3, 'face': 'front', 'position': 35, 'device_type': 'R640', 'site': 'UK1', 'status': 'active'}, 'state': 'present'})

TASK [devices : Create interface and assign it to parent LAG] ****************************************************************************************************************
changed: [localhost] => (item={'data': {'device': 'ld4leaf1', 'name': 'GigabitEthernet1', 'enabled': False, 'type': '1000Base-t (1GE)', 'mtu': 1600, 'mgmt_only': False, 'mode': 'Access', 'tags': ['DMZ', 'XC']}, 'state': 'present'})
changed: [localhost] => (item={'data': {'device': 'ld4leaf1', 'name': 'GigabitEthernet2', 'enabled': False, 'type': '1000Base-t (1GE)', 'description': 'Bank1', 'mtu': 1600, 'mgmt_only': False, 'mode': 'Access', 'tags': ['XC', 'DMZ']}, 'state': 'present'})
changed: [localhost] => (item={'data': {'device': 'ld4leaf1', 'name': 'GigabitEthernet3', 'enabled': False, 'type': '1000Base-t (1GE)', 'mtu': 1600, 'mgmt_only': False, 'mode': 'Access'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'device': 'ld4leaf1', 'name': 'port-channel1', 'type': 'Link Aggregation Group (LAG)', 'mtu': 1600, 'mgmt_only': False, 'mode': 'Tagged'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'device': 'ld4leaf1', 'name': 'GigabitEthernet4', 'enabled': False, 'type': '1000Base-t (1GE)', 'lag': {'name': 'port-channel1'}, 'mtu': 1600, 'mgmt_only': False, 'mode': 'Tagged'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'device': 'Server1', 'name': 'DRAC', 'enabled': True, 'type': '1000Base-t (1GE)', 'mgmt_only': True}, 'state': 'present'})
changed: [localhost] => (item={'data': {'device': 'Server1', 'name': 'NIC1', 'enabled': True, 'type': 'SFP+ (10GE)', 'mgmt_only': False}, 'state': 'present'})
changed: [localhost] => (item={'data': {'device': 'Server1', 'name': 'NIC2', 'enabled': True, 'type': 'SFP+ (10GE)', 'mgmt_only': False}, 'state': 'present'})

TASK [devices : Create rear port within NetBox with only required information] ***********************************************************************************************
changed: [localhost] => (item={'data': {'name': 'Test Rear Port', 'device': 'PP:0000:1219408', 'type': 'lc', 'description': 'rear port description', 'positions': 24}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'Bank1', 'device': 'PP:0000:1219408', 'type': 'lc', 'description': 'Bank1', 'positions': 1}, 'state': 'present'})

TASK [devices : Update front port with other fields] *************************************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'Bank1', 'device': 'PP:0000:1219408', 'type': 'lc', 'rear_port': 'Test Rear Port', 'rear_port_position': 1, 'description': 'Bank1'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'Test Front Port', 'device': 'PP:0000:1219408', 'type': 'lc', 'rear_port': 'Test Rear Port', 'rear_port_position': 5, 'description': 'front port description'}, 'state': 'present'})

TASK [devices : Create power port within NetBox with only required information] **********************************************************************************************
changed: [localhost] => (item={'data': {'name': 'Power A', 'device': 'Server1', 'type': 'iec-60320-c6', 'allocated_draw': 100, 'maximum_draw': 200}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'Power B', 'device': 'Server1', 'type': 'iec-60320-c6', 'allocated_draw': 100, 'maximum_draw': 200}, 'state': 'present'})

TASK [ipam : Create vrf within NetBox with only required information] ********************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'v001_v139_bank1', 'rd': 1111, 'tenant': 'Bank1', 'custom_fields': {'route_leaking': '{"route_leak_to": ["v001_v104_Prod", "v001_v124_ECN_Prod", "v001_v134_Maxx_Prod"]}'}}, 'state': 'present'})
changed: [localhost] => (item={'data': {'name': 'v139_bank1', 'rd': 1112, 'tenant': 'Bank1'}, 'state': 'present'})

TASK [ipam : Create vlan group within NetBox with only required information - Post 2.11] *************************************************************************************
changed: [localhost] => (item={'data': {'name': 'Edge VLANs', 'scope_type': 'dcim.site', 'scope': 'uk1'}, 'state': 'present'})

TASK [ipam : Create vlan with all information] *******************************************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'Bank1-2139', 'vid': 2139, 'site': 'uk1', 'vlan_group': 'Edge VLANs', 'tenant': 'Bank1', 'status': 'Active', 'description': 'Just a test', 'tags': ['DMZ']}, 'state': 'present'})

TASK [ipam : Create prefix with several specified options] *******************************************************************************************************************
changed: [localhost] => (item={'data': {'family': 4, 'prefix': '10.156.32.0/19', 'site': 'uk1', 'vrf': 'v139_bank1', 'status': 'Active', 'description': 'Test description', 'is_pool': False, 'tags': ['DMZ']}, 'state': 'present', 'first_available': False})
changed: [localhost] => (item={'data': {'prefix': '10.156.33.0/24', 'site': 'uk1', 'vrf': 'v139_bank1', 'tenant': 'Bank1', 'tags': ['DMZ']}, 'state': 'present', 'first_available': False})
changed: [localhost] => (item={'data': {'prefix': '10.156.34.0/24', 'site': 'uk1', 'vrf': 'v139_bank1', 'tenant': 'Bank1', 'tags': ['DMZ']}, 'state': 'present', 'first_available': False})
changed: [localhost] => (item={'data': {'prefix': '10.156.35.0/24', 'site': 'uk1', 'vrf': 'v139_bank1', 'tenant': 'Bank1', 'description': 'Bank1 peering', 'vlan': {'name': 'Bank1-2139', 'site': 'uk1', 'tenant': 'Bank1', 'vlan_group': 'Edge VLANs'}, 'tags': ['DMZ']}, 'state': 'present', 'first_available': False})

TASK [ipam : Create IP address with several specified options] ***************************************************************************************************************
changed: [localhost] => (item={'data': {'address': '10.156.35.74/32', 'vrf': 'v139_bank1', 'status': 'active', 'description': 'Dummy'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'address': '2a11:b4ca:ffee:0:139:128:0:6/128', 'vrf': 'v001_v139_bank1', 'tenant': 'Bank1', 'status': 'active', 'description': 'IPv6 NAT'}, 'state': 'present'})
changed: [localhost] => (item={'data': {'address': '10.156.35.174/32', 'vrf': 'v139_bank1', 'tenant': 'Bank1', 'status': 'active', 'description': 'IPv6 NAT', 'nat_inside': '2a11:b4ca:ffee:0:139:128:0:6/128', 'tags': ['DMZ']}, 'state': 'present'})

TASK [circuits : Create provider within NetBox with only required information] ***********************************************************************************************
changed: [localhost] => (item={'data': {'name': 'XC'}, 'state': 'present'})

TASK [circuits : Create type within NetBox with only required information] ***************************************************************************************************
changed: [localhost] => (item={'data': {'name': 'Cross-Connect', 'description': 'Cross-Connects to LPs, Buy-Sides and Service Providers'}, 'state': 'present'})

TASK [circuits : Create circuit within NetBox with only required information] ************************************************************************************************
changed: [localhost] => (item={'data': {'cid': 'Bank1-ID', 'circuit_type': 'Cross-Connect', 'tenant': 'Bank1', 'description': 'Bank1', 'tags': ['DMZ'], 'provider': 'XC'}, 'state': 'present'})

TASK [circuits : Create circuit termination within NetBox with only required information] ************************************************************************************
changed: [localhost] => (item={'data': {'circuit': 'Bank1-ID', 'term_side': 'Z', 'site': 'uk1', 'port_speed': 1000000, 'xconnect_id': 123456789}, 'state': 'present'})

PLAY RECAP *******************************************************************************************************************************************************************
localhost                  : ok=27   changed=18   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
$ tree
.
├── group_vars
│   └── all.yml
├── README.md
├── roles
│   ├── circuits
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── connections
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── customisation
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── devices
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── ipam
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   └── organisation
│       ├── defaults
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       └── vars
│           └── main.yml
└── site.yml

26 directories, 21 files

Leave a Comment

Your email address will not be published. Required fields are marked *