Inconsistent enforcement of duplicate IP addresses #4523

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

Originally created by @candlerb on GitHub (Feb 2, 2021).

Originally assigned to: @candlerb on GitHub.

Environment

  • Python version: 3.6.9
  • NetBox version: 2.10.4

Steps to Reproduce

This is with ENFORCE_GLOBAL_UNIQUE = True in configuration.py

  1. Add two interfaces to a device, say "test1" and "test2" (these can be virtual)
  2. Add IP address 1.2.3.4/24 to "test1" with no role
  3. Add IP address 1.2.3.4/24 to "test2" with role VIP
  4. Change the test1 1.2.3.4/24 IP address to role VIP
  5. Change the test1 1.2.3.4/24 IP address back to no role

Expected Behavior

I expected duplicate IP address enforcement to be consistent: either require both addresses to be VIP, or allow one normal and one VIP to share the same IP address. (Probably the former).

In other words: either step 3 should have failed with a duplicate address error, or step 5 should have been accepted since it puts things back to how they were at step 3.

Observed Behavior

Step 3 is accepted, but step 5 fails with:
image

Originally created by @candlerb on GitHub (Feb 2, 2021). Originally assigned to: @candlerb on GitHub. ### Environment * Python version: 3.6.9 * NetBox version: 2.10.4 ### Steps to Reproduce This is with `ENFORCE_GLOBAL_UNIQUE = True` in `configuration.py` 1. Add two interfaces to a device, say "test1" and "test2" (these can be virtual) 2. Add IP address 1.2.3.4/24 to "test1" with no role 3. Add IP address 1.2.3.4/24 to "test2" with role VIP 4. Change the test1 1.2.3.4/24 IP address to role VIP 5. Change the test1 1.2.3.4/24 IP address back to no role ### Expected Behavior I expected duplicate IP address enforcement to be consistent: either require both addresses to be VIP, or allow one normal and one VIP to share the same IP address. (Probably the former). In other words: either step 3 should have failed with a duplicate address error, or step 5 should have been accepted since it puts things back to how they were at step 3. ### Observed Behavior Step 3 is accepted, but step 5 fails with: ![image](https://user-images.githubusercontent.com/44789/106595854-150c9c80-654c-11eb-91cb-01eb5037df24.png)
adam added the type: bugstatus: accepted labels 2025-12-29 18:36:57 +01:00
adam closed this issue 2025-12-29 18:36:57 +01:00
Author
Owner

@candlerb commented on GitHub (Feb 2, 2021):

It looks like a couple of extra tests are required around here e.g.

    @override_settings(ENFORCE_GLOBAL_UNIQUE=True)
    def test_duplicate_nonunique_nonrole_role(self):
        IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24'))
        duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP)
        self.assertRaises(ValidationError, duplicate_ip.clean)

    @override_settings(ENFORCE_GLOBAL_UNIQUE=True)
    def test_duplicate_nonunique_role_nonrole(self):
        IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP)
        duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24'))
        self.assertRaises(ValidationError, duplicate_ip.clean)

That assumes you want to disallow the duplicates between role and non-role. To allow them, self.assertIsNone(duplicate_ip.clean())

@candlerb commented on GitHub (Feb 2, 2021): It looks like a couple of extra tests are required around [here](https://github.com/netbox-community/netbox/blob/develop/netbox/ipam/tests/test_models.py#L262) e.g. ``` @override_settings(ENFORCE_GLOBAL_UNIQUE=True) def test_duplicate_nonunique_nonrole_role(self): IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24')) duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) self.assertRaises(ValidationError, duplicate_ip.clean) @override_settings(ENFORCE_GLOBAL_UNIQUE=True) def test_duplicate_nonunique_role_nonrole(self): IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')) self.assertRaises(ValidationError, duplicate_ip.clean) ``` That assumes you want to disallow the duplicates between role and non-role. To allow them, `self.assertIsNone(duplicate_ip.clean())`
Author
Owner

@jeremystretch commented on GitHub (Feb 4, 2021):

@candlerb want to take this one?

@jeremystretch commented on GitHub (Feb 4, 2021): @candlerb want to take this one?
Author
Owner

@candlerb commented on GitHub (Feb 4, 2021):

Not for a while... would have to set up a test/dev environment for it.

@candlerb commented on GitHub (Feb 4, 2021): Not for a while... would have to set up a test/dev environment for it.
Author
Owner

@jeremystretch commented on GitHub (Feb 4, 2021):

Shouldn't take more than a few minutes to get a development environment up and running. NetBox needs all the help it can get now that I'm no longer able to work on it full-time.

@jeremystretch commented on GitHub (Feb 4, 2021): Shouldn't take more than a few minutes to get a [development environment](https://netbox.readthedocs.io/en/stable/development/getting-started/) up and running. NetBox needs all the help it can get now that I'm no longer able to work on it full-time.
Author
Owner

@candlerb commented on GitHub (Feb 7, 2021):

Shouldn't take more than a few minutes to get a development environment up and running.

Looks like those instructions haven't been checked for a while :-(

(netbox) root@netbox-dev:~/netbox# python3 netbox/manage.py test
System check identified no issues (0 silenced).

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

This is fresh installation, with configuration.py based on configuration.testing.py.

(Makes random guesses) Ah, looks like I have to be in a different directory:

(netbox) root@netbox-dev:~/netbox# cd netbox/
(netbox) root@netbox-dev:~/netbox/netbox# python3 ./manage.py test
Creating test database for alias 'default'...
Got an error creating the test database: permission denied to create database

Now, user needs credentials with permissions to create databases?

postgres=# ALTER USER netboxtest CREATEDB;
ALTER ROLE

OK, that's sufficient to make the test suite run (4 are skipped, although it doesn't show which ones).

