Open ignatievia opened 2 years ago
What does the following show?
for host_obj in nr.inventory.hosts:
print(host_obj.hostname)
Are there any devices that do not have a hostname?
for host_obj in nr.inventory.hosts:
... print(host_obj.hostname)
...
Traceback (most recent call last):
File "<input>", line 2, in <module>
AttributeError: 'str' object has no attribute 'hostname'
while
print (nr.inventory.hosts)
{'eve_cisco_ios': Host: eve_cisco_ios}
print (nr.inventory.hosts["eve_cisco_ios"].hostname)
10.0.10.71
In this particular case there's only 1 device in inventory
May the root of the problem be in object type?
for host_obj in nr.inventory.hosts:
... print(type(host_obj))
...
<class 'str'>
type (nr.inventory.hosts["eve_cisco_ios"])
<class 'nornir.core.inventory.Host'>
My error above...so what do you get with this:
for name, host_obj in nr.inventory.hosts.items():
print(f"{name} -> {host_obj.hostname}")
You might need to look at the Python debugger and see what things are at this line 467:
File "/Users/ivan/project_name/venv/lib/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
i.e. print out both p
and `sp.
for name, host_obj in nr.inventory.hosts.items():
... print(f"{name} -> {host_obj.hostname}")
...
eve_cisco_ios -> 10.0.10.71
Below is pycharm screenshot with p
and sp
variables at the line 467 (sorry, have not found more convenient way to show it)
https://drive.google.com/file/d/1dZV-sxS9xh0pP_4whwfR4uD9htmwmQLl/view?usp=sharing
sp
shouldn't be a dict. sp
should be a ConnectionOptions
object. Whoever is populating defaults.connection_options
is doing it wrong.
Fore reference, here is the type definition:
https://github.com/nornir-automation/nornir/blob/develop/nornir/core/inventory.py#L216
and where sp is coming from:
https://github.com/nornir-automation/nornir/blob/develop/nornir/core/inventory.py#L465
However, according to your traceback and debug information sp
is a dict.
This is most likely a plugin issue so I'd suggest checking with them.
@dbarrosop I may have identified the issue, but need more details to properly identify how this is triggered and to be able to confirm it.
The problem is here https://github.com/wvandeun/nornir_netbox/blob/860d2f80e3fd2b2989c33044c560decdd2685cf1/nornir_netbox/plugins/inventory/netbox.py#L47
We try to retrieve the connection_options
from the dictionary data
, but that key does not exist. The connection options are instead defined in data["data"]
instead. The same issue exists on line 66.
These functions were directly copied from Nornir's Simple inventory plugin, so the same issue should also exist in that plugin:
https://github.com/nornir-automation/nornir/blob/33076fa2209ba69e188c0ab1c034bdeb7a8bf112/nornir/plugins/inventory/simple.py#L44
The nornir_ansible
inventory plugin seems to have the exact same approach as well btw:
https://github.com/carlmontanari/nornir_ansible/blob/d00fa4788bbca5b24a18b9c15ccc6361bd890bd0/nornir_ansible/plugins/inventory/ansible.py#L471 (probably also copied from simple inventory)
If I modify the line to:
connection_options=_get_connection_options(data.get("data", {}).get("connection_options", {})),
then it seems to work properly
>>> nr.inventory.defaults.connection_options
{'netmiko': <nornir.core.inventory.ConnectionOptions object at 0x107e4aa90>}
>>> nr.inventory.defaults.connection_options.get("netmiko").hostname
"10.10.10.10"
connection_options=_get_connection_options(data.get("data", {}).get("connection_options", {})),
This doesn't look correct though. This would mean that your defaults_dict looks like:
data:
connection_options:
...
And it shouldn't as connection_options is an attribute of Defaults
, it doesn't belong inside data
. Look at the test file for reference. So I suspect that the issue is simply that the defaults.yaml
you are using is wrong.
If I am wrong, I'd suggest you create a branch with a unit test that triggers the issue and I will try to help out but I am confident this is not a nornir issue as we are actively testing this scenario.
Appreciate your help @ktbyers @dbarrosop
The problem was in connection_options
population and was fixed this way
nr.inventory.defaults.connection_options["netmiko"] = ConnectionOptions(extras={'device_type': device_type})
Looks like it's a documentation problem cause I've found similar issue by @dmfigol https://github.com/nornir-automation/nornir/issues/369
Similar issue was described here - https://github.com/nornir-automation/nornir/issues/279 In my case primary_ip is defined in Netbox and populates 'hostname' attribute
nr.run(netmiko_send_config, config_commands=commands)
gets back error