Arista et le framework Nornir

Lorsque l’objectif est d’utiliser Python 3 pour automatiser l’accès aux équipements Arista, le framework Python Nornir apporte une aide précieuse. Pour les connexions, Nornir peut utiliser NAPALM, Netmiko, Paramiko ou Netconf.

La librairie NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) est indiqué pour se connecter aux équipements Arista. Il s’appuie sur la librairie pyeapi avec un bon niveau de support des fonctionnalités.

Fichier de configuration Nornir :

---
core:
    num_workers: 100
inventory:
    plugin: nornir.plugins.inventory.simple.SimpleInventory
    options:
        host_file: "inventory/hosts.yaml"
        group_file: "inventory/groups.yaml"
        defaults_file: "inventory/defaults.yaml"

Fichiers inventory/ :

---
ceos1:
    hostname: 127.0.0.1
    port: 4443
    groups:
        - ceos

veos1:
    hostname: 192.168.1.60
    groups:
        - veos

veos2:
    hostname: 192.168.1.61
    groups:
        - veos
---
ceos:
    platform: 'eos'

veos:
    platform: 'eos'
    data:
        vlans:
            - {id: 10, name: test10, ip: 10.10.10.254}
            - {id: 20, name: test20, ip: 10.10.20.254}
        accesses:
            - {interface: 3, vlan_id: 10}
            - {interface: 4, vlan_id: 20}
        trunks:
            - {interface: 1, id: 1}
            - {interface: 2, id: 1}
---
username: 'admin'
password: 'arista'

Fichier script :

#!/usr/bin/env python
import nornir
import nornir.plugins.tasks.networking as nptn
import nornir.plugins.functions.text as npft
import nornir.core.filter as ncf


def arista_get_version():
    nr = nornir.InitNornir(config_file='config.yaml')
    veos = nr.filter(ncf.F(groups__contains='veos'))
    npft.print_title('Playbook to display virtual switch version')
    results = veos.run(
        task=nptn.napalm_get,
        getters=["facts"]
    )
    for host, r in results.items():
        print(host, '-->', r.result['facts']['os_version'])
#!/usr/bin/env python
import nornir
import nornir.plugins.tasks.networking as nptn
import nornir.plugins.functions.text as npft
import nornir.core.filter as ncf
import datetime as date


def arista_get_config():
    nr = nornir.InitNornir(config_file='config.yaml')
    veos = nr.filter(ncf.F(groups__contains='veos'))
    results = veos.run(
        task=nptn.napalm_get,
        getters=['config'],
        getters_options={'config': {'retrieve': 'running'}}
    )
    for host, r in results.items():
        npft.print_title('Record ' + host + ' virtual switch running config')
        out_filename = host + '_' + date.datetime.now().strftime('%Y-%m-%d_%H:%M:%S') + '.conf'
        with open(out_filename, 'w') as out_file:
            out_file.write(r.result['config']['running'])


if __name__ == '__main__':
    arista_get_config()
#!/usr/bin/env python
import nornir
import nornir.plugins.tasks.networking as nptn
import nornir.plugins.tasks.text as nptt
import nornir.plugins.functions.text as npft
import nornir.core.filter as ncf

def arista_configuration(task):
    template = task.run(
        task=nptt.template_file,
        template='configuration.j2',
        path='templates/'
    )
    task.host['config'] = template.result
    results = task.run(
        task=nptn.napalm_configure,
        configuration=task.host['config']
    )


def arista_config_template():
    nr = nornir.InitNornir(config_file='config.yaml')
    veos = nr.filter(ncf.F(groups__contains='veos'))
    npft.print_title('Playbook to configure virtual switch with template')
    results = veos.run(task=arista_configuration)
    npft.print_result(results)


if __name__ == '__main__':
    arista_config_template()
{%- for vlan in host['vlans'] %}
vlan {{ vlan.id }}
   name {{ vlan.name }}
{% endfor %}

{%- if host.name == 'veos1' %}
{%- for vlan in host['vlans'] %}
interface Vlan{{ vlan.id }}
   ip address {{ vlan.ip }}/24
{% endfor %}
ip routing
{% endif %}

{%- for access in host['accesses'] %}
interface Ethernet{{ access.interface }}
   switchport access vlan {{ access.vlan_id }}
{% endfor %}

{%- for trunk in host['trunks'] %}
interface Ethernet{{ trunk.interface }}
   channel-group {{ trunk.id }} mode active
{% endfor %}

interface Port-Channel{{ host['trunks'][0]['id'] }}
   switchport mode trunk
Architecture Arista vEOS-lab Nornir