Integrity Error thrown when dealing with Front/Rear Console Ports on patch panels #2475

Closed
opened 2025-12-29 18:19:11 +01:00 by adam · 6 comments
Owner

Originally created by @Xelinor on GitHub (Mar 19, 2019).

Environment

  • Python version: 3.6.8
  • NetBox version: 2.5.9 (Also reproduced in 2.5.5 & 2.5.8)

Steps to Reproduce

  1. Built a patch panel with 8 front ports mapped to 1 rear port
  2. Built a console server with 1 console server port which is connected to the rear port of the patch panel
  3. Built 2 devices, which have console ports leading to the first 2 ports on the patch panel
  4. First device connects fine, no problems
  5. SECOND device fails to connect the console port, throwing an integrity error

Expected Behavior

Expected it to let me create the cable and to show it connected in an octopus-like cable pattern to the console server

Observed Behavior

Cable is still created, but when viewed from device 2 it shows the green 'Connected' but still displays as 'Not Connected'
example

Originally created by @Xelinor on GitHub (Mar 19, 2019). ### Environment * Python version: 3.6.8 * NetBox version: 2.5.9 (Also reproduced in 2.5.5 & 2.5.8) <!-- Describe in detail the exact steps that someone else can take to reproduce this bug using the current stable release of NetBox (or the current beta release where applicable). Begin with the creation of any necessary database objects and call out every operation being performed explicitly. If reporting a bug in the REST API, be sure to reconstruct the raw HTTP request(s) being made: Don't rely on a wrapper like pynetbox. --> ### Steps to Reproduce 1. Built a patch panel with 8 front ports mapped to 1 rear port 2. Built a console server with 1 console server port which is connected to the rear port of the patch panel 3. Built 2 devices, which have console ports leading to the first 2 ports on the patch panel 4. First device connects fine, no problems 5. SECOND device fails to connect the console port, throwing an integrity error <!-- What did you expect to happen? --> ### Expected Behavior Expected it to let me create the cable and to show it connected in an octopus-like cable pattern to the console server <!-- What happened instead? --> ### Observed Behavior Cable is still created, but when viewed from device 2 it shows the green 'Connected' but still displays as 'Not Connected' ![example](https://user-images.githubusercontent.com/16243975/54635555-aac6dd80-4a41-11e9-8c8e-a7fe0a0528e1.png)
adam added the type: bugstatus: accepted labels 2025-12-29 18:19:11 +01:00
adam closed this issue 2025-12-29 18:19:11 +01:00
Author
Owner

@nickzxcv commented on GitHub (Mar 25, 2019):

I've only used octopus cables with Cisco console servers, but in IOS an octopus cable appears as 8 separate interfaces/console ports anyway. For a 16 port line card, the interface numbers went 1-16 so the octopus cable wasn't significant in this way. I've just treated my octopus cables, as 8 individual cables although I think I created them before "cables" were a thing in netbox anyway.

@nickzxcv commented on GitHub (Mar 25, 2019): I've only used octopus cables with Cisco console servers, but in IOS an octopus cable appears as 8 separate interfaces/console ports anyway. For a 16 port line card, the interface numbers went 1-16 so the octopus cable wasn't significant in this way. I've just treated my octopus cables, as 8 individual cables although I think I created them before "cables" were a thing in netbox anyway.
Author
Owner

@Xelinor commented on GitHub (Apr 3, 2019):

The stated point of netbox is to model the physical world though. In the real world, I take a (for example) Cisco 2911 ISR and stick 5 WICs into it. Each WIC gives me 2 physical ports. I then run a cable over to the back of my patch panel (in this example, a GLD Group 32 Port Async Octal Panel). That plugs into 2 ports on the back of that device, providing me with 16 ports (8 per port, 4 rear ports). That takes up space on my racks, and I need to be able to track those cables. Yes, it does show up as 16 ports on the 2911, but that doesn't help me model the real world, especially when that patch panel is sitting a rack over from the 2911. The example I'm attempting to model is only octopus-like, it's not the same.

Also, I just tested and this bug is still present in 2.5.9

@Xelinor commented on GitHub (Apr 3, 2019): The stated point of netbox is to model the physical world though. In the real world, I take a (for example) Cisco 2911 ISR and stick 5 WICs into it. Each WIC gives me 2 physical ports. I then run a cable over to the back of my patch panel (in this example, a GLD Group 32 Port Async Octal Panel). That plugs into 2 ports on the back of that device, providing me with 16 ports (8 per port, 4 rear ports). That takes up space on my racks, and I need to be able to track those cables. Yes, it does show up as 16 ports on the 2911, but that doesn't help me model the real world, especially when that patch panel is sitting a rack over from the 2911. The example I'm attempting to model is only octopus-like, it's not the same. Also, I just tested and this bug is still present in 2.5.9
Author
Owner

