From c8f09f28b16979e84b32dca7b859cb9d5f4dd952 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 5 Jan 2021 21:10:58 -0500 Subject: [PATCH 01/30] PRVB --- netbox/netbox/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 4c36332fc..ed1f9c732 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.3' +VERSION = '2.10.4-dev' # Hostname HOSTNAME = platform.node() From 47b7ec8d00905dd82a44945691b526750d1467ac Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 Jan 2021 11:19:11 -0500 Subject: [PATCH 02/30] Fixes #5584: Restore power utilization panel under device view --- docs/release-notes/version-2.10.md | 8 ++++++++ netbox/templates/dcim/device.html | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index a3ab5968c..9773ec1b7 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -1,5 +1,13 @@ # NetBox v2.10 +## v2.10.4 (FUTURE) + +### Bug Fixes + +* [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view + +--- + ## v2.10.3 (2021-01-05) ### Bug Fixes diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 97f7c8953..55be343ac 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -204,7 +204,7 @@ {% plugin_left_page object %}
- {% if power_ports and poweroutlets %} + {% if object.powerports.exists and object.poweroutlets.exists %}
Power Utilization @@ -217,10 +217,10 @@ Available Utilization - {% for pp in power_ports %} - {% with utilization=pp.get_power_draw powerfeed=pp.connected_endpoint %} + {% for powerport in object.powerports.all %} + {% with utilization=powerport.get_power_draw powerfeed=powerport.connected_endpoint %} - {{ pp }} + {{ powerport }} {{ utilization.outlet_count }} {{ utilization.allocated }}VA {% if powerfeed.available_power %} From e9d888bf6330f1107f38aaa2458b7c04a34fc9fb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 Jan 2021 11:29:59 -0500 Subject: [PATCH 03/30] Closes #5570: Add "management only" filter widget for interfaces list --- docs/release-notes/version-2.10.md | 4 ++++ netbox/dcim/forms.py | 6 ++++++ netbox/dcim/tables/devices.py | 1 + 3 files changed, 11 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 9773ec1b7..f9dee5dec 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -2,6 +2,10 @@ ## v2.10.4 (FUTURE) +### Enhancements + +* [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list + ### Bug Fixes * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index f7eb510ec..18fdbdb40 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2687,6 +2687,12 @@ class InterfaceFilterForm(DeviceComponentFilterForm): choices=BOOLEAN_WITH_BLANK_CHOICES ) ) + mgmt_only = forms.NullBooleanField( + required=False, + widget=StaticSelect2( + choices=BOOLEAN_WITH_BLANK_CHOICES + ) + ) mac_address = forms.CharField( required=False, label='MAC address' diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index 663206505..2b067a69d 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -406,6 +406,7 @@ class BaseInterfaceTable(BaseTable): class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable): + mgmt_only = BooleanColumn() tags = TagColumn( url_name='dcim:interface_list' ) From c51d2a56ac09eb4b34882a3af0eaec9a9c0a6a31 Mon Sep 17 00:00:00 2001 From: Mikhail Yohman Date: Fri, 8 Jan 2021 19:30:27 -0700 Subject: [PATCH 04/30] Closes 5586: Adds name, master, and master_id filtering --- netbox/dcim/filters.py | 12 +++++++++++- netbox/dcim/tests/test_filters.py | 17 ++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 3046a0f33..05ae08923 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -1016,6 +1016,16 @@ class VirtualChassisFilterSet(BaseFilterSet): method='search', label='Search', ) + master_id = django_filters.ModelMultipleChoiceFilter( + queryset=Device.objects.all(), + label='Master (ID)', + ) + master = django_filters.ModelMultipleChoiceFilter( + field_name='master__name', + queryset=Device.objects.all(), + to_field_name='name', + label='Master (name)', + ) region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='master__site__region', @@ -1055,7 +1065,7 @@ class VirtualChassisFilterSet(BaseFilterSet): class Meta: model = VirtualChassis - fields = ['id', 'domain'] + fields = ['id', 'domain', 'name'] def search(self, queryset, name, value): if not value.strip(): diff --git a/netbox/dcim/tests/test_filters.py b/netbox/dcim/tests/test_filters.py index c701c47cf..a76788e65 100644 --- a/netbox/dcim/tests/test_filters.py +++ b/netbox/dcim/tests/test_filters.py @@ -2399,9 +2399,9 @@ class VirtualChassisTestCase(TestCase): Device.objects.bulk_create(devices) virtual_chassis = ( - VirtualChassis(master=devices[0], domain='Domain 1'), - VirtualChassis(master=devices[2], domain='Domain 2'), - VirtualChassis(master=devices[4], domain='Domain 3'), + VirtualChassis(name='VC 1', master=devices[0], domain='Domain 1'), + VirtualChassis(name='VC 2', master=devices[2], domain='Domain 2'), + VirtualChassis(name='VC 3', master=devices[4], domain='Domain 3'), ) VirtualChassis.objects.bulk_create(virtual_chassis) @@ -2417,6 +2417,17 @@ class VirtualChassisTestCase(TestCase): params = {'domain': ['Domain 1', 'Domain 2']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_master(self): + masters = Device.objects.all() + params = {'master_id': [masters[0].pk, masters[2].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'master': [masters[0].name, masters[2].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['VC 1', 'VC 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_region(self): regions = Region.objects.all()[:2] params = {'region_id': [regions[0].pk, regions[1].pk]} From 1e1e2d5f54a3c5ff60e15deb7a71a81fb4ddc8fb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 11 Jan 2021 11:28:03 -0500 Subject: [PATCH 05/30] Fixes #5597: Fix ordering devices by primary IP address --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/tables/devices.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index f9dee5dec..870a11890 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -9,6 +9,7 @@ ### Bug Fixes * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view +* [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address --- diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index 2b067a69d..edd9e7a43 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -129,6 +129,7 @@ class DeviceTable(BaseTable): ) primary_ip = tables.Column( linkify=True, + order_by=('primary_ip6', 'primary_ip4'), verbose_name='IP Address' ) primary_ip4 = tables.Column( From e13d96a6f24ad45fdfd354a47f22947b005b7acc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sun, 17 Jan 2021 14:08:59 -0500 Subject: [PATCH 06/30] Don't pin Ubuntu installations to Python 3.6 --- docs/installation/3-netbox.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation/3-netbox.md b/docs/installation/3-netbox.md index 9745df1f3..f2461b40d 100644 --- a/docs/installation/3-netbox.md +++ b/docs/installation/3-netbox.md @@ -7,12 +7,12 @@ This section of the documentation discusses installing and configuring the NetBo Begin by installing all system packages required by NetBox and its dependencies. !!! note - NetBox v2.8.0 and later require Python 3.6, 3.7, or 3.8. This documentation assumes Python 3.6. + NetBox v2.8.0 and later require Python 3.6, 3.7, or 3.8. ### Ubuntu ```no-highlight -sudo apt install -y python3.6 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev +sudo apt install -y python3 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev ``` ### CentOS From d838a76461771f71144c8b9ae75eef55aa71e8ca Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Mon, 18 Jan 2021 14:06:28 +0100 Subject: [PATCH 07/30] Add choices for GG45 and TERA connectors and Cat7a/Cat8 cables Fixes #5612 --- netbox/dcim/choices.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index d8f8e3e27..d4cc0ecf4 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -873,6 +873,10 @@ class PortTypeChoices(ChoiceSet): TYPE_8P6C = '8p6c' TYPE_8P4C = '8p4c' TYPE_8P2C = '8p2c' + TYPE_GG45 = 'gg45' + TYPE_TERA4P = 'tera-4p' + TYPE_TERA2P = 'tera-2p' + TYPE_TERA1P = 'tera-1p' TYPE_110_PUNCH = '110-punch' TYPE_BNC = 'bnc' TYPE_MRJ21 = 'mrj21' @@ -898,6 +902,10 @@ class PortTypeChoices(ChoiceSet): (TYPE_8P6C, '8P6C'), (TYPE_8P4C, '8P4C'), (TYPE_8P2C, '8P2C'), + (TYPE_GG45, 'GG45'), + (TYPE_TERA4P, 'TERA 4P'), + (TYPE_TERA2P, 'TERA 2P'), + (TYPE_TERA1P, 'TERA 1P'), (TYPE_110_PUNCH, '110 Punch'), (TYPE_BNC, 'BNC'), (TYPE_MRJ21, 'MRJ21'), @@ -936,6 +944,8 @@ class CableTypeChoices(ChoiceSet): TYPE_CAT6 = 'cat6' TYPE_CAT6A = 'cat6a' TYPE_CAT7 = 'cat7' + TYPE_CAT7A = 'cat7a' + TYPE_CAT8 = 'cat8' TYPE_DAC_ACTIVE = 'dac-active' TYPE_DAC_PASSIVE = 'dac-passive' TYPE_MRJ21_TRUNK = 'mrj21-trunk' @@ -960,6 +970,8 @@ class CableTypeChoices(ChoiceSet): (TYPE_CAT6, 'CAT6'), (TYPE_CAT6A, 'CAT6a'), (TYPE_CAT7, 'CAT7'), + (TYPE_CAT7A, 'CAT7a'), + (TYPE_CAT8, 'CAT8'), (TYPE_DAC_ACTIVE, 'Direct Attach Copper (Active)'), (TYPE_DAC_PASSIVE, 'Direct Attach Copper (Passive)'), (TYPE_MRJ21_TRUNK, 'MRJ21 Trunk'), From 69bf451b209087b7a4025571c816551eee47538a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 19 Jan 2021 09:41:49 -0500 Subject: [PATCH 08/30] Changelog for #5586 and #5612 --- docs/release-notes/version-2.10.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 870a11890..63eec8083 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -5,6 +5,8 @@ ### Enhancements * [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list +* [#5586](https://github.com/netbox-community/netbox/issues/5586) - Allow filtering virtual chassis by name and master +* [#5612](https://github.com/netbox-community/netbox/issues/5612) - Add GG45 and TERA port types, and CAT7a and CAT8 cable types ### Bug Fixes From a0e82e181701159012882c6ba1378a6b2f3453e1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 19 Jan 2021 10:49:56 -0500 Subject: [PATCH 09/30] Fixes #5574: Restrict the creation of device bay templates on non-parent device types --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/models/device_component_templates.py | 6 ++++++ netbox/dcim/tests/test_api.py | 5 ++++- netbox/dcim/tests/test_views.py | 5 +++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 63eec8083..a653173f9 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -10,6 +10,7 @@ ### Bug Fixes +* [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index 58233f3bf..e52fe2602 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -363,3 +363,9 @@ class DeviceBayTemplate(ComponentTemplateModel): name=self.name, label=self.label ) + + def clean(self): + if self.device_type and self.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT: + raise ValidationError( + f"Subdevice role of device type ({self.device_type}) must be set to \"parent\" to allow device bays." + ) diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index 77c3b4786..ad1ca930c 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -740,7 +740,10 @@ class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase): def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1') devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' + manufacturer=manufacturer, + model='Device Type 1', + slug='device-type-1', + subdevice_role=SubdeviceRoleChoices.ROLE_PARENT ) device_bay_templates = ( diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 91ec8776c..86518af84 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -396,6 +396,7 @@ manufacturer: Generic model: TEST-1000 slug: test-1000 u_height: 2 +subdevice_role: parent comments: test comment console-ports: - name: Console Port 1 @@ -831,8 +832,8 @@ class DeviceBayTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') devicetypes = ( - DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'), - DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'), + DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1', subdevice_role=SubdeviceRoleChoices.ROLE_PARENT), + DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2', subdevice_role=SubdeviceRoleChoices.ROLE_PARENT), ) DeviceType.objects.bulk_create(devicetypes) From 3c9be8cd0806c29445310e01957ab09afbe24818 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 19 Jan 2021 11:24:34 -0500 Subject: [PATCH 10/30] Fixes #5639: Fix filtering connection lists by device name --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/filters.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index a653173f9..f3cf87764 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -13,6 +13,7 @@ * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address +* [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name --- diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 05ae08923..03deca2a4 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -1152,7 +1152,7 @@ class ConnectionFilterSet: def filter_device(self, queryset, name, value): if not value: return queryset - return queryset.filter(device_id__in=value) + return queryset.filter(**{f'{name}__in': value}) class ConsoleConnectionFilterSet(ConnectionFilterSet, BaseFilterSet): From f469920759f8711c8443de9ee0892e042a895fd3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 15:18:13 -0500 Subject: [PATCH 11/30] Fixes #5640: Fix permissions assessment when adding VM interfaces in bulk --- docs/release-notes/version-2.10.md | 1 + netbox/templates/virtualization/virtualmachine_list.html | 2 +- netbox/virtualization/views.py | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index f3cf87764..0ef5f2a0f 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -14,6 +14,7 @@ * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name +* [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk --- diff --git a/netbox/templates/virtualization/virtualmachine_list.html b/netbox/templates/virtualization/virtualmachine_list.html index 9d8c1720f..245e55092 100644 --- a/netbox/templates/virtualization/virtualmachine_list.html +++ b/netbox/templates/virtualization/virtualmachine_list.html @@ -7,7 +7,7 @@ Add Components
{% endif %} diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index 9ef4a0863..dcf9ebcda 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -396,3 +396,6 @@ class VirtualMachineBulkAddInterfaceView(generic.BulkComponentCreateView): model_form = forms.VMInterfaceForm filterset = filters.VirtualMachineFilterSet table = tables.VirtualMachineTable + + def get_required_permission(self): + return f'virtualization.add_vminterface' From 0994719b9124cfc10626598eebb7cee459903d2a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 15:36:04 -0500 Subject: [PATCH 12/30] Add NetBox installation video to docs --- docs/installation/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/installation/index.md b/docs/installation/index.md index 730176e0c..71e669295 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -11,6 +11,10 @@ The following sections detail how to set up a new instance of NetBox: 5. [HTTP server](5-http-server.md) 6. [LDAP authentication](6-ldap.md) (optional) +The video below demonstrates the installation of NetBox v2.10.3 on Ubuntu 20.04 for your reference. + + + ## Requirements | Dependency | Minimum Version | From e739d6aa057750d17af01d4f9b772027d47183c5 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Wed, 20 Jan 2021 23:52:54 +0000 Subject: [PATCH 13/30] Fix white cables --- netbox/templates/dcim/trace/cable.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/templates/dcim/trace/cable.html b/netbox/templates/dcim/trace/cable.html index 4235768a6..7a7fbcf55 100644 --- a/netbox/templates/dcim/trace/cable.html +++ b/netbox/templates/dcim/trace/cable.html @@ -1,6 +1,6 @@ {% load helpers %} -
+
{% if cable.label %}{{ cable.label }}{% else %}Cable #{{ cable.pk }}{% endif %} From fefc6233436a3df4d2b106aac4f7d059aae6f951 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 20:48:24 -0500 Subject: [PATCH 14/30] Changelog for #5603 --- 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 0ef5f2a0f..16d48dba7 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -13,6 +13,7 @@ * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address +* [#5603](https://github.com/netbox-community/netbox/issues/5603) - Fix display of white cables in trace view * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name * [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk From 5e962719ca84a250f24d61a5d999e9e6c8e91ad0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Jan 2021 21:29:23 -0500 Subject: [PATCH 15/30] Closes #5542: Show cable trace lengths in both meters and feet --- docs/release-notes/version-2.10.md | 1 + netbox/templates/dcim/cable_trace.html | 3 ++- netbox/utilities/templatetags/helpers.py | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 16d48dba7..27d9fef49 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -4,6 +4,7 @@ ### Enhancements +* [#5542](https://github.com/netbox-community/netbox/issues/5542) - Show cable trace lengths in both meters and feet * [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list * [#5586](https://github.com/netbox-community/netbox/issues/5586) - Allow filtering virtual chassis by name and master * [#5612](https://github.com/netbox-community/netbox/issues/5612) - Add GG45 and TERA port types, and CAT7a and CAT8 cable types diff --git a/netbox/templates/dcim/cable_trace.html b/netbox/templates/dcim/cable_trace.html index a36922612..a39ada1ce 100644 --- a/netbox/templates/dcim/cable_trace.html +++ b/netbox/templates/dcim/cable_trace.html @@ -69,7 +69,8 @@
Total segments: {{ traced_path|length }}
Total length: {% if total_length %} - {{ total_length|floatformat:"-2" }} Meters + {{ total_length|floatformat:"-2" }} Meters / + {{ total_length|meters_to_feet|floatformat:"-2" }} Feet {% else %} N/A {% endif %} diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index 29c920d4f..01dce8479 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -220,6 +220,14 @@ def as_range(n): return range(n) +@register.filter() +def meters_to_feet(n): + """ + Convert a length from meters to feet. + """ + return float(n) * 3.28084 + + # # Tags # From 3de04094fb4f5f53ed5319d831e099e135a2446b Mon Sep 17 00:00:00 2001 From: Riley Littlefield Date: Sat, 23 Jan 2021 13:41:48 -0500 Subject: [PATCH 16/30] Fixes typo --- docs/configuration/required-settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/required-settings.md b/docs/configuration/required-settings.md index 2edf6c7c7..f03745930 100644 --- a/docs/configuration/required-settings.md +++ b/docs/configuration/required-settings.md @@ -5,7 +5,7 @@ This is a list of valid fully-qualified domain names (FQDNs) and/or IP addresses that can be used to reach the NetBox service. Usually this is the same as the hostname for the NetBox server, but can also be different; for example, when using a reverse proxy serving the NetBox website under a different FQDN than the hostname of the NetBox server. To help guard against [HTTP Host header attackes](https://docs.djangoproject.com/en/3.0/topics/security/#host-headers-virtual-hosting), NetBox will not permit access to the server via any other hostnames (or IPs). !!! note - This parameter must always be defined as a list or tuple, even if only value is provided. + This parameter must always be defined as a list or tuple, even if only a single value is provided. The value of this option is also used to set `CSRF_TRUSTED_ORIGINS`, which restricts POST requests to the same set of hosts (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-CSRF_TRUSTED_ORIGINS)). Keep in mind that NetBox, by default, sets `USE_X_FORWARDED_HOST` to true, which means that if you're using a reverse proxy, it's the FQDN used to reach that reverse proxy which needs to be in this list (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#allowed-hosts)). From 9eb64dc6a47ba6400b92e02125bd0251b7bf74e1 Mon Sep 17 00:00:00 2001 From: Riley Littlefield Date: Sat, 23 Jan 2021 13:54:44 -0500 Subject: [PATCH 17/30] Fixes another typo --- docs/configuration/required-settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/required-settings.md b/docs/configuration/required-settings.md index f03745930..dba8cdc8c 100644 --- a/docs/configuration/required-settings.md +++ b/docs/configuration/required-settings.md @@ -101,7 +101,7 @@ REDIS = { If you are using [Redis Sentinel](https://redis.io/topics/sentinel) for high-availability purposes, there is minimal configuration necessary to convert NetBox to recognize it. It requires the removal of the `HOST` and `PORT` keys from -above and the addition of two new keys. +above and the addition of three new keys. * `SENTINELS`: List of tuples or tuple of tuples with each inner tuple containing the name or IP address of the Redis server and port for each sentinel instance to connect to From 60baa5e59e1d5f3f71f1cb8c051c700dc27ba5c6 Mon Sep 17 00:00:00 2001 From: Riley Littlefield Date: Sat, 23 Jan 2021 14:06:48 -0500 Subject: [PATCH 18/30] Fixes small typo in optional settings --- docs/configuration/optional-settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index 91c0e7597..4af83493e 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -56,7 +56,7 @@ BASE_PATH = 'netbox/' Default: 900 -The number of seconds to cache entries will be retained before expiring. +The number of seconds that cache entries will be retained before expiring. --- From b6e532f01d852738f40eb8bedc89f5c056b2f62c Mon Sep 17 00:00:00 2001 From: Thomas Fargeix Date: Sun, 24 Jan 2021 21:20:55 +0100 Subject: [PATCH 19/30] Fix how SECRET_KEY is generated Use secrets.choice instead of random.sample to generate the secret key. --- netbox/generate_secret_key.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/netbox/generate_secret_key.py b/netbox/generate_secret_key.py index 3c88aa710..c3de29cee 100755 --- a/netbox/generate_secret_key.py +++ b/netbox/generate_secret_key.py @@ -1,7 +1,6 @@ #!/usr/bin/env python # This script will generate a random 50-character string suitable for use as a SECRET_KEY. -import random +import secrets charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(-_=+)' -secure_random = random.SystemRandom() -print(''.join(secure_random.sample(charset, 50))) +print(''.join(secrets.choice(charset) for _ in range(50))) From 87c600aa7cc3da60019a34b2c75162baefa4e40f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 25 Jan 2021 14:19:32 -0500 Subject: [PATCH 20/30] Fixes #5665: Validate rack group is assigned to same site when creating a rack --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/models/racks.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 27d9fef49..98595ff4a 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -17,6 +17,7 @@ * [#5603](https://github.com/netbox-community/netbox/issues/5603) - Fix display of white cables in trace view * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name * [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk +* [#5665](https://github.com/netbox-community/netbox/issues/5665) - Validate rack group is assigned to same site when creating a rack --- diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index ccc775954..dfaf7da61 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -299,6 +299,10 @@ class Rack(ChangeLoggedModel, CustomFieldModel): def clean(self): super().clean() + # Validate group/site assignment + if self.site and self.group and self.group.site != self.site: + raise ValidationError(f"Assigned rack group must belong to parent site ({self.site}).") + # Validate outer dimensions and unit if (self.outer_width is not None or self.outer_depth is not None) and not self.outer_unit: raise ValidationError("Must specify a unit when setting an outer width/depth") From 137aa9da2c2e71b352c287341bfcdd80d56d706c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 25 Jan 2021 14:29:03 -0500 Subject: [PATCH 21/30] Fixes #5648: Include VC member interfaces on interfaces tab count when viewing VC master --- docs/release-notes/version-2.10.md | 1 + netbox/templates/dcim/device/base.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 98595ff4a..05b48a896 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -17,6 +17,7 @@ * [#5603](https://github.com/netbox-community/netbox/issues/5603) - Fix display of white cables in trace view * [#5639](https://github.com/netbox-community/netbox/issues/5639) - Fix filtering connection lists by device name * [#5640](https://github.com/netbox-community/netbox/issues/5640) - Fix permissions assessment when adding VM interfaces in bulk +* [#5648](https://github.com/netbox-community/netbox/issues/5648) - Include VC member interfaces on interfaces tab count when viewing VC master * [#5665](https://github.com/netbox-community/netbox/issues/5665) - Validate rack group is assigned to same site when creating a rack --- diff --git a/netbox/templates/dcim/device/base.html b/netbox/templates/dcim/device/base.html index 631abde89..8f488b284 100644 --- a/netbox/templates/dcim/device/base.html +++ b/netbox/templates/dcim/device/base.html @@ -90,7 +90,7 @@ - {% with interface_count=object.interfaces.count %} + {% with interface_count=object.vc_interfaces.count %} {% if interface_count %}
- {% with rack=object.rack %} -
-
-
-

Front

-
- {% include 'dcim/inc/rack_elevation.html' with face='front' %} -
-
-
-

Rear

-
- {% include 'dcim/inc/rack_elevation.html' with face='rear' %} +
+
+
+

Front

+ {% include 'dcim/inc/rack_elevation.html' with object=object.rack face='front' %}
- {% endwith %} +
+
+

Rear

+
+ {% include 'dcim/inc/rack_elevation.html' with object=object.rack face='rear' %} +
+
{% plugin_right_page object %}
From 90e8f26cd4e34d9ea3364fa15a961f47298d0e05 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 10:17:58 -0500 Subject: [PATCH 23/30] Closes #5678: Show available type choices for all device component import forms --- docs/release-notes/version-2.10.md | 1 + netbox/dcim/forms.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 1d954d383..02897b614 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -8,6 +8,7 @@ * [#5570](https://github.com/netbox-community/netbox/issues/5570) - Add "management only" filter widget for interfaces list * [#5586](https://github.com/netbox-community/netbox/issues/5586) - Allow filtering virtual chassis by name and master * [#5612](https://github.com/netbox-community/netbox/issues/5612) - Add GG45 and TERA port types, and CAT7a and CAT8 cable types +* [#5678](https://github.com/netbox-community/netbox/issues/5678) - Show available type choices for all device component import forms ### Bug Fixes diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 18fdbdb40..fd533b6ac 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2352,6 +2352,10 @@ class ConsolePortCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=ConsolePortTypeChoices, + help_text='Port type' + ) class Meta: model = ConsolePort @@ -2425,6 +2429,10 @@ class ConsoleServerPortCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=ConsolePortTypeChoices, + help_text='Port type' + ) class Meta: model = ConsoleServerPort @@ -2510,6 +2518,10 @@ class PowerPortCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=PowerPortTypeChoices, + help_text='Port type' + ) class Meta: model = PowerPort @@ -2630,6 +2642,10 @@ class PowerOutletCSVForm(CSVModelForm): queryset=Device.objects.all(), to_field_name='name' ) + type = CSVChoiceField( + choices=PowerOutletTypeChoices, + help_text='Outlet type' + ) power_port = CSVModelChoiceField( queryset=PowerPort.objects.all(), required=False, From d5a0e12283d4dadf8b36f4826faeeafe4cccb2a5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 10:35:03 -0500 Subject: [PATCH 24/30] Certain component types are optional --- netbox/dcim/forms.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index fd533b6ac..40c16d59f 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2354,6 +2354,7 @@ class ConsolePortCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=ConsolePortTypeChoices, + required=False, help_text='Port type' ) @@ -2431,6 +2432,7 @@ class ConsoleServerPortCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=ConsolePortTypeChoices, + required=False, help_text='Port type' ) @@ -2520,6 +2522,7 @@ class PowerPortCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=PowerPortTypeChoices, + required=False, help_text='Port type' ) @@ -2644,6 +2647,7 @@ class PowerOutletCSVForm(CSVModelForm): ) type = CSVChoiceField( choices=PowerOutletTypeChoices, + required=False, help_text='Outlet type' ) power_port = CSVModelChoiceField( From edc015d9bf1312f0925d17ccdd7590c44045859e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 11:20:06 -0500 Subject: [PATCH 25/30] Emphasize use of GitHub discussions in README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 68927463d..a12daa783 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,7 @@ complete list of requirements, see `requirements.txt`. The code is available [on The complete documentation for NetBox can be found at [Read the Docs](https://netbox.readthedocs.io/en/stable/). -Questions? Comments? Please start a [discussion on GitHub](https://github.com/netbox-community/netbox/discussions), -or join us in the **#netbox** Slack channel on [NetworkToCode](https://networktocode.slack.com/)! +Questions? Comments? Start by perusing our [GitHub discussions](https://github.com/netbox-community/netbox/discussions) for the topic you have in mind. ### Build Status From a23ff4e5191836005ee59f8484641c6043b0ef8f Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 26 Jan 2021 10:34:07 -0600 Subject: [PATCH 26/30] Fixes: #5232 - Corrects swagger definition --- 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 02897b614..9be3f22d1 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -12,6 +12,7 @@ ### Bug Fixes +* [#5232](https://github.com/netbox-community/netbox/issues/5232) - Correct swagger definition for ip_prefixes_available-ips_create API * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address From aabc1a82655ad680e99c76ef1b86280e8cb97170 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 26 Jan 2021 10:34:07 -0600 Subject: [PATCH 27/30] Fixes: #5232 - Corrects swagger definition --- docs/release-notes/version-2.10.md | 1 + netbox/ipam/api/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 02897b614..9be3f22d1 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -12,6 +12,7 @@ ### Bug Fixes +* [#5232](https://github.com/netbox-community/netbox/issues/5232) - Correct swagger definition for ip_prefixes_available-ips_create API * [#5574](https://github.com/netbox-community/netbox/issues/5574) - Restrict the creation of device bay templates on non-parent device types * [#5584](https://github.com/netbox-community/netbox/issues/5584) - Restore power utilization panel under device view * [#5597](https://github.com/netbox-community/netbox/issues/5597) - Fix ordering devices by primary IP address diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index d9eae69aa..c322c249d 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -178,7 +178,7 @@ class PrefixViewSet(CustomFieldModelViewSet): @swagger_auto_schema(method='get', responses={200: serializers.AvailableIPSerializer(many=True)}) @swagger_auto_schema(method='post', responses={201: serializers.AvailableIPSerializer(many=True)}, - request_body=serializers.AvailableIPSerializer(many=False)) + request_body=serializers.AvailableIPSerializer(many=True)) @action(detail=True, url_path='available-ips', methods=['get', 'post'], queryset=IPAddress.objects.all()) @advisory_lock(ADVISORY_LOCK_KEYS['available-ips']) def available_ips(self, request, pk=None): From 0680b01a96e3ed2cec2b377e5831603eb4ffc534 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 26 Jan 2021 11:47:33 -0600 Subject: [PATCH 28/30] update python package name At least on ubuntu 20.04, the python3 package is now 3.8, but the package 'python3' points to the current best version of python available without needing to specialize a minor version and should require fewer changes to the document. --- docs/installation/3-netbox.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/3-netbox.md b/docs/installation/3-netbox.md index 9745df1f3..7698be4ad 100644 --- a/docs/installation/3-netbox.md +++ b/docs/installation/3-netbox.md @@ -12,7 +12,7 @@ Begin by installing all system packages required by NetBox and its dependencies. ### Ubuntu ```no-highlight -sudo apt install -y python3.6 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev +sudo apt install -y python3 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev ``` ### CentOS From 03e48161a152ed0c6029b1834a7dc44c55f98fcc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 26 Jan 2021 13:06:29 -0500 Subject: [PATCH 29/30] Release v2.10.4 --- 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 9be3f22d1..b6bc33229 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.4 (FUTURE) +## v2.10.4 (2021-01-26) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index ed1f9c732..3dd780b26 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.4-dev' +VERSION = '2.10.4' # Hostname HOSTNAME = platform.node() From fc8f02c180dc8dd9ec6d6b3226432382f22e6f69 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Tue, 26 Jan 2021 14:03:46 -0600 Subject: [PATCH 30/30] Corrects error with ListSerializer as request_body --- netbox/utilities/custom_inspectors.py | 51 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/netbox/utilities/custom_inspectors.py b/netbox/utilities/custom_inspectors.py index 95c647fb8..b110a9123 100644 --- a/netbox/utilities/custom_inspectors.py +++ b/netbox/utilities/custom_inspectors.py @@ -28,29 +28,38 @@ class NetBoxSwaggerAutoSchema(SwaggerAutoSchema): serializer = super().get_request_serializer() if serializer is not None and self.method in self.implicit_body_methods: - properties = {} - for child_name, child in serializer.fields.items(): - if isinstance(child, (ChoiceField, WritableNestedSerializer)): - properties[child_name] = None - elif isinstance(child, ManyRelatedField) and isinstance(child.child_relation, SerializedPKRelatedField): - properties[child_name] = None - - if properties: - if type(serializer) not in self.writable_serializers: - writable_name = 'Writable' + type(serializer).__name__ - meta_class = getattr(type(serializer), 'Meta', None) - if meta_class: - ref_name = 'Writable' + get_serializer_ref_name(serializer) - writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name}) - properties['Meta'] = writable_meta - - self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties) - - writable_class = self.writable_serializers[type(serializer)] - serializer = writable_class() - + writable_class = self.get_writable_class(serializer) + if writable_class is not None: + if hasattr(serializer, 'child'): + child_serializer = self.get_writable_class(serializer.child) + serializer = writable_class(child=child_serializer) + else: + serializer = writable_class() return serializer + def get_writable_class(self, serializer): + properties = {} + fields = {} if hasattr(serializer, 'child') else serializer.fields + for child_name, child in fields.items(): + if isinstance(child, (ChoiceField, WritableNestedSerializer)): + properties[child_name] = None + elif isinstance(child, ManyRelatedField) and isinstance(child.child_relation, SerializedPKRelatedField): + properties[child_name] = None + + if properties: + if type(serializer) not in self.writable_serializers: + writable_name = 'Writable' + type(serializer).__name__ + meta_class = getattr(type(serializer), 'Meta', None) + if meta_class: + ref_name = 'Writable' + get_serializer_ref_name(serializer) + writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name}) + properties['Meta'] = writable_meta + + self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties) + + writable_class = self.writable_serializers[type(serializer)] + return writable_class + class SerializedPKRelatedFieldInspector(FieldInspector): def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):