Add Virtual Machine to NetBox with an Ansible playbook

Table of contents

  1. Automation / Orchestration
  2. Install Ansible Netbox.Netbox Collection
  3. Prepare the NetBox API-Token
  4. Prepare an Ansible role for NetBox
  5. Setting up Ansible role
    1. Set up role variables
    2. Set up main-task
    3. Set up sub-task
  6. Inventory File
  7. Run Ansible playbook
  8. Things to improve

Automation / Orchestration

I’m playing around with automation/orchestration at the moment to get rid off some manual tasks I’m using for my home network lab. To automate/orchestrate tasks I’m using Ansible and I saw that a collection for NetBox is also available.

In this blog post I’m showing how to get a Virtual Machine, defined in an Ansible inventory file, into the NetBox DCIM (Data Center Information Management) tool.

Install Ansible Netbox.Netbox Collection

The NetBox Ansible Collection must be installed on the Ansible Host first. This can be accomplished by executing the command line shown below:


    ansible-galaxy collection install netbox.netbox

Prepare the NetBox API-Token

To use the NetBox Ansible Collection, an API-Key in NetBox is required. To separate API users from human users, a dedicated API user is set up. This API user creates an API token and the IP address is limited to the IP address of the Ansible Host.

Netbox API tokens for Ansible

Prepare an Ansible role for NetBox

For handling various tasks in NetBox, an Ansible role can be created with this command:


    ansible-galaxy init netbox

The created Ansible role will have this directory structure:


    .
    ├── defaults
    │   └── main.yml
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   ├── main.yml        <--- Includes netbox_vm.yml file
    │   ├── netbox_vm.yml   <--- Tasks to add VM and Interfaces to NetBox
    │   └── ....yml         <--- Other NetBox-related tasks
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml        <--- NetBox URL and API Token Vars

Setting up Ansible role

To set up the Ansible role, three files have to be changed and/or created. Those files are:

  • ./vars/main.yml - NetBox URL and API Token Vars

  • ./tasks/main.yml - Includes netbox_vm.yml file

  • ./tasks/netbox_vm.yml - Tasks to add VM and Interfaces to NetBox

Set up role variables

The file ./vars/main.yml contains the NetBox URL and created NetBox API token as variables. Those variables are used in the ./tasks/netbox_vm.yml file. Example:


    ---
    # Vars file for NetBox
    netbox_url: "https://[FQDN_TO_YOUR_NETBOX_HOST]"
    netbox_token: "[GENERATED_NETBOX_API_TOKEN]"

Set up main-task

The file ./tasks/main.yml includes the ./tasks/netbox_vm.yml (and eventually other NetBox-related) files. This file might look like this:


    ---
    # Main-Task for NetBox
    - include: netbox_vm.yml

Set up sub-task

The file ./tasks/netbox_vm.yml is doing the “heavy job” to add a Virtual Machine and two interfaces (if used) to NetBox. The single tasks are “grouped together” by using the block: statement. To ensure the task is executed by the Ansible Host, the statement delegate_to: at the end of the block is used:


    ---
    #
    # Sub-Task to add VM + Interface to NetBox
    #
    - name: "Add Virtual Machine to NetBox"
      block:

        #
        # Task to add a Virtual Machine including some configuration
        # information like vcpu, memory, disk, comments
        #
        - name: "Add Virtual Machine"
          netbox.netbox.netbox_virtual_machine:
            #
            # use variables defined in role
            #
            netbox_url: "{{ netbox_url }}"
            netbox_token: "{{ netbox_token }}"
            data:
              name: "{{ netbox_name }}"
              status: "{{ netbox_status }}"
              virtual_machine_role: "{{ netbox_role }}"
              site: "{{ netbox_site }}"
              cluster: "{{ netbox_cluster }}"
              platform: "{{ netbox_platform }}"
              vcpus: "{{ netbox_vcpus }}"
              memory: "{{ netbox_memory }}"
              disk: "{{ netbox_disk }}"
              comments: "{{ netbox_comments }}"
            state: present

        #
        # Task to add interface eth0
        #
        - name: "Add interface eth0 to Virtual Machine"
          netbox.netbox.netbox_vm_interface:
          #
          # use variables defined in role
          #
            netbox_url: "{{ netbox_url }}"
            netbox_token: "{{ netbox_token }}"
            data:
              virtual_machine: "{{ netbox_name }}"
              name: "eth0"
              description: "{{ netbox_eth0_description }}"
              enabled: true
            state: present
          #
          # Perform task only if true
          #
          when: netbox_eth0 == true

        #
        # Task to add interface eth1
        #
        - name: "Add interface eth1 to Virtual Machine"
          netbox.netbox.netbox_vm_interface:
          #
          # use variables defined in role
          #
            netbox_url: "{{ netbox_url }}"
            netbox_token: "{{ netbox_token }}"
            data:
              virtual_machine: "{{ netbox_name }}"
              name: "eth1"
              description: "{{ netbox_eth1_description }}"
              enabled: true
            state: present
          #
          # Perform task only if true
          #
          when: netbox_eth1 == true

      #
      # Ensure tasks are executed on Ansible host
      #
      delegate_to: localhost

Inventory File

The Inventory files must contain the NetBox-specific variables used in the task. Those variables might look like this:


    ---
    netbox_name: "[FQDN_HOSTNAME_OF_VM]"    # test-vm.example.com
    netbox_status: "Active"                 # Active, Planned, ...
    netbox_role: "[NETBOX_ROLE]"            # Virtual-Machine
    netbox_site: "[NETBOX_SITE]"            # Example-Site
    netbox_cluster: "[NETBOX_VM_CLUSTER]"   # cluster0815.example.com
    netbox_platform: "[NETBOX_PLATFORM]"    # Debian Linux
    netbox_vcpus: 4
    netbox_memory: 4096
    netbox_disk: 50
    netbox_comments: "**Description**\n\n[HOST_DESCRIPTION]" # Web Server Testing
    netbox_eth0: true
    netbox_eth0_description: "[INTERFACE_DESCRIPTION]"       # vlan-server
    netbox_eth1: true
    netbox_eth1_description: "[INTERFACE_DESCRIPTION]"       # vlan-management

Run Ansible playbook

To test the role, a simple playbook can be used. This might look in a file deploy_test-vm.yml like this:


    ---
    - hosts: test-vm
      gather_facts: no
      roles:
      - netbox

To run the platbook, the following command line can be used:


    ansible-playbook playbooks/deploy_test-vm.yml

After the run of the playbook, NetBox shows in Virtual Machines the created Virtual Machine:

Netbox with created Virtual Machine

Things to improve

If a Virtual Machine is deleted, tasks to remove the Virtual Machine from NetBox can be addded.

Additional information like IP addresses or services can be added.