NetBox is a hugely popular open-source IP address management (IPAM) and data centre infrastructure management (DCIM) tool. NetBox provides a range of automation features, one of which is the ability to update NetBox with Ansible using the Ansible NetBox collection.
In this short post, we'll walk through the process of creating a device and adding a primary IP address, along with assigning a management interface and IP to the device using Ansible.
Prerequisites
- A working NetBox installation.
- Ansible installed on your machine.
- The
netbox.netbox
Ansible collection. Install it using:
ansible-galaxy collection install netbox.netbox
NetBox API URL and Token
Create an API Token within NetBox
- Log in to NetBox.
- Access your profile by clicking on your username in the top right.
- Navigate to API Tokens.
- Click Add a Token.
- The key will be used in the
.env
, in the next step.
Create an .env
In your project directory, create a .env
file:
NETBOX_URL=http://your-netbox-url
NETBOX_TOKEN=NETBOX_API_KEY
Load the .env
Load your environment variables so they will be available in your Ansible Playbook:
export $(cat .env)
Define Your Variables
Create a vars.yml
file that contains the following:
tenant_name: Acme1
site_name: Site1
ip_prefixes:
- prefix: 172.29.1.0/24
devices:
- device: rtr-spine1
interface: GigabitEthernet0/7
primary_ip: 172.29.1.101/24
- device: rtr-spine2
interface: GigabitEthernet0/7
primary_ip: 172.29.1.102/24
- device: rtr-spine3
interface: GigabitEthernet0/7
primary_ip: 172.29.1.103/24
Create the Ansible Playbook
Create a Playbook named pb_create_device_w_primary_ip.yml
.
Within this Playbook, we will, in NetBox:
- Create the IP prefix for our management network.
- Create the devices.
- Assign the IP to the mgmt interface.
- Set the required interface as mgmt
- Set the required interface (mgmt) to the primary IP.
Note: This Playbook presumes you already have created the:
- Tenant: Acme1
- Site: Site1
- Role: Spine
- Device type: Cisco IOSv
- Platform: ios
- name: Create Devices and Add Primary IP
hosts: localhost
gather_facts: no
vars:
NETBOX_ENDPOINT: "{{ lookup('env','NETBOX_ENDPOINT') }}"
NETBOX_TOKEN: "{{ lookup('env','NETBOX_TOKEN') }}"
vars_files:
- "../vars.yml"
tasks:
- name: Create IP Prefixes
netbox.netbox.netbox_prefix:
netbox_url: "{{ NETBOX_ENDPOINT }}"
netbox_token: "{{ NETBOX_TOKEN }}"
data:
prefix: "{{ item.prefix }}"
site: "{{ site_name }}"
tenant: "{{ tenant_name }}"
loop: "{{ ip_prefixes }}"
tags: prefix
- name: Create Devices
netbox.netbox.netbox_device:
netbox_url: "{{ NETBOX_ENDPOINT }}"
netbox_token: "{{ NETBOX_TOKEN }}"
data:
name: "{{ item.device }}"
site: "{{ site_name }}"
tenant: "{{ tenant_name }}"
device_type: cisco-iosv
device_role: spine
platform: ios
loop: "{{ devices }}"
tags: device
- name: Update Management IPs
netbox.netbox.netbox_ip_address:
netbox_url: "{{ NETBOX_ENDPOINT }}"
netbox_token: "{{ NETBOX_TOKEN }}"
data:
address: "{{ item.primary_ip }}"
assigned_object:
device: "{{ item.device }}"
name: "{{ item.interface }}"
loop: "{{ devices }}"
tags: mgmt
- name: Update Management Interfaces
netbox.netbox.netbox_device_interface:
netbox_url: "{{ NETBOX_ENDPOINT }}"
netbox_token: "{{ NETBOX_TOKEN }}"
data:
device: "{{ item.device }}"
name: "{{ item.interface }}"
mgmt_only: true
loop: "{{ devices }}"
tags: mgmt
- name: Update Primary IP
netbox.netbox.netbox_device:
netbox_url: "{{ NETBOX_ENDPOINT }}"
netbox_token: "{{ NETBOX_TOKEN }}"
data:
name: "{{ item.device }}"
site: "{{ site_name }}"
tenant: "{{ tenant_name }}"
primary_ip4: "{{ item.primary_ip }}"
loop: "{{ devices }}"
tags: device
Note: We use the device module twice within this Playbook. This is because we need the device to be present to assign an IP against it before we can mark the IP on the device as primary.
Run the Playbook
Next, we run the Playbook, like so:
$ ansible-playbook pb_create_device_w_primary_ip.yml
PLAY [Create Devices and Add Primary IP] **************************************************************************************
TASK [Create IP Prefixes] *****************************************************************************************************
changed: [localhost] => (item={'prefix': '172.29.1.0/24'})
TASK [Create Devices] *********************************************************************************************************
changed: [localhost] => (item={'device': 'rtr-spine1', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.101/24'})
changed: [localhost] => (item={'device': 'rtr-spine2', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.102/24'})
changed: [localhost] => (item={'device': 'rtr-spine3', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.103/24'})
TASK [Update Management IPs] **************************************************************************************************
changed: [localhost] => (item={'device': 'rtr-spine1', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.101/24'})
changed: [localhost] => (item={'device': 'rtr-spine2', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.102/24'})
changed: [localhost] => (item={'device': 'rtr-spine3', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.103/24'})
TASK [Update Management Interfaces] *******************************************************************************************
changed: [localhost] => (item={'device': 'rtr-spine1', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.101/24'})
changed: [localhost] => (item={'device': 'rtr-spine2', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.102/24'})
changed: [localhost] => (item={'device': 'rtr-spine3', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.103/24'})
TASK [Update Primary IP] ******************************************************************************************************
changed: [localhost] => (item={'device': 'rtr-spine1', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.101/24'})
changed: [localhost] => (item={'device': 'rtr-spine2', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.102/24'})
changed: [localhost] => (item={'device': 'rtr-spine3', 'interface': 'GigabitEthernet0/7', 'primary_ip': '172.29.1.103/24'})
PLAY RECAP ********************************************************************************************************************
localhost : ok=5 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Based on the Ansible output, we can see the changes to NetBox. Great!
But we can also see from NetBox that the devices are now present.
Closing Comments
I hope you`ve enjoyed this post. Populating NetBox using Ansible, coupled with YAML, offers many benefits. This approach accelerates the onboarding of data into a Source of Truth (SoT) and ensures that the process is more repeatable and less prone to errors. Great stuff! Until next time - Happy automating!