@jeremystretch commented on GitHub (May 1, 2019):

NetBox does not support modeling breakout cables. When multiple front ports are mapped to a single rear port, the rear port must have a peer that breaks them back out into individual front ports. In your case, you'll need to model the console server ports as individual ports (which they are, just sharing a common cable).

However, NetBox should be returning a validation error instead of raising an exception. I'm marking this as a bug because the exception needs to be caught.

@jeremystretch commented on GitHub (May 1, 2019): NetBox does not support modeling breakout cables. When multiple front ports are mapped to a single rear port, the rear port must have a peer that breaks them back out into individual front ports. In your case, you'll need to model the console server ports as individual ports (which they are, just sharing a common cable). However, NetBox should be returning a validation error instead of raising an exception. I'm marking this as a bug because the exception needs to be caught.
Author
Owner

@jeremystretch commented on GitHub (May 1, 2019):

Posting a traceback for future reference:

Traceback:

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute
  85.                 return self.cursor.execute(sql, params)

The above exception (duplicate key value violates unique constraint "dcim_consoleport_cs_port_id_key"
DETAIL:  Key (connected_endpoint_id)=(55088) already exists.
) was the direct cause of the following exception:

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/contrib/auth/mixins.py" in dispatch
  85.         return super().dispatch(request, *args, **kwargs)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/home/jstretch/netbox/netbox/utilities/views.py" in post
  238.             obj = form.save()

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/forms/models.py" in save
  458.             self.instance.save()

File "/home/jstretch/netbox/netbox/dcim/models.py" in save
  2652.         super().save(*args, **kwargs)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save
  718.                        force_update=force_update, update_fields=update_fields)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save_base
  758.                 update_fields=update_fields, raw=raw, using=using,

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/dispatch/dispatcher.py" in send
  175.             for receiver in self._live_receivers(sender)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/dispatch/dispatcher.py" in <listcomp>
  175.             for receiver in self._live_receivers(sender)

File "/home/jstretch/netbox/netbox/dcim/signals.py" in update_connected_endpoints
  43.         endpoint_a.save()

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save
  718.                        force_update=force_update, update_fields=update_fields)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save_base
  748.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in _save_table
  812.                                       forced_update)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in _do_update
  861.         return filtered._update(values) > 0

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/query.py" in _update
  712.         return query.get_compiler(self.db).execute_sql(CURSOR)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql
  1383.         cursor = super().execute_sql(result_type)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql
  1065.             cursor.execute(sql, params)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/debug_toolbar/panels/sql/tracking.py" in execute
  186.         return self._record(self.cursor.execute, sql, params)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/debug_toolbar/panels/sql/tracking.py" in _record
  124.             return method(sql, params)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
  100.             return super().execute(sql, params)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
  68.         return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute_with_wrappers
  77.         return executor(sql, params, many, context)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute
  85.                 return self.cursor.execute(sql, params)

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/utils.py" in __exit__
  89.                 raise dj_exc_value.with_traceback(traceback) from exc_value

File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute
  85.                 return self.cursor.execute(sql, params)