@candlerb commented on GitHub (Feb 7, 2021): > Shouldn't take more than a few minutes to get a [development environment](https://netbox.readthedocs.io/en/stable/development/getting-started/) up and running. Looks like those instructions haven't been checked for a while :-( ``` (netbox) root@netbox-dev:~/netbox# python3 netbox/manage.py test System check identified no issues (0 silenced). ---------------------------------------------------------------------- Ran 0 tests in 0.000s OK ``` This is fresh installation, with `configuration.py` based on `configuration.testing.py`. (Makes random guesses) Ah, looks like I have to be in a different directory: ``` (netbox) root@netbox-dev:~/netbox# cd netbox/ (netbox) root@netbox-dev:~/netbox/netbox# python3 ./manage.py test Creating test database for alias 'default'... Got an error creating the test database: permission denied to create database ``` Now, user needs credentials with permissions to create databases? ``` postgres=# ALTER USER netboxtest CREATEDB; ALTER ROLE ``` OK, that's sufficient to make the test suite run (4 are skipped, although it doesn't show which ones).
Author
Owner

@candlerb commented on GitHub (Feb 7, 2021):

Is there any way to avoid it creating and deleting the entire database on every test? On a quad-core i7 it takes over a minute just to run a single test file.

(netbox) root@netbox-dev:~/netbox/netbox# time python3 ./manage.py test ipam.tests.test_models
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...F..................
======================================================================
FAIL: test_duplicate_nonunique_nonrole_role (ipam.tests.test_models.TestIPAddress)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/.venv/netbox/lib/python3.6/site-packages/django/test/utils.py", line 381, in inner
    return func(*args, **kwargs)
  File "/root/netbox/netbox/ipam/tests/test_models.py", line 266, in test_duplicate_nonunique_nonrole_role
    self.assertRaises(ValidationError, duplicate_ip.clean)
AssertionError: ValidationError not raised by clean

----------------------------------------------------------------------
Ran 22 tests in 0.177s

FAILED (failures=1)
Destroying test database for alias 'default'...

real	1m12.375s
user	0m57.308s
sys	0m0.280s

UPDATE: hint from forum: manage.py test {app} --keepdb

@candlerb commented on GitHub (Feb 7, 2021): Is there any way to avoid it creating and deleting the entire database on every test? On a quad-core i7 it takes over a minute just to run a single test file. ``` (netbox) root@netbox-dev:~/netbox/netbox# time python3 ./manage.py test ipam.tests.test_models Creating test database for alias 'default'... System check identified no issues (0 silenced). ...F.................. ====================================================================== FAIL: test_duplicate_nonunique_nonrole_role (ipam.tests.test_models.TestIPAddress) ---------------------------------------------------------------------- Traceback (most recent call last): File "/root/.venv/netbox/lib/python3.6/site-packages/django/test/utils.py", line 381, in inner return func(*args, **kwargs) File "/root/netbox/netbox/ipam/tests/test_models.py", line 266, in test_duplicate_nonunique_nonrole_role self.assertRaises(ValidationError, duplicate_ip.clean) AssertionError: ValidationError not raised by clean ---------------------------------------------------------------------- Ran 22 tests in 0.177s FAILED (failures=1) Destroying test database for alias 'default'... real 1m12.375s user 0m57.308s sys 0m0.280s ``` UPDATE: hint from [forum](https://groups.google.com/g/netbox-discuss/c/8YD1ZdFJ2CQ/m/f3SXm_ZyAwAJ): `manage.py test {app} --keepdb`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#4523