While selecting a saved Netmap view from the dropdown list and then switching the view options from a layer 2 to a layer 3 view, the underlying XHR request will fail with a 500 error. An e-mail with a full traceback is sent to the site admin, while the end user will receive a java script alert dialog with this text:
Error loading graph, please try to reload the page
The e-mail sent to the site admin will reference this errors:
AttributeError at /netmap/graph/layer3/14/
'Netbox' object has no attribute '_Netbox__key'
To Reproduce
This isn't easy to reproduce without very specific data from a production NAV install.
Expected behavior
The map should load without error in the UI and without causing a 500-error e-mail being sent to the site admin.
Screenshots
Tracebacks
Traceback (most recent call last):
File "/opt/venvs/nav/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/opt/venvs/nav/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/opt/venvs/nav/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/opt/venvs/nav/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/opt/venvs/nav/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/opt/venvs/nav/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/opt/venvs/nav/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/opt/venvs/nav/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/web/netmap/api.py", line 194, in get
return Response(get_topology_graph(layer, load_traffic, view))
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/web/netmap/graph.py", line 53, in get_topology_graph
return _json_layer3(load_traffic, view=view)
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/web/netmap/cache.py", line 75, in get_traffic
result = func(*args, **kwargs)
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/web/netmap/graph.py", line 97, in _json_layer3
graph = build_netmap_layer3_graph(topology_without_metadata, load_traffic, view)
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/netmap/topology.py", line 194, in build_netmap_layer3_graph
graph = _attach_node_positions(graph, view.node_positions.all())
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/netmap/topology.py", line 211, in _attach_node_positions
node_meta_dict = [x for x in node_set if x.netbox == node]
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/netmap/topology.py", line 211, in <listcomp>
node_meta_dict = [x for x in node_set if x.netbox == node]
File "/opt/venvs/nav/lib/python3.9/site-packages/nav/netmap/stubs/__init__.py", line 42, in __eq__
return self.__key() == i.__key()
Exception Type: AttributeError at /netmap/graph/layer3/14/
Exception Value: 'Netbox' object has no attribute '_Netbox__key'
Environment (please complete the following information):
NAV version installed: 5.11.0
The error message was first observed at least three years back, but the problem has likely been in NAV since Netmap was first written.
Additional context
The issue is located in this __eq__ implementation in a Netbox "stub" class:
When Netmap builds a layer 3 topology graph, it will in some cases insert "stub" netboxes into the graph. These are objects that I believe usually represent a peering device that doesn't exist in NAV itself, a sort of pseudo-node to represent something outside the site's own network.
However, this stub class presents with the above faulty implementation of the __eq__ method. Working with a Graph object, sometimes, the nodes need to be compared for equality. However, this implementation only ever expects to be compared to another stub Netbox instance, not, for example, to nav.models.manage.Netbox objects - yet, it will of course be compared with these, since these are everywhere in the Graph. In reality, the stub class should just be comparing its own sysname attribute to that of the other object.
Describe the bug
While selecting a saved Netmap view from the dropdown list and then switching the view options from a layer 2 to a layer 3 view, the underlying XHR request will fail with a 500 error. An e-mail with a full traceback is sent to the site admin, while the end user will receive a java script alert dialog with this text:
The e-mail sent to the site admin will reference this errors:
To Reproduce
This isn't easy to reproduce without very specific data from a production NAV install.
Expected behavior
The map should load without error in the UI and without causing a 500-error e-mail being sent to the site admin.
Screenshots
Tracebacks
Environment (please complete the following information):
The error message was first observed at least three years back, but the problem has likely been in NAV since Netmap was first written.
Additional context
The issue is located in this
__eq__
implementation in aNetbox
"stub" class:https://github.com/Uninett/nav/blob/e6634e512c8ecf283c85a701366620e724806ab7/python/nav/netmap/stubs/__init__.py#L41-L42
When Netmap builds a layer 3 topology graph, it will in some cases insert "stub" netboxes into the graph. These are objects that I believe usually represent a peering device that doesn't exist in NAV itself, a sort of pseudo-node to represent something outside the site's own network.
However, this stub class presents with the above faulty implementation of the
__eq__
method. Working with aGraph
object, sometimes, the nodes need to be compared for equality. However, this implementation only ever expects to be compared to another stub Netbox instance, not, for example, tonav.models.manage.Netbox
objects - yet, it will of course be compared with these, since these are everywhere in theGraph
. In reality, the stub class should just be comparing its ownsysname
attribute to that of the other object.