Exception Type: IntegrityError at /dcim/console-ports/8654/connect/
Exception Value: duplicate key value violates unique constraint "dcim_consoleport_cs_port_id_key"
DETAIL:  Key (connected_endpoint_id)=(55088) already exists.
@jeremystretch commented on GitHub (May 1, 2019): Posting a traceback for future reference: ``` Traceback: File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute 85. return self.cursor.execute(sql, params) The above exception (duplicate key value violates unique constraint "dcim_consoleport_cs_port_id_key" DETAIL: Key (connected_endpoint_id)=(55088) already exists. ) was the direct cause of the following exception: File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner 34. response = get_response(request) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response 126. response = self.process_exception_by_middleware(e, request) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response 124. response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/views/generic/base.py" in view 68. return self.dispatch(request, *args, **kwargs) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/contrib/auth/mixins.py" in dispatch 85. return super().dispatch(request, *args, **kwargs) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/views/generic/base.py" in dispatch 88. return handler(request, *args, **kwargs) File "/home/jstretch/netbox/netbox/utilities/views.py" in post 238. obj = form.save() File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/forms/models.py" in save 458. self.instance.save() File "/home/jstretch/netbox/netbox/dcim/models.py" in save 2652. super().save(*args, **kwargs) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save 718. force_update=force_update, update_fields=update_fields) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save_base 758. update_fields=update_fields, raw=raw, using=using, File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/dispatch/dispatcher.py" in send 175. for receiver in self._live_receivers(sender) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/dispatch/dispatcher.py" in <listcomp> 175. for receiver in self._live_receivers(sender) File "/home/jstretch/netbox/netbox/dcim/signals.py" in update_connected_endpoints 43. endpoint_a.save() File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save 718. force_update=force_update, update_fields=update_fields) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in save_base 748. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in _save_table 812. forced_update) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/base.py" in _do_update 861. return filtered._update(values) > 0 File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/query.py" in _update 712. return query.get_compiler(self.db).execute_sql(CURSOR) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql 1383. cursor = super().execute_sql(result_type) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql 1065. cursor.execute(sql, params) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/debug_toolbar/panels/sql/tracking.py" in execute 186. return self._record(self.cursor.execute, sql, params) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/debug_toolbar/panels/sql/tracking.py" in _record 124. return method(sql, params) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in execute 100. return super().execute(sql, params) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in execute 68. return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute_with_wrappers 77. return executor(sql, params, many, context) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute 85. return self.cursor.execute(sql, params) File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/utils.py" in __exit__ 89. raise dj_exc_value.with_traceback(traceback) from exc_value File "/home/jstretch/.virtualenvs/netbox/lib/python3.5/site-packages/django/db/backends/utils.py" in _execute 85. return self.cursor.execute(sql, params) Exception Type: IntegrityError at /dcim/console-ports/8654/connect/ Exception Value: duplicate key value violates unique constraint "dcim_consoleport_cs_port_id_key" DETAIL: Key (connected_endpoint_id)=(55088) already exists. ```
Author
Owner

@Xelinor commented on GitHub (May 1, 2019):

NetBox does not support modeling breakout cables.

Oh sure, I totally understand that. The report was just on the bug, and the fact that it still created the cable in spite of the exception.

That said, might be worth considering adding that as a feature in the future, since the breakout is actually happening on a totally different box in a totally different rack. The only way to model this successfully and have it NOT throw errors is to basically make up a bunch of ports that don't exist and consequently a bunch of cables running from those ports to the patch panel...which is a great deal away from modeling the real world in this scenario.

@Xelinor commented on GitHub (May 1, 2019): > NetBox does not support modeling breakout cables. Oh sure, I totally understand that. The report was just on the bug, and the fact that it still created the cable in spite of the exception. That said, might be worth considering adding that as a feature in the future, since the breakout is actually happening on a totally different box in a totally different rack. The only way to model this successfully and have it NOT throw errors is to basically make up a bunch of ports that don't exist and consequently a bunch of cables running from those ports to the patch panel...which is a great deal away from modeling the real world in this scenario.
Author
Owner

@candlerb commented on GitHub (Jul 19, 2019):

The only way to model this successfully and have it NOT throw errors is to basically make up a bunch of ports that don't exist and consequently a bunch of cables running from those ports to the patch panel...

That's what you have to do.

It's a limitation of Netbox's data model that there is a forced 1:1 relationship between "physical port" and "logical interface / console server connection", because they are modelled as the same data entity.

Therefore, if you have a physical connector carrying 8 console connections, you need to create 8 "console server ports", which are connected to the relevant destinations. Imagine 8 separate cables, where at one end you've tied them all together with an elastic band. This bundling of 8 interfaces to 1 physical connector is something that Netbox cannot model today.

This problem occurs the other way round too, where one logical interface presents as multiple physical ports. For example, I have some switches where some of the interfaces have two physical ports, RJ45 and SFP; you can connect to either one. On the front they might be labelled say "48T" and "48F". But in the system configuration, there is only a single logical interface, "1/0/48".

@candlerb commented on GitHub (Jul 19, 2019): > The only way to model this successfully and have it NOT throw errors is to basically make up a bunch of ports that don't exist and consequently a bunch of cables running from those ports to the patch panel... That's what you have to do. It's a limitation of Netbox's data model that there is a forced 1:1 relationship between "physical port" and "logical interface / console server connection", because they are modelled as the same data entity. Therefore, if you have a physical connector carrying 8 console connections, you need to create 8 "console server ports", which are connected to the relevant destinations. Imagine 8 separate cables, where at one end you've tied them all together with an elastic band. This bundling of 8 interfaces to 1 physical connector is something that Netbox cannot model today. This problem occurs the other way round too, where one logical interface presents as multiple physical ports. For example, I have some switches where some of the interfaces have two physical ports, RJ45 and SFP; you can connect to either one. On the front they might be labelled say "48T" and "48F". But in the system configuration, there is only a single logical interface, "1/0/48".
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#2475