Uninett / nav

Network Administration Visualized
GNU General Public License v3.0
194 stars 39 forks source link

[BUG] Some Netmap layer 3 views will generate an `AttributeError` e-mail and a "Error loading graph" error message to the user #3225

Closed lunkwill42 closed 3 days ago

lunkwill42 commented 1 week ago

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:

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

2024-11-20_10-36

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):

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:

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 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.