netbox-community / netbox

The premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/free-netbox-cloud/
http://netboxlabs.com/oss/netbox/
Apache License 2.0
15.98k stars 2.56k forks source link

Cable trace issue after upgrade from 2.x to 3.x - 'NoneType' object has no attribute 'get_absolute_url' #7739

Closed Epaphus closed 2 years ago

Epaphus commented 2 years ago

NetBox version

v3.0.9

Python version

3.8

Steps to Reproduce

  1. Create a circuit
  2. Attach circuit A end to rear port of patch panel
  3. Attach the front port of the patch panel to an interface on a device
  4. Run a cable trace

image

image

image

Expected Behavior

Trace to complete showing the correct path

Switch interface -> Patch Panel -> Circuit

Observed Behavior

Trace fails and downloading SVG has a "'NoneType' object has no attribute 'get_absolute_url'" error.

image

Internal Server Error: /api/dcim/interfaces/886/trace/

AttributeError at /api/dcim/interfaces/886/trace/ 'NoneType' object has no attribute 'get_absolute_url'

Request Method: GET
Request URL: http://netbox-dev.domain.com/api/dcim/interfaces/886/trace/?render=svg
Django Version: 3.2.9
Python Executable: /opt/netbox-3.0.9/venv/bin/python3
Python Version: 3.8.11
Python Path: ['/opt/netbox/netbox', '/opt/netbox-3.0.9', '/opt/netbox-3.0.9/venv/bin', '/opt/rh/rh-python38/root/usr/lib64/python38.zip', '/opt/rh/rh-python38/root/usr/lib64/python3.8', '/opt/rh/rh-python38/root/usr/lib64/python3.8/lib-dynload', '/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages', '/opt/netbox-3.0.9/venv/lib/python3.8/site-packages']
Server time: Thu, 04 Nov 2021 10:23:22 +0000 Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'corsheaders',
 'debug_toolbar',
 'graphiql_debug_toolbar',
 'django_filters',
 'django_tables2',
 'django_prometheus',
 'graphene_django',
 'mptt',
 'rest_framework',
 'taggit',
 'timezone_field',
 'circuits',
 'dcim',
 'ipam',
 'extras',
 'tenancy',
 'users',
 'utilities',
 'virtualization',
 'django_rq',
 'drf_yasg',
 'nextbox_ui_plugin.NextBoxUIConfig']
Installed Middleware:
['graphiql_debug_toolbar.middleware.DebugToolbarMiddleware',
 'django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'netbox.middleware.ExceptionHandlingMiddleware',
 'netbox.middleware.RemoteUserMiddleware',
 'netbox.middleware.LoginRequiredMiddleware',
 'netbox.middleware.APIVersionMiddleware',
 'netbox.middleware.ObjectChangeMiddleware',
 'django_prometheus.middleware.PrometheusAfterMiddleware']

