wvandeun / nornir_netbox

NetBox plugin for Nornir
Apache License 2.0
69 stars 17 forks source link

hostname Attribute error when NetBoxInventory2 plugin in use #40

Closed davama closed 2 years ago

davama commented 2 years ago

Hello,

playing around with nornir and netbox.

I get this error:

Traceback (most recent call last):
  File "/root/dave-dev-environment/lib64/python3.9/site-packages/nornir/core/task.py", line 99, in start
    r = self.task(self, **self.params)
  File "/root/dave-dev-environment/dcom/nornir_lib.py", line 30, in getVlan_obj
    net_connect = task.host.get_connection(CONNECTION_NAME, task.nornir.config)
  File "/root/dave-dev-environment/lib64/python3.9/site-packages/nornir/core/inventory.py", line 493, in get_connection
    conn = self.get_connection_parameters(connection)
  File "/root/dave-dev-environment/lib64/python3.9/site-packages/nornir/core/inventory.py", line 427, in get_connection_parameters
    r = self._get_connection_options_recursively(connection)
  File "/root/dave-dev-environment/lib64/python3.9/site-packages/nornir/core/inventory.py", line 456, in _get_connection_options_recursively
    sp = g._get_connection_options_recursively(connection)
  File "/root/dave-dev-environment/lib64/python3.9/site-packages/nornir/core/inventory.py", line 467, in _get_connection_options_recursively
    p.hostname = p.hostname if p.hostname is not None else sp.hostname
AttributeError: 'dict' object has no attribute 'hostname'

I googled around and found this ticket which i thought was interesting: https://github.com/nornir-automation/nornir/issues/779 Specifically the last comment.

when i run what was suggested in that ticket, i get the hostname and associated primary_ip

print (nr.inventory.hosts[var].hostname)

for name, host_obj in nr.inventory.hosts.items():
            print(f"{name} -> {host_obj.hostname}")

# results in:

Xxx:xxx:1::36
rtr-36 -> xxx:xxx:1::36

Honestly, just starting out with nornir. So my debug skill are not so great.

What could be the cause for the errors?

any input is appreciated!

thank you, Dave

wvandeun commented 2 years ago

Can you provide a little more detail on when and how this issue is triggered? I'm not immediately able to reproduce what you describe.

Can you please share:

davama commented 2 years ago

@wvandeun ill get this to you this week!! Thank you for the support!

davama commented 2 years ago

the script:

from dcom.nornir_settings import *
import sys
import pprint
from nornir import InitNornir
from nornir_napalm.plugins.tasks import napalm_get
from nornir.core.task import Task, Result
from nornir_utils.plugins.functions import print_result
from nornir_netmiko.tasks import netmiko_send_command
from nornir_netmiko.connections import CONNECTION_NAME
from genie.libs.parser.iosxe.show_cdp import ShowCdpNeighborsDetail
from genie.libs.parser.iosxe.show_lldp import ShowLldpNeighborsDetail
from genie.libs.parser.iosxe.show_vlan import ShowVlan
from unittest.mock import Mock

def getLLDPnei_obj(task: Task) -> Result:
    if(task.host.platform == 'ios'):
        net_connect = task.host.get_connection(CONNECTION_NAME, task.nornir.config)
        #result = net_connect.send_command("show cdp neighbors detail")
        result = net_connect.send_command("show lldp neighbors detail")
        #parser = ShowCdpNeighborsDetail(Mock())
        parser = ShowLldpNeighborsDetail(Mock())
        result = parser.cli(result)

    return Result(
        host= task.host,
        result= result
    )

var = sys.argv[1]

nr = nr.filter(name=var)

print (nr.inventory.hosts[var].hostname)

# this returns the hostname > primary_ip
for name, host_obj in nr.inventory.hosts.items():
            print(f"{name} -> {host_obj.hostname}")

getNeighbors_obj = nr.run(name="get LLDP neighbors",task=getLLDPnei_obj)

print_result(getNeighbors_obj)

The nornir_settings.py:

from nornir import InitNornir
from dcom.requests_disable_ssl_warning import *
from dcom.load_dot_env import *
import os

nr = InitNornir(
    dry_run=True,
    runner={
        "plugin": "threaded",
        "options": {
            "num_workers": 100
        }
    },
    inventory={
        "plugin": "NetBoxInventory2",
        "options": {
            "nb_url": os.getenv("NB_URL"),
            "nb_token": os.getenv("NB_TOKEN"),
            "ssl_verify": False,
            "flatten_custom_fields": True,
            "use_platform_napalm_driver": True,
            "filter_parameters": {
                "region": 'usa',
                "site": 'usa-wkl'
            }
        }
    }
)
# Set the username and password using the environment variable
nr.inventory.defaults.username = os.getenv("DEVICE_USERNAME")
nr.inventory.defaults.password = os.getenv("DEVICE_PASSWORD")
nr.inventory.defaults.connection_options = {'netmiko': {'extras': { 'fast_cli': False, 'global_delay_factor': 2 }}}

relevant versions:

Python 3.9.6
nornir                       3.2.0
nornir-napalm                0.1.2
nornir-netbox                0.3.0
nornir-netmiko               0.1.2
nornir-utils                 0.1.2
netbox - v3.1.10

genie                        22.2
genie.libs.clean             22.2
genie.libs.conf              22.2
genie.libs.filetransferutils 22.2
genie.libs.health            22.2
genie.libs.ops               22.2
genie.libs.parser            22.2
genie.libs.sdk               22.2

@wvandeun hope that covers it.

Please let me know if I missed anything

Thank you, Dave

wvandeun commented 2 years ago

In nornir_settings.py on the last line, you are defining connection_options for netmiko as a dict. This is not correct. It should be defined as a ConnectionOptions object.

from nornir.core.inventory import ConnectionOptions
nr.inventory.defaults.connection_options["netmiko"] = ConnectionOptions(extras={ 'fast_cli': False, 'global_delay_factor': 2 })
davama commented 2 years ago

Yup! That was it!!

thank you very much

closing