From 7c48e3632db052924c80213fc07faa8d3059fe7c Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 14 Apr 2021 10:21:07 -0400 Subject: [PATCH 01/10] Closes #6157: Support Markdown rendering for report logs --- docs/release-notes/version-2.10.md | 4 ++++ netbox/templates/extras/report_result.html | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 69db03724..8b1d367ef 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -2,6 +2,10 @@ ## v2.10.10 (FUTURE) +### Enhancements + +* [#6157](https://github.com/netbox-community/netbox/issues/6157) - Support Markdown rendering for report logs + ### Bug Fixes * [#5419](https://github.com/netbox-community/netbox/issues/5419) - Update parent device/VM when deleting a primary IP diff --git a/netbox/templates/extras/report_result.html b/netbox/templates/extras/report_result.html index 80715f2aa..3d01ca38e 100644 --- a/netbox/templates/extras/report_result.html +++ b/netbox/templates/extras/report_result.html @@ -66,9 +66,11 @@ {{ obj }} {% elif obj %} {{ obj }} + {% else %} + {% endif %} - {{ message }} + {{ message|render_markdown }} {% endfor %} {% endfor %} From 18a691482def587bfc65759d5a4569923a5010af Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 14 Apr 2021 10:38:54 -0400 Subject: [PATCH 02/10] Closes #6160: Add F connector port type --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/choices.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 8b1d367ef..6fccdaf00 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -5,6 +5,7 @@ ### Enhancements * [#6157](https://github.com/netbox-community/netbox/issues/6157) - Support Markdown rendering for report logs +* [#6160](https://github.com/netbox-community/netbox/issues/6160) - Add F connector port type ### Bug Fixes diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index ee832b085..57f288531 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -881,6 +881,7 @@ class PortTypeChoices(ChoiceSet): TYPE_TERA1P = 'tera-1p' TYPE_110_PUNCH = '110-punch' TYPE_BNC = 'bnc' + TYPE_F = 'f' TYPE_MRJ21 = 'mrj21' TYPE_ST = 'st' TYPE_SC = 'sc' @@ -910,6 +911,7 @@ class PortTypeChoices(ChoiceSet): (TYPE_TERA1P, 'TERA 1P'), (TYPE_110_PUNCH, '110 Punch'), (TYPE_BNC, 'BNC'), + (TYPE_F, 'F Connector'), (TYPE_MRJ21, 'MRJ21'), ), ), From e849d2827684f061b3fc4702a4c93f1a78353676 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 14 Apr 2021 10:40:31 -0400 Subject: [PATCH 03/10] Closes #5980: Add Saf-D-Grid power port, outlet types --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/choices.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 6fccdaf00..4ad08ea61 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -4,6 +4,7 @@ ### Enhancements +* [#5980](https://github.com/netbox-community/netbox/issues/5980) - Add Saf-D-Grid power port, outlet types * [#6157](https://github.com/netbox-community/netbox/issues/6157) - Support Markdown rendering for report logs * [#6160](https://github.com/netbox-community/netbox/issues/6160) - Add F connector port type diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 57f288531..bd4ae1831 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -314,6 +314,8 @@ class PowerPortTypeChoices(ChoiceSet): TYPE_USB_MICRO_B = 'usb-micro-b' TYPE_USB_3_B = 'usb-3-b' TYPE_USB_3_MICROB = 'usb-3-micro-b' + # Proprietary + TYPE_SAF_D_GRID = 'saf-d-grid' CHOICES = ( ('IEC 60320', ( @@ -414,6 +416,9 @@ class PowerPortTypeChoices(ChoiceSet): (TYPE_USB_3_B, 'USB 3.0 Type B'), (TYPE_USB_3_MICROB, 'USB 3.0 Micro B'), )), + ('Proprietary', ( + (TYPE_SAF_D_GRID, 'Saf-D-Grid'), + )), ) @@ -509,6 +514,7 @@ class PowerOutletTypeChoices(ChoiceSet): TYPE_USB_C = 'usb-c' # Proprietary TYPE_HDOT_CX = 'hdot-cx' + TYPE_SAF_D_GRID = 'saf-d-grid' CHOICES = ( ('IEC 60320', ( @@ -604,6 +610,7 @@ class PowerOutletTypeChoices(ChoiceSet): )), ('Proprietary', ( (TYPE_HDOT_CX, 'HDOT Cx'), + (TYPE_SAF_D_GRID, 'Saf-D-Grid'), )), ) From 3d0882856fd393c3feaa0b40227505894160b5da Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 14 Apr 2021 10:44:15 -0400 Subject: [PATCH 04/10] Closes #5796: Add DC terminal power port, outlet types --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/choices.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 4ad08ea61..83f9d5d25 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -4,6 +4,7 @@ ### Enhancements +* [#5796](https://github.com/netbox-community/netbox/issues/5796) - Add DC terminal power port, outlet types * [#5980](https://github.com/netbox-community/netbox/issues/5980) - Add Saf-D-Grid power port, outlet types * [#6157](https://github.com/netbox-community/netbox/issues/6157) - Support Markdown rendering for report logs * [#6160](https://github.com/netbox-community/netbox/issues/6160) - Add F connector port type diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index bd4ae1831..55b7539d1 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -314,6 +314,8 @@ class PowerPortTypeChoices(ChoiceSet): TYPE_USB_MICRO_B = 'usb-micro-b' TYPE_USB_3_B = 'usb-3-b' TYPE_USB_3_MICROB = 'usb-3-micro-b' + # Direct current (DC) + TYPE_DC = 'dc-terminal' # Proprietary TYPE_SAF_D_GRID = 'saf-d-grid' @@ -416,6 +418,9 @@ class PowerPortTypeChoices(ChoiceSet): (TYPE_USB_3_B, 'USB 3.0 Type B'), (TYPE_USB_3_MICROB, 'USB 3.0 Micro B'), )), + ('DC', ( + (TYPE_DC, 'DC Terminal'), + )), ('Proprietary', ( (TYPE_SAF_D_GRID, 'Saf-D-Grid'), )), @@ -512,6 +517,8 @@ class PowerOutletTypeChoices(ChoiceSet): TYPE_USB_A = 'usb-a' TYPE_USB_MICROB = 'usb-micro-b' TYPE_USB_C = 'usb-c' + # Direct current (DC) + TYPE_DC = 'dc-terminal' # Proprietary TYPE_HDOT_CX = 'hdot-cx' TYPE_SAF_D_GRID = 'saf-d-grid' @@ -608,6 +615,9 @@ class PowerOutletTypeChoices(ChoiceSet): (TYPE_USB_MICROB, 'USB Micro B'), (TYPE_USB_C, 'USB Type C'), )), + ('DC', ( + (TYPE_DC, 'DC Terminal'), + )), ('Proprietary', ( (TYPE_HDOT_CX, 'HDOT Cx'), (TYPE_SAF_D_GRID, 'Saf-D-Grid'), From a2203da1c6fa674a55d3071a287094d70cb1c502 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 14 Apr 2021 16:17:19 -0400 Subject: [PATCH 05/10] Fixes #6162: Fix choice field filters (multiple models) --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/filters.py | 32 ++++++++++++++++++++++++ netbox/dcim/tests/test_filters.py | 40 ++++++++++++------------------ 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 83f9d5d25..9c41edd2c 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -15,6 +15,7 @@ * [#6056](https://github.com/netbox-community/netbox/issues/6056) - Optimize change log cleanup * [#6144](https://github.com/netbox-community/netbox/issues/6144) - Fix MAC address field display in VM interfaces search form * [#6152](https://github.com/netbox-community/netbox/issues/6152) - Fix custom field filtering for cables, virtual chassis +* [#6162](https://github.com/netbox-community/netbox/issues/6162) - Fix choice field filters (multiple models) --- diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index dff552910..ac6ecb272 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -446,6 +446,10 @@ class PowerPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): class PowerOutletTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): + feed_leg = django_filters.MultipleChoiceFilter( + choices=PowerOutletFeedLegChoices, + null_value=None + ) class Meta: model = PowerOutletTemplate @@ -453,6 +457,10 @@ class PowerOutletTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): class InterfaceTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): + type = django_filters.MultipleChoiceFilter( + choices=InterfaceTypeChoices, + null_value=None + ) class Meta: model = InterfaceTemplate @@ -460,6 +468,10 @@ class InterfaceTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): class FrontPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): + type = django_filters.MultipleChoiceFilter( + choices=PortTypeChoices, + null_value=None + ) class Meta: model = FrontPortTemplate @@ -467,6 +479,10 @@ class FrontPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): class RearPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet): + type = django_filters.MultipleChoiceFilter( + choices=PortTypeChoices, + null_value=None + ) class Meta: model = RearPortTemplate @@ -817,6 +833,10 @@ class PowerOutletFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTermina choices=PowerOutletTypeChoices, null_value=None ) + feed_leg = django_filters.MultipleChoiceFilter( + choices=PowerOutletFeedLegChoices, + null_value=None + ) class Meta: model = PowerOutlet @@ -917,6 +937,10 @@ class InterfaceFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminati class FrontPortFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet): + type = django_filters.MultipleChoiceFilter( + choices=PortTypeChoices, + null_value=None + ) class Meta: model = FrontPort @@ -924,6 +948,10 @@ class FrontPortFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminati class RearPortFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet): + type = django_filters.MultipleChoiceFilter( + choices=PortTypeChoices, + null_value=None + ) class Meta: model = RearPort @@ -1301,6 +1329,10 @@ class PowerFeedFilterSet( queryset=Rack.objects.all(), label='Rack (ID)', ) + status = django_filters.MultipleChoiceFilter( + choices=PowerFeedStatusChoices, + null_value=None + ) tag = TagFilter() class Meta: diff --git a/netbox/dcim/tests/test_filters.py b/netbox/dcim/tests/test_filters.py index 02a44bbc1..f9ab32765 100644 --- a/netbox/dcim/tests/test_filters.py +++ b/netbox/dcim/tests/test_filters.py @@ -851,9 +851,8 @@ class PowerOutletTemplateTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_feed_leg(self): - # TODO: Support filtering for multiple values - params = {'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_A} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'feed_leg': [PowerOutletFeedLegChoices.FEED_LEG_A, PowerOutletFeedLegChoices.FEED_LEG_B]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) class InterfaceTemplateTestCase(TestCase): @@ -892,9 +891,8 @@ class InterfaceTemplateTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_type(self): - # TODO: Support filtering for multiple values - params = {'type': InterfaceTypeChoices.TYPE_1GE_FIXED} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'type': [InterfaceTypeChoices.TYPE_1GE_FIXED, InterfaceTypeChoices.TYPE_1GE_GBIC]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_mgmt_only(self): params = {'mgmt_only': 'true'} @@ -946,9 +944,8 @@ class FrontPortTemplateTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_type(self): - # TODO: Support filtering for multiple values - params = {'type': PortTypeChoices.TYPE_8P8C} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'type': [PortTypeChoices.TYPE_8P8C, PortTypeChoices.TYPE_110_PUNCH]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) class RearPortTemplateTestCase(TestCase): @@ -987,9 +984,8 @@ class RearPortTemplateTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_type(self): - # TODO: Support filtering for multiple values - params = {'type': PortTypeChoices.TYPE_8P8C} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'type': [PortTypeChoices.TYPE_8P8C, PortTypeChoices.TYPE_110_PUNCH]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_positions(self): params = {'positions': [1, 2]} @@ -1824,9 +1820,8 @@ class PowerOutletTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_feed_leg(self): - # TODO: Support filtering for multiple values - params = {'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_A} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'feed_leg': [PowerOutletFeedLegChoices.FEED_LEG_A, PowerOutletFeedLegChoices.FEED_LEG_B]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_connected(self): params = {'connected': True} @@ -2063,9 +2058,8 @@ class FrontPortTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_type(self): - # TODO: Test for multiple values - params = {'type': PortTypeChoices.TYPE_8P8C} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'type': [PortTypeChoices.TYPE_8P8C, PortTypeChoices.TYPE_110_PUNCH]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_description(self): params = {'description': ['First', 'Second']} @@ -2159,9 +2153,8 @@ class RearPortTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_type(self): - # TODO: Test for multiple values - params = {'type': PortTypeChoices.TYPE_8P8C} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'type': [PortTypeChoices.TYPE_8P8C, PortTypeChoices.TYPE_110_PUNCH]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_positions(self): params = {'positions': [1, 2]} @@ -2732,9 +2725,8 @@ class PowerFeedTestCase(TestCase): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_status(self): - # TODO: Test for multiple values - params = {'status': PowerFeedStatusChoices.STATUS_ACTIVE} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'status': [PowerFeedStatusChoices.STATUS_ACTIVE, PowerFeedStatusChoices.STATUS_FAILED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_type(self): params = {'type': PowerFeedTypeChoices.TYPE_PRIMARY} From 92df40a6a012a82b02eae73a4b43b97e5907f26e Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 15 Apr 2021 12:04:34 -0400 Subject: [PATCH 06/10] Fixes #5652: Update object data when renaming a custom field --- docs/release-notes/version-2.10.md | 1 + netbox/extras/models/customfields.py | 18 ++++++++++++++++ netbox/extras/signals.py | 11 +++++++++- netbox/extras/tests/test_customfields.py | 27 ++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 9c41edd2c..3755944dc 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -12,6 +12,7 @@ ### Bug Fixes * [#5419](https://github.com/netbox-community/netbox/issues/5419) - Update parent device/VM when deleting a primary IP +* [#5652](https://github.com/netbox-community/netbox/issues/5652) - Update object data when renaming a custom field * [#6056](https://github.com/netbox-community/netbox/issues/6056) - Optimize change log cleanup * [#6144](https://github.com/netbox-community/netbox/issues/6144) - Fix MAC address field display in VM interfaces search form * [#6152](https://github.com/netbox-community/netbox/issues/6152) - Fix custom field filtering for cables, virtual chassis diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index a69816d21..4f37d4870 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -162,6 +162,24 @@ class CustomField(models.Model): def __str__(self): return self.label or self.name.replace('_', ' ').capitalize() + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Cache instance's original name so we can check later whether it has changed + self._name = self.name + + def rename_object_data(self, old_name, new_name): + """ + Called when a CustomField has been renamed. Updates all assigned object data. + """ + for ct in self.content_types.all(): + model = ct.model_class() + params = {f'custom_field_data__{old_name}__isnull': False} + instances = model.objects.filter(**params) + for instance in instances: + instance.custom_field_data[new_name] = instance.custom_field_data.pop(old_name) + model.objects.bulk_update(instances, ['custom_field_data'], batch_size=100) + def remove_stale_data(self, content_types): """ Delete custom field data which is no longer relevant (either because the CustomField is diff --git a/netbox/extras/signals.py b/netbox/extras/signals.py index 9eeb4ce45..3556f6fe8 100644 --- a/netbox/extras/signals.py +++ b/netbox/extras/signals.py @@ -5,7 +5,7 @@ from cacheops.signals import cache_invalidated, cache_read from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.db import DEFAULT_DB_ALIAS -from django.db.models.signals import m2m_changed, pre_delete +from django.db.models.signals import m2m_changed, post_save, pre_delete from django.utils import timezone from django_prometheus.models import model_deletes, model_inserts, model_updates from prometheus_client import Counter @@ -86,6 +86,14 @@ def handle_cf_removed_obj_types(instance, action, pk_set, **kwargs): instance.remove_stale_data(ContentType.objects.filter(pk__in=pk_set)) +def handle_cf_renamed(instance, created, **kwargs): + """ + Handle the renaming of custom field data on objects when a CustomField is renamed. + """ + if not created and instance.name != instance._name: + instance.rename_object_data(old_name=instance._name, new_name=instance.name) + + def handle_cf_deleted(instance, **kwargs): """ Handle the cleanup of old custom field data when a CustomField is deleted. @@ -94,6 +102,7 @@ def handle_cf_deleted(instance, **kwargs): m2m_changed.connect(handle_cf_removed_obj_types, sender=CustomField.content_types.through) +post_save.connect(handle_cf_renamed, sender=CustomField) pre_delete.connect(handle_cf_deleted, sender=CustomField) diff --git a/netbox/extras/tests/test_customfields.py b/netbox/extras/tests/test_customfields.py index 4f7a67676..d1725ac9d 100644 --- a/netbox/extras/tests/test_customfields.py +++ b/netbox/extras/tests/test_customfields.py @@ -91,6 +91,33 @@ class CustomFieldTest(TestCase): # Delete the custom field cf.delete() + def test_rename_customfield(self): + obj_type = ContentType.objects.get_for_model(Site) + FIELD_DATA = 'abc' + + # Create a custom field + cf = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='field1') + cf.save() + cf.content_types.set([obj_type]) + + # Assign custom field data to an object + site = Site.objects.create( + name='Site 1', + slug='site-1', + custom_field_data={'field1': FIELD_DATA} + ) + site.refresh_from_db() + self.assertEqual(site.custom_field_data['field1'], FIELD_DATA) + + # Rename the custom field + cf.name = 'field2' + cf.save() + + # Check that custom field data on the object has been updated + site.refresh_from_db() + self.assertNotIn('field1', site.custom_field_data) + self.assertEqual(site.custom_field_data['field2'], FIELD_DATA) + class CustomFieldManagerTest(TestCase): From 14d2a499420aa1fd28508311781c769adfbab4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20N=C3=B6thlich?= Date: Thu, 15 Apr 2021 18:37:45 +0200 Subject: [PATCH 07/10] Fixes #6168: Add SFP56 interface type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Adrian Nöthlich --- netbox/dcim/choices.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 55b7539d1..a33e268a3 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -662,6 +662,7 @@ class InterfaceTypeChoices(ChoiceSet): TYPE_10GE_XENPAK = '10gbase-x-xenpak' TYPE_10GE_X2 = '10gbase-x-x2' TYPE_25GE_SFP28 = '25gbase-x-sfp28' + TYPE_50GE_SFP56 = '50gbase-x-sfp56' TYPE_40GE_QSFP_PLUS = '40gbase-x-qsfpp' TYPE_50GE_QSFP28 = '50gbase-x-sfp28' TYPE_100GE_CFP = '100gbase-x-cfp' @@ -766,6 +767,7 @@ class InterfaceTypeChoices(ChoiceSet): (TYPE_10GE_XENPAK, 'XENPAK (10GE)'), (TYPE_10GE_X2, 'X2 (10GE)'), (TYPE_25GE_SFP28, 'SFP28 (25GE)'), + (TYPE_50GE_SFP56, 'SFP56 (50GE)'), (TYPE_40GE_QSFP_PLUS, 'QSFP+ (40GE)'), (TYPE_50GE_QSFP28, 'QSFP28 (50GE)'), (TYPE_100GE_CFP, 'CFP (100GE)'), From f67369a9a9fa283469c80ed3a18cef2d03f31036 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 15 Apr 2021 13:26:19 -0400 Subject: [PATCH 08/10] Fixes #5643: Fix VLAN assignment when editing VM interfaces in bulk --- docs/release-notes/version-2.10.md | 1 + netbox/virtualization/forms.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 3755944dc..0e1e207fd 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -12,6 +12,7 @@ ### Bug Fixes * [#5419](https://github.com/netbox-community/netbox/issues/5419) - Update parent device/VM when deleting a primary IP +* [#5643](https://github.com/netbox-community/netbox/issues/5643) - Fix VLAN assignment when editing VM interfaces in bulk * [#5652](https://github.com/netbox-community/netbox/issues/5652) - Update object data when renaming a custom field * [#6056](https://github.com/netbox-community/netbox/issues/6056) - Optimize change log cleanup * [#6144](https://github.com/netbox-community/netbox/issues/6144) - Fix MAC address field display in VM interfaces search form diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index a3e6c4cf4..8d20b390a 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -756,6 +756,26 @@ class VMInterfaceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): # Add current site to VLANs query params self.fields['untagged_vlan'].widget.add_query_param('site_id', site.pk) self.fields['tagged_vlans'].widget.add_query_param('site_id', site.pk) + else: + # See 5643 + if 'pk' in self.initial: + site = None + interfaces = VMInterface.objects.filter(pk__in=self.initial['pk']).prefetch_related( + 'virtual_machine__cluster__site' + ) + + # Check interface sites. First interface should set site, further interfaces will either continue the + # loop or reset back to no site and break the loop. + for interface in interfaces: + if site is None: + site = interface.virtual_machine.cluster.site + elif interface.virtual_machine.cluster.site is not site: + site = None + break + + if site is not None: + self.fields['untagged_vlan'].widget.add_query_param('site_id', site.pk) + self.fields['tagged_vlans'].widget.add_query_param('site_id', site.pk) class VMInterfaceBulkRenameForm(BulkRenameForm): From 3e49745257bcb67b3091e63f1342c1a3cb19f856 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 15 Apr 2021 13:30:42 -0400 Subject: [PATCH 09/10] Changelog for #6168 --- docs/release-notes/version-2.10.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 0e1e207fd..4329c9916 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -8,6 +8,7 @@ * [#5980](https://github.com/netbox-community/netbox/issues/5980) - Add Saf-D-Grid power port, outlet types * [#6157](https://github.com/netbox-community/netbox/issues/6157) - Support Markdown rendering for report logs * [#6160](https://github.com/netbox-community/netbox/issues/6160) - Add F connector port type +* [#6168](https://github.com/netbox-community/netbox/issues/6168) - Add SFP56 50GE interface type ### Bug Fixes From ae349d4424b853f7bdf2858de1970a9d3e40df3a Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 15 Apr 2021 15:20:30 -0400 Subject: [PATCH 10/10] Release v2.10.10 --- docs/release-notes/version-2.10.md | 2 +- netbox/netbox/settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 4329c9916..d356fc235 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -1,6 +1,6 @@ # NetBox v2.10 -## v2.10.10 (FUTURE) +## v2.10.10 (2021-04-15) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 233ee72c4..3c03651bf 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -16,7 +16,7 @@ from django.core.validators import URLValidator # Environment setup # -VERSION = '2.10.10-dev' +VERSION = '2.10.10' # Hostname HOSTNAME = platform.node()