NetBox Ansible Collection: Site Module
This post dives into the NetBox Ansible Content Collection module to create/update a Site. As I start into this series on looking at the modules that create/update/delete data from NetBox, the question that I keep asking myself is should I be looking at the modules that are creating/updating/deleting items? The reason that I ask this to myself is because I am a firm believer that automation should be coming from NetBox as its Source of Truth (SoT). You can hear/read plenty more about these thoughts on posts and videos here:
Note
This post was created when NetBox was an open source project used often in my automation framework. I have moved on to using Nautobot due to the project vision and providing a methodology that will drive network automation forward further. You may want to take a look at it yourself.
When it comes to creating and deleting sites in NetBox, this one is an easy one. In my opinion this is a yes it should be. Most likely an IT tool is not the tool that will be the Source of Truth as it comes to physical sites. So this module in particualr that should be looked at and put into production use with Ansible.
Environment#
For this demo, here are the versions shown:
Component | Version |
---|---|
NetBox | v2.9.9 (NetBox Docker) |
NetBox Ansible Collection | v1.1.0 |
pynetbox | 5.1.0 |
Site Module#
Within NetBox, the site is the most basic unit, and is required for devices to be added. This is the first thing that you should do when creating a NetBox instance is to start to build out sites. There are a many set of parameters that you can add to your sites, but the minimum required are:
- name: The name of the site
Take a look at the documentation for all of the additional parameters. The ones that stick out to me (and there are many more) include:
- asn: The BGP AS Number
- contact name & email: Site contact information
- physical and shipping addresses
- tags
- time_zone
Examples#
The point of these posts are to show examples and get you started. So let's get started. At the beginning of this there are going to be four sites that we can check out with the query function:
The data here instead of coming from a system of record that has sites will come from a YAML file. So the first step would be to look at getting data from a data source that has sites. This could be a CRM tool if you were a MSP, or any other tooling that has your sites. Here is what the data would look like:
---
sites:
- name: MSP
time_zone: America/Chicago
status: active
description: Minneapolis
- name: DEN
time_zone: America/Denver
status: active
description: Denver
- name: NYC
time_zone: America/New_York
status: active
description: New York
- name: PDX
time_zone: America/Los_Angeles
status: active
description: Portland
Running the following playbook multiple times will show that the module itself is idempotent in that it will not keep creating sites.
---
- name: "SETUP SITES"
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: "05 - QUERY SITES"
set_fact:
site_list_before: "{{ query('netbox.netbox.nb_lookup', 'sites') | json_query('[*].value.name') }}"
- name: "10 - SETUP SITES"
netbox.netbox.netbox_site:
netbox_url: "{{ lookup('env', 'NETBOX_URL') }}"
netbox_token: "{{ lookup('env', 'NETBOX_TOKEN') }}"
data: "{{ site }}"
state: present
validate_certs: False
loop: "{{ sites }}"
loop_control:
loop_var: site
label: "{{ site['name'] }}"
The output below is from a second run. The sites for the current NetBox demo was originally deployed with this.
In here we see that there were two tasks that showed ok and no tasks in the other sections of the play recap.
Adding an additional site#
The source for the sites just had a new site added. This is adding the Orlando location. As such the data now looks like this:
---
sites:
- name: MSP
time_zone: America/Chicago
status: active
description: Minneapolis
- name: DEN
time_zone: America/Denver
status: active
description: Denver
- name: NYC
time_zone: America/New_York
status: active
description: New York
- name: PDX
time_zone: America/Los_Angeles
status: active
description: Portland
- name: MCO
time_zone: America/New_York
status: active
description: Orlando
With the new location, the Ansible Playbook is executed and we see a new site is added:
Taking a look at line 45 in this last execution you see the message site MCO created. This shows that it as created and there was a task that showed chagned in the play recap.
Removing Sites#
In this example for the removing of sites I am going to keep it a little bit more manual. I'm going to create a new variable in the group_vars/all/sites.yml
file called closed_sites
. So in this scenario the Orlando site was opened, but very quickly it was decided to close it down. So now we need to remove the site from NetBox. The group_vars/all/sites.yml
now looks like below:
---
sites:
- name: MSP
time_zone: America/Chicago
status: active
description: Minneapolis
- name: DEN
time_zone: America/Denver
status: active
description: Denver
- name: NYC
time_zone: America/New_York
status: active
description: New York
- name: PDX
time_zone: America/Los_Angeles
status: active
description: Portland
closed_sites:
- name: MCO
time_zone: America/New_York
status: active
description: Orlando
The updated Ansible Playbook now needs to remove any sites that are showing up in the closed sites:
---
- name: "SETUP SITES"
hosts: localhost
connection: local
gather_facts: no
tasks:
- name: "05 - QUERY SITES"
set_fact:
site_list_before: "{{ query('netbox.netbox.nb_lookup', 'sites') | json_query('[*].value.name') }}"
- name: "10 - SETUP SITES"
netbox.netbox.netbox_site:
netbox_url: "{{ lookup('env', 'NETBOX_URL') }}"
netbox_token: "{{ lookup('env', 'NETBOX_TOKEN') }}"
data: "{{ site }}"
state: present
validate_certs: False
loop: "{{ sites }}"
loop_control:
loop_var: site
label: "{{ site['name'] }}"
- name: "20 - REMOVE CLOSED SITES"
netbox.netbox.netbox_site:
netbox_url: "{{ lookup('env', 'NETBOX_URL') }}"
netbox_token: "{{ lookup('env', 'NETBOX_TOKEN') }}"
data: "{{ site }}"
state: absent
validate_certs: False
loop: "{{ sites }}"
loop_control:
loop_var: site
label: "{{ site['name'] }}"
- name: "25 - QUERY SITES AT END"
set_fact:
site_list_end: "{{ query('netbox.netbox.nb_lookup', 'sites') | json_query('[*].value.name') }}"
- name: "30 - SHOW RESULTS"
debug:
msg:
- "{{ site_list_before }}"
- "{{ site_list_end }}"
The result of the playbook shows that we had the site at the beginning, then we were able to successfully remove it in Task 20 to remove the closed sites.
When removing a site, you do need to make sure that all of the corresponding devices and other relationships are gone from the site. NetBox will not allow you to remove a site without it being empty first.
Summary#
This module is a very good module with a lot of options to get you started. This is absolutely a module that I would become familiar with as your organization is changing over time. This will allow you to keep your NetBox environment up to date with the site changes as you get new and closed sites alike. Hopefully this has been helpful to demonstrate it's capabities. Let me know your comments below, or give it a thumbs up if you have found this helpful.
Thanks,
Josh
Share on Share on Share on Share on Share on