Traceback (most recent call last):
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
  File "/opt/netbox/netbox/netbox/api/views.py", line 201, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/opt/netbox-3.0.9/venv/lib64/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/opt/netbox/netbox/dcim/api/views.py", line 59, in trace
    drawing = obj.get_trace_svg(
  File "/opt/netbox/netbox/dcim/models/device_components.py", line 201, in get_trace_svg
    return trace.render()
  File "/opt/netbox/netbox/dcim/svg.py", line 448, in render
    url=near_end.get_absolute_url(),

Exception Type: AttributeError at /api/dcim/interfaces/886/trace/ Exception Value: 'NoneType' object has no attribute 'get_absolute_url'
Request information:
USER: username

GET:
render = 'svg'

POST: No POST data

FILES: No FILES data

COOKIES:
csrftoken = 'o8y9T3Z2WTR85aOtaaaaaaa5BWxZsqQc1biK5j1ffbbbbbbbbbN7ZPkzje10Wvk5'
sessionid = '5l77wp6b56jtckf6p6ipdo7zxu4s8nfc'
lt-anonymous-id = '0.f60b7cc6175458ffd93'
lt-session-data = '{"id":"0.350d8c917ce510be21","lastUpdatedDate":"2021-11-03T09:10:52.194Z"}'
lt-pageview-id = '0.04ee50b417ce510be25'

META:
CSRF_COOKIE = 'o8y9T3Z2WTR85aOtaaaaaaa5BWxZsqQc1biK5j1ffbbbbbbbbbN7ZPkzje10Wvk5'
HTTP_ACCEPT = '*/*'
HTTP_ACCEPT_ENCODING = 'gzip, deflate, br'
HTTP_ACCEPT_LANGUAGE = 'en-GB,en;q=0.5'
HTTP_CONNECTION = 'Keep-Alive'
HTTP_COOKIE = 'csrftoken=o8y9T3Z2WTR85aOtaaaaaaa5BWxZsqQc1biK5j1ffbbbbbbbbbN7ZPkzje10Wvk5; sessionid=5l77wp6b56jtckf6p6ipdo7zxu4s8nfc; lt-anonymous-id="0.f60b7cc6175458ffd93"; lt-session-data={"id":"0.350d8c917ce510be21","lastUpdatedDate":"2021-11-03T09:10:52.194Z"}; lt-pageview-id="0.04ee50b417ce510be25"'
HTTP_HOST = 'netbox-dev.domain.com'
HTTP_REFERER = 'https://netbox-dev.domain.com/dcim/interfaces/886/trace/'
HTTP_SEC_FETCH_DEST = 'object'
HTTP_SEC_FETCH_MODE = 'navigate'
HTTP_SEC_FETCH_SITE = 'same-origin'
HTTP_USER_AGENT = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0'
HTTP_X_FORWARDED_FOR = '10.60.60.60'
HTTP_X_FORWARDED_HOST = 'netbox-dev.domain.com'
HTTP_X_FORWARDED_PROTO = '(null)'
HTTP_X_FORWARDED_SERVER = 'netbox-dev.domain.com'
PATH_INFO = '/api/dcim/interfaces/886/trace/'
QUERY_STRING = 'render=svg'
RAW_URI = '/api/dcim/interfaces/886/trace/?render=svg'
REMOTE_ADDR = '127.0.0.1'
REMOTE_PORT = '33280'
REQUEST_METHOD = 'GET'
SCRIPT_NAME = ''
SERVER_NAME = '127.0.0.1'
SERVER_PORT = '8001'
SERVER_PROTOCOL = 'HTTP/1.1'
SERVER_SOFTWARE = 'gunicorn/20.1.0'
gunicorn.socket = <socket.socket fd=10, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8001), raddr=('127.0.0.1', 33280)> wsgi.errors = <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7f10e0110790> wsgi.file_wrapper = <class 'gunicorn.http.wsgi.FileWrapper'> wsgi.input = <gunicorn.http.body.Body object at 0x7f10dc0c4160> wsgi.input_terminated = True wsgi.multiprocess = True wsgi.multithread = True wsgi.run_once = False wsgi.url_scheme = 'http'
wsgi.version = '(1, 0)'
jeremystretch commented 2 years ago

Attach circuit A end to rear port of patch panel

Thank you for opening a bug report. Unfortunately, the information you have provided is not sufficient for someone else to attempt to reproduce the reported behavior. Remember, each bug report must include detailed steps that someone else can follow on a clean, empty NetBox installation to reproduce the exact problem you're experiencing. These instructions should include the creation of any involved objects, any configuration changes, and complete accounting of the actions being taken. Also be sure that your report does not reference data on the public NetBox demo, as that is subject to change at any time by an outside party and cannot be relied upon for bug reports.

Epaphus commented 2 years ago

For a blank Netbox install.

  1. Create a site
  2. Create a manufacture for a switch
  3. Create a manufacture for a patch panel
  4. Create a device type for a switch
  5. Add interfaces to the switch device type
  6. Create a device type for a patch panel
  7. Add rear ports to the patch panel device type
  8. Add front ports to the patch panel device type which are mapped 1 to 1 to the rear ports.
  9. Create a switch under devices using the device type from step 4 and site from step 1 10 Add interface ports to the switch created in step 9
  10. Create a patch panel under devices using the device type from step 6 and site from step 1
  11. Create a provider under circuits
  12. Create a circuit type
  13. Create a circuit using the provider from step 12 and type from step 13
  14. Add a circuit termination for the A side of the circuit in step 14 using the site from step 1
  15. Create a cable from A side termination of the circuit created in step 14 to rear port 1 of patch panel created in step 11
  16. Create a cable from front port 1 of patch panel created in step 11 to an interface on the switch created in step 9
  17. Run a trace from either the A side termination of the circuit or from the interface on the switch.

The end result should be an interface on a switch connected to a circuit via a patch panel.

bistraque commented 2 years ago

I got the same issue while preparing the upgrade of our server from 2.11.12 to 3.0.9. In my case, the error occurs on circuits for which there is no 'Termination Z' endpoint. The trace shows fine in 2.11.12 but fails in 3.0.9. Enabling debug hints at it because the local var traced_path contains an extra segment:

[(<Interface: Gi3/0/2 (2)>, <Cable: #1969>, <FrontPort: 3>),
 (<RearPort: 3>, <Cable: #4316>, <CircuitTermination: Termination A: XXXXXX>),
 (None, None, None)]

Nothing makes either termination mandatory, hence cable trace should cope with it nicely.

Edit: I was able to reproduce this bug on demo.netbox.dev. The steps: