Copying Files to Multi-Vendor Network Devices Using Ansible

  • April 29, 2016

Ever need to copy a file to more than one network device? Maybe a config file, operating system- it doesn't matter what it is, but if you've done this manually, you've wasted valuable time. In this tutorial, we look at using Ansible, and specifically the ntc_file_copy module to copy files to different types of devices such as Cisco Nexus, Cisco IOS, Arista EOS, and Juniper Junos devices.

Our setup has 4 network devices:

  • csr1 - Cisco IOS router
  • nxos-spine1 - Cisco Nexus switch
  • eos-spine1 - Arista switch
  • vmx1 - Juniper MX router

We are going to show how to copy a different file to each device in a single Anisble task.

Create Files

We are going to create four files with arbitrary text. In reality, this could be OS images or config files.

ntc@ntc:~/copy$ echo ARISTA > eos.conf
ntc@ntc:~/copy$ echo CISCO IOS > ios.conf
ntc@ntc:~/copy$ echo CISCO NEXUS > nxos.conf
ntc@ntc:~/copy$ echo JUNOS > junos.conf
ntc@ntc:~/copy$ 

Create Ansible Inventory

We are going to create an Ansible inventory called inventory with 4 groups and then define two group variables per group. It is one group per device type and then variables for the filename and type of platform. These will be used as inputs to the Ansible module.

[all:vars]
un=ntc
pwd=ntc123

[nxos]
nxos-spine1

[eos]
eos-spine1

[ios]
csr1

[junos]
vmx1

[nxos:vars]
filename=nxos.conf
net_platform=cisco_nxos_nxapi

[ios:vars]
filename=ios.conf
net_platform=cisco_ios_ssh

[eos:vars]
filename=eos.conf
net_platform=arista_eos_eapi

[junos:vars]
filename=junos.conf
net_platform=juniper_junos_netconf

Create Playbook

We are going to create a playbook called filecopy.yml with a single task that copies all files to the respective device. We can do this in a single task because we created the proper variables in the inventory file.

---
  - name: PLAY - FILE COPY
    hosts: all
    gather_facts: no
    connection: local

    tasks:

      - name: ENSURE FILES ARE ON REMOTE DEVICES
        ntc_file_copy:
          local_file={{ filename }}
          platform={{ net_platform }}
          host={{ inventory_hostname }}
          username={{ un }}
          password={{ pwd }}

Note: as you start to scale, it's recommended using proper vars files rather than storing variables in the inventory, but the goal here is simply to show how to use the ntc_file_copy module.

Of course, you could have also done 4 tasks, one per device type, but that wouldn't have been very clean :)

Execute the Playbook

We are now ready to run the playbook.

ntc@ntc:~/copy$ ansible-playbook -i inventory filecopy.yml 

PLAY [PLAY - FILE COPY] ******************************************************* 

TASK: [ENSURE FILES ARE ON REMOTE DEVICES] ************************************ 
changed: [nxos-spine1]
changed: [eos-spine1]
changed: [vmx1]
changed: [csr1]

PLAY RECAP ******************************************************************** 
csr1                       : ok=1    changed=1   unreachable=0    failed=0   
eos-spine1                 : ok=1    changed=1   unreachable=0    failed=0   
nxos-spine1                : ok=1    changed=1    unreachable=0    failed=0   
vmx1                       : ok=1    changed=1    unreachable=0    failed=0  

This module is also idempotent, so you can run it again, and no files are copied to the device. Assuming a file with the same name and MD5 checksum exist on the remote device, the file is not copied again to the device. You can see the output below when running the playbook again.

ntc@ntc:~/copy$ ansible-playbook -i inventory filecopy.yml 

PLAY [PLAY - FILE COPY] ******************************************************* 

TASK: [ENSURE FILES ARE ON REMOTE DEVICES] ************************************ 
ok: [eos-spine1]
ok: [nxos-spine1]
ok: [vmx1]
ok: [csr1]

PLAY RECAP ******************************************************************** 
csr1                       : ok=1    changed=0    unreachable=0    failed=0   
eos-spine1                 : ok=1    changed=0    unreachable=0    failed=0   
nxos-spine1                : ok=1    changed=0    unreachable=0    failed=0   
vmx1                       : ok=1    changed=0    unreachable=0    failed=0 

-Jason