From b6170cf0c98cd8eac35914c9e3a8611754bf8a6b Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Thu, 2 May 2024 13:39:29 +0200 Subject: [PATCH 01/11] Add OUI model --- python/nav/models/oui.py | 19 +++++++++++++++++++ .../nav/models/sql/changes/sc.05.08.0001.sql | 5 +++++ 2 files changed, 24 insertions(+) create mode 100644 python/nav/models/oui.py create mode 100644 python/nav/models/sql/changes/sc.05.08.0001.sql diff --git a/python/nav/models/oui.py b/python/nav/models/oui.py new file mode 100644 index 0000000000..c175601ec7 --- /dev/null +++ b/python/nav/models/oui.py @@ -0,0 +1,19 @@ +from django.db import models +from django.core.validators import MinLengthValidator + +from nav.models.fields import VarcharField + + +class OUI(models.Model): + """Defines an OUI and the name of the vendor the OUI belongs to""" + + vendor = VarcharField() + oui = models.CharField( + max_length=6, unique=True, validators=[MinLengthValidator(6)] + ) + + def __str__(self): + return self.oui + + class Meta(object): + db_table = 'oui' diff --git a/python/nav/models/sql/changes/sc.05.08.0001.sql b/python/nav/models/sql/changes/sc.05.08.0001.sql new file mode 100644 index 0000000000..f59238c950 --- /dev/null +++ b/python/nav/models/sql/changes/sc.05.08.0001.sql @@ -0,0 +1,5 @@ +CREATE TABLE manage.oui ( + id SERIAL PRIMARY KEY, + vendor VARCHAR NOT NULL, + oui CHAR(6) NOT NULL UNIQUE +); From 50e5d36273b008562338891c7d5b3f9f67b6dfd9 Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Thu, 2 May 2024 13:47:54 +0200 Subject: [PATCH 02/11] Add towncrier file --- changelog.d/+2896.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/+2896.added.md diff --git a/changelog.d/+2896.added.md b/changelog.d/+2896.added.md new file mode 100644 index 0000000000..320ed61532 --- /dev/null +++ b/changelog.d/+2896.added.md @@ -0,0 +1 @@ +Add model representing an Organizationally Unique Identifier (OUI) \ No newline at end of file From ff0d65e9e153f809925e8d5ba64fd79cbba681cf Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Fri, 3 May 2024 10:49:51 +0200 Subject: [PATCH 03/11] Add OUI tests --- tests/integration/models/oui_test.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/integration/models/oui_test.py diff --git a/tests/integration/models/oui_test.py b/tests/integration/models/oui_test.py new file mode 100644 index 0000000000..7ab6653019 --- /dev/null +++ b/tests/integration/models/oui_test.py @@ -0,0 +1,26 @@ +import pytest + +from django.core.exceptions import ValidationError + +from nav.models.oui import OUI + + +class TestOUI: + def test_validation_should_raise_error_if_oid_is_less_than_6_characters(self): + with pytest.raises(ValidationError): + instance = OUI(oui="AABB", vendor="myvendor") + instance.full_clean() + + def test_validation_should_raise_error_if_oid_is_more_than_6_characters(self): + with pytest.raises(ValidationError): + instance = OUI(oui="AABBCCDD", vendor="myvendor") + instance.full_clean() + + def test_validation_should_allow_oid_with_6_characters(self): + instance = OUI(oui="AABBCC", vendor="myvendor") + instance.full_clean() + + def test_string_representation_should_match_oid(self): + oui = "AABBCC" + instance = OUI(oui=oui, vendor="myvendor") + assert str(instance) == oui From 6212cc9797cc5a9235f7cae1491e0588bbc51738 Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Fri, 3 May 2024 14:01:05 +0200 Subject: [PATCH 04/11] Use macaddr data type --- python/nav/models/oui.py | 5 +---- python/nav/models/sql/changes/sc.05.08.0001.sql | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/python/nav/models/oui.py b/python/nav/models/oui.py index c175601ec7..2dc41fc5d4 100644 --- a/python/nav/models/oui.py +++ b/python/nav/models/oui.py @@ -1,5 +1,4 @@ from django.db import models -from django.core.validators import MinLengthValidator from nav.models.fields import VarcharField @@ -8,9 +7,7 @@ class OUI(models.Model): """Defines an OUI and the name of the vendor the OUI belongs to""" vendor = VarcharField() - oui = models.CharField( - max_length=6, unique=True, validators=[MinLengthValidator(6)] - ) + oui = models.CharField(max_length=17) def __str__(self): return self.oui diff --git a/python/nav/models/sql/changes/sc.05.08.0001.sql b/python/nav/models/sql/changes/sc.05.08.0001.sql index f59238c950..386e0b4961 100644 --- a/python/nav/models/sql/changes/sc.05.08.0001.sql +++ b/python/nav/models/sql/changes/sc.05.08.0001.sql @@ -1,5 +1,5 @@ CREATE TABLE manage.oui ( id SERIAL PRIMARY KEY, vendor VARCHAR NOT NULL, - oui CHAR(6) NOT NULL UNIQUE + oui MACADDR NOT NULL UNIQUE ); From f22185444b136593c8ad96c5332733326032d7fc Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Fri, 3 May 2024 14:50:52 +0200 Subject: [PATCH 05/11] Constraint last 3 bytes to be 0 --- python/nav/models/sql/changes/sc.05.08.0001.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/nav/models/sql/changes/sc.05.08.0001.sql b/python/nav/models/sql/changes/sc.05.08.0001.sql index 386e0b4961..e59e8ed263 100644 --- a/python/nav/models/sql/changes/sc.05.08.0001.sql +++ b/python/nav/models/sql/changes/sc.05.08.0001.sql @@ -1,5 +1,6 @@ CREATE TABLE manage.oui ( id SERIAL PRIMARY KEY, vendor VARCHAR NOT NULL, - oui MACADDR NOT NULL UNIQUE + oui MACADDR NOT NULL UNIQUE, + CHECK (oui=trunc(oui)) ); From 8067ff1a30713276ca893329b0589de1f5c3b959 Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Fri, 3 May 2024 14:51:18 +0200 Subject: [PATCH 06/11] Update tests --- tests/integration/models/oui_test.py | 47 +++++++++++++++++----------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/tests/integration/models/oui_test.py b/tests/integration/models/oui_test.py index 7ab6653019..c506249f41 100644 --- a/tests/integration/models/oui_test.py +++ b/tests/integration/models/oui_test.py @@ -1,26 +1,35 @@ import pytest -from django.core.exceptions import ValidationError +from django.db.utils import IntegrityError from nav.models.oui import OUI class TestOUI: - def test_validation_should_raise_error_if_oid_is_less_than_6_characters(self): - with pytest.raises(ValidationError): - instance = OUI(oui="AABB", vendor="myvendor") - instance.full_clean() - - def test_validation_should_raise_error_if_oid_is_more_than_6_characters(self): - with pytest.raises(ValidationError): - instance = OUI(oui="AABBCCDD", vendor="myvendor") - instance.full_clean() - - def test_validation_should_allow_oid_with_6_characters(self): - instance = OUI(oui="AABBCC", vendor="myvendor") - instance.full_clean() - - def test_string_representation_should_match_oid(self): - oui = "AABBCC" - instance = OUI(oui=oui, vendor="myvendor") - assert str(instance) == oui + def test_string_representation_should_match_oid(self, valid_oui): + assert str(valid_oui) == valid_oui.oui + + def test_save_should_raise_error_if_last_3_bytes_are_not_zero(self, invalid_oui): + with pytest.raises(IntegrityError): + invalid_oui.save() + + def test_save_should_allow_oui_if_last_3_bytes_are_zero(self, valid_oui): + valid_oui.save() + + +@pytest.fixture() +def valid_oui(): + oui = "aa:bb:cc:00:00:00" + instance = OUI(oui=oui, vendor="myvendor") + yield instance + if instance.id: + instance.delete() + + +@pytest.fixture() +def invalid_oui(): + oui = "aa:bb:cc:dd:ee:ff" + instance = OUI(oui=oui, vendor="myvendor") + yield instance + if instance.id: + instance.delete() From ec34f179cd3cb48ef8c4b6e99f2f78a3b1edc009 Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Thu, 16 May 2024 09:22:00 +0200 Subject: [PATCH 07/11] Rename sql file --- .../models/sql/changes/{sc.05.08.0001.sql => sc.05.10.0002.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/nav/models/sql/changes/{sc.05.08.0001.sql => sc.05.10.0002.sql} (100%) diff --git a/python/nav/models/sql/changes/sc.05.08.0001.sql b/python/nav/models/sql/changes/sc.05.10.0002.sql similarity index 100% rename from python/nav/models/sql/changes/sc.05.08.0001.sql rename to python/nav/models/sql/changes/sc.05.10.0002.sql From 216124de4dc08fd921f77cf32f8a6cdeac227ca2 Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Fri, 9 Aug 2024 10:03:33 +0200 Subject: [PATCH 08/11] Fix typo --- tests/integration/models/oui_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/models/oui_test.py b/tests/integration/models/oui_test.py index c506249f41..6efe189563 100644 --- a/tests/integration/models/oui_test.py +++ b/tests/integration/models/oui_test.py @@ -6,7 +6,7 @@ class TestOUI: - def test_string_representation_should_match_oid(self, valid_oui): + def test_string_representation_should_match_oui(self, valid_oui): assert str(valid_oui) == valid_oui.oui def test_save_should_raise_error_if_last_3_bytes_are_not_zero(self, invalid_oui): From 82df8233a948a5cdea1791397fa2b2852a66cecb Mon Sep 17 00:00:00 2001 From: stveit <31960753+stveit@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:52:50 +0200 Subject: [PATCH 09/11] Set oui field as unique Co-authored-by: Johanna England --- python/nav/models/oui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/nav/models/oui.py b/python/nav/models/oui.py index 2dc41fc5d4..88846ebff9 100644 --- a/python/nav/models/oui.py +++ b/python/nav/models/oui.py @@ -7,7 +7,7 @@ class OUI(models.Model): """Defines an OUI and the name of the vendor the OUI belongs to""" vendor = VarcharField() - oui = models.CharField(max_length=17) + oui = models.CharField(max_length=17, unique=True) def __str__(self): return self.oui From cafcfa18ea2fb6ec51de1d11b4b95d2ad6b07baa Mon Sep 17 00:00:00 2001 From: stveit <31960753+stveit@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:53:02 +0200 Subject: [PATCH 10/11] Update changelog.d/+2896.added.md Co-authored-by: Johanna England --- changelog.d/+2896.added.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/+2896.added.md b/changelog.d/+2896.added.md index 320ed61532..faa3cfe0a8 100644 --- a/changelog.d/+2896.added.md +++ b/changelog.d/+2896.added.md @@ -1 +1 @@ -Add model representing an Organizationally Unique Identifier (OUI) \ No newline at end of file +Add model representing an Organizationally Unique Identifier (OUI) to identify vendors for mac addresses \ No newline at end of file From 0029ccb8a79f99401e1dd430a456f53373ee58f8 Mon Sep 17 00:00:00 2001 From: Simon Oliver Tveit Date: Thu, 22 Aug 2024 15:31:46 +0200 Subject: [PATCH 11/11] Set oui as primary key for OUI model --- python/nav/models/oui.py | 2 +- python/nav/models/sql/changes/sc.05.10.0002.sql | 3 +-- tests/integration/models/oui_test.py | 6 ++---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/python/nav/models/oui.py b/python/nav/models/oui.py index 88846ebff9..e2911f1892 100644 --- a/python/nav/models/oui.py +++ b/python/nav/models/oui.py @@ -6,8 +6,8 @@ class OUI(models.Model): """Defines an OUI and the name of the vendor the OUI belongs to""" + oui = models.CharField(max_length=17, primary_key=True) vendor = VarcharField() - oui = models.CharField(max_length=17, unique=True) def __str__(self): return self.oui diff --git a/python/nav/models/sql/changes/sc.05.10.0002.sql b/python/nav/models/sql/changes/sc.05.10.0002.sql index e59e8ed263..514768bccf 100644 --- a/python/nav/models/sql/changes/sc.05.10.0002.sql +++ b/python/nav/models/sql/changes/sc.05.10.0002.sql @@ -1,6 +1,5 @@ CREATE TABLE manage.oui ( - id SERIAL PRIMARY KEY, + oui MACADDR PRIMARY KEY, vendor VARCHAR NOT NULL, - oui MACADDR NOT NULL UNIQUE, CHECK (oui=trunc(oui)) ); diff --git a/tests/integration/models/oui_test.py b/tests/integration/models/oui_test.py index 6efe189563..ce1323fe13 100644 --- a/tests/integration/models/oui_test.py +++ b/tests/integration/models/oui_test.py @@ -22,8 +22,7 @@ def valid_oui(): oui = "aa:bb:cc:00:00:00" instance = OUI(oui=oui, vendor="myvendor") yield instance - if instance.id: - instance.delete() + instance.delete() @pytest.fixture() @@ -31,5 +30,4 @@ def invalid_oui(): oui = "aa:bb:cc:dd:ee:ff" instance = OUI(oui=oui, vendor="myvendor") yield instance - if instance.id: - instance.delete() + instance.delete()