Skip to content

Instantly share code, notes, and snippets.

@danielmacuare
Last active April 19, 2019 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielmacuare/494a8973397e3bf547b65c7163a66ba4 to your computer and use it in GitHub Desktop.
Save danielmacuare/494a8973397e3bf547b65c7163a66ba4 to your computer and use it in GitHub Desktop.

Napalm get_facts to Nornir

The purpose of this gist is to gather facts from a network device with Napalm and Nornir alike.
This will help us understand how to use tasks in Nornir.

Considerations

  • We will be using Telnet to connect to our devices. By default, Napalm uses SSH to connect (See Napalm optional args) to the IOS devices. For this reason, we will need to pass optional_arguments when instantiating the Napalm driver object.
  • r2 can be replaced with the device ip. In my case, I was working with host files in my OS.

Napalm Script

The following script will connect to one device (r2) and will return its facts. To use telnet, notice we are passing the optional_args dictionary.

#!/usr/bin/python3.6
from napalm import get_network_driver
from pprint import pprint

driver = get_network_driver('ios')
conn_method = {'transport': 'telnet'}
host = 'r2'
user = 'danielmac'
passwd = 'ccnplab'

# With context manager
with driver(hostname=host, username=user, password=passwd, optional_args=conn_method) as device:
    print('Getting facts')
    pprint(device.get_facts())

Example Output

{ 'facts': { 'fqdn': 'r2.danielmacuare.com',
             'hostname': 'r2',
             'interface_list': [ 'Ethernet0/0',
                                 'Ethernet0/1',
                                 'Ethernet0/2',
                                 'Ethernet0/3',
                                 'Ethernet1/0',
                                 'Ethernet1/1',
                                 'Ethernet1/2',
                                 'Ethernet1/3',
                                 'Serial2/0',
                                 'Serial2/1',
                                 'Serial2/2',
                                 'Serial2/3',
                                 'Serial3/0',
                                 'Serial3/1',
                                 'Serial3/2',
                                 'Serial3/3'],
             'model': 'Unknown',
             'os_version': 'Linux Software (I86BI_LINUX-ADVENTERPRISEK9-M), '
                           'Version 15.2(2.15)T, ENGINEERING WEEKLY BUILD, '
                           'synced to V151_4_M3_5',
             'serial_number': '2048004',
             'uptime': 16680,
             'vendor': 'Cisco'}}

Nornir

Now, to achieve the same with Nornir we will use the open_connection task. This task allows you to pass optional parameters to Napalm. In our case, we will need to tell Napalm to use telnet as the transport method to connect to the devices.

To do this, we can define a connection_options dictionary to be used by our host or a group. In my case, since I'm using the Ansible-type inventory, I will define this in the `group_vars/all.yaml' file

You can see HERE an example on how to do this if you are using Nornir's SimpleInventory inventory instead.

cat ansible/group_vars/all.yaml

---
platform: ios
username: danielmac
password: ccnplab
port: 23

connection_options:
  napalm:
    extras:
      optional_args: {'transport': 'telnet'}

cat nornir_get_facts.py

#!/usr/bin/python3.6
from nornir import InitNornir
from nornir.plugins.tasks.networking import napalm_get
from nornir.plugins.functions.text import print_result
import ipdb

def get_facts_manually(task):
    ipdb.set_trace(context=5)
    task.host.open_connection("napalm", configuration=task.nornir.config)
    r = task.run(napalm_get, getters=['facts'])
    task.host.close_connection("napalm")

if __name__ == "__main__":
    norn = InitNornir(config_file='config.yaml')

# Working with R2 only.    
    r2 = norn.filter(hostname='r2')
    facts = r2.run(task=get_facts_manually)
    print_result(facts)

ipdb is really useful here to inspect the elements that the open_connection will receive. In this case you can make sure you are passing the well know attributes username, password, port.

> /nr_config_gen.py(66)get_facts_manually()
     64 def get_facts_manually(task):
     65     ipdb.set_trace(context=5)
---> 66     task.host.open_connection("napalm",
     67                               configuration=task.nornir.config,
     68                               )

ipdb> task.host.username                                                                                  
'danielmac'
ipdb> task.host.password                                                                                  
'ccnplab'
ipdb> task.host.port                                                                                      
23
ipdb>  
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment