From 93c95fdfa85b1abaf4ba20e8979e3ee40e08df1f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 10 Dec 2018 10:29:51 -0500 Subject: [PATCH 01/17] Post-release version bump --- 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 6321ae98b..6ba964053 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -22,7 +22,7 @@ except ImportError: ) -VERSION = '2.5.0' +VERSION = '2.5.1-dev' BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) From b697c30941137f7d0a28d7aa14d52e880a006090 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 11 Dec 2018 11:15:45 -0500 Subject: [PATCH 02/17] #2627: Removed reference to provider from Circuit.__str__() --- netbox/circuits/models.py | 2 +- .../circuits/circuittermination_edit.html | 2 +- .../templates/dcim/inc/cable_termination.html | 2 +- .../templates/dcim/inc/cable_trace_end.html | 5 +-- netbox/templates/dcim/inc/interface.html | 36 +++++++++++++++---- netbox/templates/dcim/interface.html | 4 +++ 6 files changed, 39 insertions(+), 12 deletions(-) diff --git a/netbox/circuits/models.py b/netbox/circuits/models.py index 776b24156..f10221b0b 100644 --- a/netbox/circuits/models.py +++ b/netbox/circuits/models.py @@ -176,7 +176,7 @@ class Circuit(ChangeLoggedModel, CustomFieldModel): unique_together = ['provider', 'cid'] def __str__(self): - return '{} {}'.format(self.provider, self.cid) + return self.cid def get_absolute_url(self): return reverse('circuits:circuit', args=[self.pk]) diff --git a/netbox/templates/circuits/circuittermination_edit.html b/netbox/templates/circuits/circuittermination_edit.html index 2bbc4695d..6b702c1dc 100644 --- a/netbox/templates/circuits/circuittermination_edit.html +++ b/netbox/templates/circuits/circuittermination_edit.html @@ -10,7 +10,7 @@ {% endfor %}
-

{% block title %}Circuit {{ obj.circuit }} - {{ form.term_side.value }} Side{% endblock %}

+

{% block title %}{{ obj.circuit.provider }} {{ obj.circuit }} - Side {{ form.term_side.value }}{% endblock %}

{% if form.non_field_errors %}
Errors
diff --git a/netbox/templates/dcim/inc/cable_termination.html b/netbox/templates/dcim/inc/cable_termination.html index e7b2891e7..48af97a0b 100644 --- a/netbox/templates/dcim/inc/cable_termination.html +++ b/netbox/templates/dcim/inc/cable_termination.html @@ -29,7 +29,7 @@ Circuit - {{ termination.circuit }} (Side {{ termination.term_side }}) + {{ termination.circuit }} ({{ termination }}) {% endif %} diff --git a/netbox/templates/dcim/inc/cable_trace_end.html b/netbox/templates/dcim/inc/cable_trace_end.html index 1ed12c877..3c5a7c7fc 100644 --- a/netbox/templates/dcim/inc/cable_trace_end.html +++ b/netbox/templates/dcim/inc/cable_trace_end.html @@ -5,7 +5,7 @@ {% if end.device %} {{ end.device }} {% else %} - {{ end.circuit }} + {{ end.circuit.provider }} {% endif %}
@@ -21,7 +21,8 @@ {% endwith %} {% else %} {# Circuit termination #} - Side {{ end.term_side }} + {{ end.circuit }}
+ {{ end }} {% endif %}
diff --git a/netbox/templates/dcim/inc/interface.html b/netbox/templates/dcim/inc/interface.html index f976d7f85..3d8057208 100644 --- a/netbox/templates/dcim/inc/interface.html +++ b/netbox/templates/dcim/inc/interface.html @@ -75,10 +75,16 @@ {% elif iface.connected_endpoint.name %} {# Connected to an Interface #} - {{ iface.connected_endpoint.device }} + + {{ iface.connected_endpoint.device }} + - {{ iface.connected_endpoint }} + + + {{ iface.connected_endpoint }} + + {% elif iface.connected_endpoint.term_side %} {# Connected to a CircuitTermination #} @@ -86,22 +92,38 @@ {% if peer_termination %} {% if peer_termination.connected_endpoint %} - {{ peer_termination.connected_endpoint.device }}
- via {{ iface.connected_endpoint.circuit }} + + {{ peer_termination.connected_endpoint.device }} +
+ via + + {{ iface.connected_endpoint.circuit.provider }} + {{ iface.connected_endpoint.circuit }} + + {{ peer_termination.connected_endpoint }} {% else %} - {{ peer_termination.site }} - via {{ iface.connected_endpoint.circuit }} + + {{ peer_termination.site }} + + via + + {{ iface.connected_endpoint.circuit.provider }} + {{ iface.connected_endpoint.circuit }} + {% endif %} {% else %} - {{ iface.connected_endpoint.circuit }} + + {{ iface.connected_endpoint.circuit.provider }} + {{ iface.connected_endpoint.circuit }} + {% endif %} {% endwith %} diff --git a/netbox/templates/dcim/interface.html b/netbox/templates/dcim/interface.html index 2ca17ac33..8625852e7 100644 --- a/netbox/templates/dcim/interface.html +++ b/netbox/templates/dcim/interface.html @@ -163,6 +163,10 @@ {% elif connected_circuittermination %} {% with ct=connected_circuittermination %} + + Provider + {{ ct.circuit.provider }} + Circuit {{ ct.circuit }} From b4f79f1667a2cb80e6e2ad1d5b1458263df57c9a Mon Sep 17 00:00:00 2001 From: dansheps Date: Tue, 11 Dec 2018 12:40:07 -0600 Subject: [PATCH 03/17] Fixes #2666: Uses correct function for displaying choices label * Changes record.length_type to record.get_length_type_display --- netbox/dcim/tables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index b38a60827..ba9035d19 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -179,7 +179,7 @@ CABLE_TERMINATION_PARENT = """ """ CABLE_LENGTH = """ -{% if record.length %}{{ record.length }}{{ record.length_unit }}{% else %}—{% endif %} +{% if record.length %}{{ record.length }}{{ record.get_length_unit_display }}{% else %}—{% endif %} """ From b8a4316297e0803e4261736a368c87146edddf1b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 11 Dec 2018 13:47:24 -0500 Subject: [PATCH 04/17] Changelog for #2666 --- CHANGELOG.md | 8 ++++++++ netbox/dcim/tables.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73f82845b..05cb5ccaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +v2.5.1 (FUTURE) + +## Bug Fixes + +* [#2666](https://github.com/digitalocean/netbox/issues/2666) - Correct display of length unit in cables list + +--- + v2.5.0 (2018-12-10) ## Notes diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index ba9035d19..0c88852f0 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -179,7 +179,7 @@ CABLE_TERMINATION_PARENT = """ """ CABLE_LENGTH = """ -{% if record.length %}{{ record.length }}{{ record.get_length_unit_display }}{% else %}—{% endif %} +{% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}—{% endif %} """ From 8364e56e867ae7e4fe9b67cf6fdb6264ee8e4c48 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 11 Dec 2018 17:00:20 -0500 Subject: [PATCH 05/17] Fixes #2676: Fix exception when passing dictionary value to a ChoiceField --- CHANGELOG.md | 1 + netbox/utilities/api.py | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05cb5ccaa..1f202fd34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ v2.5.1 (FUTURE) ## Bug Fixes * [#2666](https://github.com/digitalocean/netbox/issues/2666) - Correct display of length unit in cables list +* [#2676](https://github.com/digitalocean/netbox/issues/2676) - Fix exception when passing dictionary value to a ChoiceField --- diff --git a/netbox/utilities/api.py b/netbox/utilities/api.py index c24fd1a16..530372fb9 100644 --- a/netbox/utilities/api.py +++ b/netbox/utilities/api.py @@ -78,17 +78,26 @@ class ChoiceField(Field): return data def to_internal_value(self, data): + + # Provide an explicit error message if the request is trying to write a dict + if type(data) is dict: + raise ValidationError('Value must be passed directly (e.g. "foo": 123); do not use a dictionary.') + + # Check for string representations of boolean/integer values if hasattr(data, 'lower'): - # Hotwiring boolean values from string if data.lower() == 'true': - return True - if data.lower() == 'false': - return False - # Check for string representation of an integer (e.g. "123") - try: - data = int(data) - except ValueError: - pass + data = True + elif data.lower() == 'false': + data = False + else: + try: + data = int(data) + except ValueError: + pass + + if data not in self._choices: + raise ValidationError("{} is not a valid choice.".format(data)) + return data From b0a6781623117a362dcc8415eba36e3b096a24f6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 09:20:07 -0500 Subject: [PATCH 06/17] Fixes #2680: Disallow POST requests to /dcim/interface-connections/ API endpoint --- CHANGELOG.md | 1 + netbox/dcim/api/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f202fd34..c101eb96d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ v2.5.1 (FUTURE) * [#2666](https://github.com/digitalocean/netbox/issues/2666) - Correct display of length unit in cables list * [#2676](https://github.com/digitalocean/netbox/issues/2676) - Fix exception when passing dictionary value to a ChoiceField +* [#2680](https://github.com/digitalocean/netbox/issues/2680) - Disallow POST requests to `/dcim/interface-connections/` API endpoint --- diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 2c0032cb4..7e0179171 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -484,7 +484,7 @@ class PowerConnectionViewSet(ListModelMixin, GenericViewSet): filterset_class = filters.PowerConnectionFilter -class InterfaceConnectionViewSet(ModelViewSet): +class InterfaceConnectionViewSet(ListModelMixin, GenericViewSet): queryset = Interface.objects.select_related( 'device', '_connected_interface', '_connected_circuittermination' ).filter( From 6460c95e000c080cc7bd0c957d8d1485715c43c2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 09:30:31 -0500 Subject: [PATCH 07/17] Fixes #2678: Fix error when viewing webhook in admin UI without write permission --- CHANGELOG.md | 1 + netbox/extras/admin.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c101eb96d..e8cfa7aa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ v2.5.1 (FUTURE) * [#2666](https://github.com/digitalocean/netbox/issues/2666) - Correct display of length unit in cables list * [#2676](https://github.com/digitalocean/netbox/issues/2676) - Fix exception when passing dictionary value to a ChoiceField +* [#2678](https://github.com/digitalocean/netbox/issues/2678) - Fix error when viewing webhook in admin UI without write permission * [#2680](https://github.com/digitalocean/netbox/issues/2680) - Disallow POST requests to `/dcim/interface-connections/` API endpoint --- diff --git a/netbox/extras/admin.py b/netbox/extras/admin.py index e747bf71a..b4962dfd7 100644 --- a/netbox/extras/admin.py +++ b/netbox/extras/admin.py @@ -30,7 +30,8 @@ class WebhookForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - order_content_types(self.fields['obj_type']) + if 'obj_type' in self.fields: + order_content_types(self.fields['obj_type']) @admin.register(Webhook, site=admin_site) From ee038bd77b10365831d5c636f2768307f6c53d01 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 09:48:17 -0500 Subject: [PATCH 08/17] Closes #2655: Add 128GFC Fibrechannel interface type --- CHANGELOG.md | 4 ++++ netbox/dcim/constants.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8cfa7aa9..c87fe8043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ v2.5.1 (FUTURE) +## Enhancements + +* [#2655](https://github.com/digitalocean/netbox/issues/265) - Add 128GFC Fibrechannel interface type + ## Bug Fixes * [#2666](https://github.com/digitalocean/netbox/issues/2666) - Correct display of length unit in cables list diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 47a202893..8e5e09a26 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -103,6 +103,7 @@ IFACE_FF_4GFC_SFP = 3040 IFACE_FF_8GFC_SFP_PLUS = 3080 IFACE_FF_16GFC_SFP_PLUS = 3160 IFACE_FF_32GFC_SFP28 = 3320 +IFACE_FF_128GFC_QSFP28 = 3400 # Serial IFACE_FF_T1 = 4000 IFACE_FF_E1 = 4010 @@ -188,6 +189,7 @@ IFACE_FF_CHOICES = [ [IFACE_FF_8GFC_SFP_PLUS, 'SFP+ (8GFC)'], [IFACE_FF_16GFC_SFP_PLUS, 'SFP+ (16GFC)'], [IFACE_FF_32GFC_SFP28, 'SFP28 (32GFC)'], + [IFACE_FF_128GFC_QSFP28, 'QSFP28 (128GFC)'], ] ], [ From 3480832bf5f8be078243da28f04f5f279b636222 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 09:59:54 -0500 Subject: [PATCH 09/17] Added changelog for #2662 (fixed under #2680) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c87fe8043..8f29a09eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ v2.5.1 (FUTURE) ## Bug Fixes +* [#2662](https://github.com/digitalocean/netbox/issues/2662) - Fix ImproperlyConfigured exception when rendering API docs * [#2666](https://github.com/digitalocean/netbox/issues/2666) - Correct display of length unit in cables list * [#2676](https://github.com/digitalocean/netbox/issues/2676) - Fix exception when passing dictionary value to a ChoiceField * [#2678](https://github.com/digitalocean/netbox/issues/2678) - Fix error when viewing webhook in admin UI without write permission From 785cdcefd6da189f2809074d51c60430624e845f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 10:27:18 -0500 Subject: [PATCH 10/17] Closes #2671: Add documentation of API brief format --- docs/api/overview.md | 48 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/docs/api/overview.md b/docs/api/overview.md index 85d972008..1115759d8 100644 --- a/docs/api/overview.md +++ b/docs/api/overview.md @@ -104,7 +104,7 @@ The base serializer is used to represent the default view of a model. This inclu } ``` -Related objects (e.g. `ForeignKey` fields) are represented using a nested serializer. A nested serializer provides a minimal representation of an object, including only its URL and enough information to construct its name. When performing write api actions (`POST`, `PUT`, and `PATCH`), any `ForeignKey` relationships do not use the nested serializer, instead you will pass just the integer ID of the related model. +Related objects (e.g. `ForeignKey` fields) are represented using a nested serializer. A nested serializer provides a minimal representation of an object, including only its URL and enough information to construct its name. When performing write api actions (`POST`, `PUT`, and `PATCH`), any `ForeignKey` relationships do not use the nested serializer, instead you will pass just the integer ID of the related model. When a base serializer includes one or more nested serializers, the hierarchical structure precludes it from being used for write operations. Thus, a flat representation of an object may be provided using a writable serializer. This serializer includes only raw database values and is not typically used for retrieval, except as part of the response to the creation or updating of an object. @@ -122,6 +122,52 @@ When a base serializer includes one or more nested serializers, the hierarchical } ``` +## Brief Format + +Most API endpoints support an optional "brief" format, which returns only a minimal representation of each object in the response. This is useful when you need only a list of the objects themselves without any related data, such as when populating a drop-down list in a form. + +For example, the default (complete) format of an IP address looks like this: + +``` +GET /api/ipam/prefixes/13980/ + +{ + "id": 13980, + "family": 4, + "prefix": "192.0.2.0/24", + "site": null, + "vrf": null, + "tenant": null, + "vlan": null, + "status": { + "value": 1, + "label": "Active" + }, + "role": null, + "is_pool": false, + "description": "", + "tags": [], + "custom_fields": {}, + "created": "2018-12-11", + "last_updated": "2018-12-11T16:27:55.073174-05:00" +} +``` + +The brief format is much more terse, but includes a link to the object's full representation: + +``` +GET /api/ipam/prefixes/13980/?brief=1 + +{ + "id": 13980, + "url": "https://netbox/api/ipam/prefixes/13980/", + "family": 4, + "prefix": "192.0.2.0/24" +} +``` + +The brief format is supported for both lists and individual objects. + ## Static Choice Fields Some model fields, such as the `status` field in the above example, utilize static integers corresponding to static choices. The available choices can be retrieved from the read-only `_choices` endpoint within each app. A specific `model:field` tuple may optionally be specified in the URL. From 2418fed65ba0591ceb2060db5ee114c094cb65d1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 13:18:42 -0500 Subject: [PATCH 11/17] Fixes #2663: Prevent duplicate interfaces from appearing under VLAN members view --- CHANGELOG.md | 3 ++- netbox/ipam/models.py | 2 +- netbox/ipam/tables.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f29a09eb..75a9b09ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,12 @@ v2.5.1 (FUTURE) ## Enhancements -* [#2655](https://github.com/digitalocean/netbox/issues/265) - Add 128GFC Fibrechannel interface type +* [#2655](https://github.com/digitalocean/netbox/issues/2655) - Add 128GFC Fibrechannel interface type ## Bug Fixes * [#2662](https://github.com/digitalocean/netbox/issues/2662) - Fix ImproperlyConfigured exception when rendering API docs +* [#2663](https://github.com/digitalocean/netbox/issues/2663) - Prevent duplicate interfaces from appearing under VLAN members view * [#2666](https://github.com/digitalocean/netbox/issues/2666) - Correct display of length unit in cables list * [#2676](https://github.com/digitalocean/netbox/issues/2676) - Fix exception when passing dictionary value to a ChoiceField * [#2678](https://github.com/digitalocean/netbox/issues/2678) - Fix error when viewing webhook in admin UI without write permission diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index ca3f812a3..789e65b82 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -812,7 +812,7 @@ class VLAN(ChangeLoggedModel, CustomFieldModel): return Interface.objects.filter( Q(untagged_vlan_id=self.pk) | Q(tagged_vlans=self.pk) - ) + ).distinct() class Service(ChangeLoggedModel, CustomFieldModel): diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 284bcb4ae..026cbc980 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -430,7 +430,7 @@ class VLANDetailTable(VLANTable): class VLANMemberTable(BaseTable): parent = tables.LinkColumn(order_by=['device', 'virtual_machine']) - name = tables.Column(verbose_name='Interface') + name = tables.LinkColumn(verbose_name='Interface') untagged = tables.TemplateColumn( template_code=VLAN_MEMBER_UNTAGGED, orderable=False From edd763b1aae33e22f1869721748cf3b991d7f3e6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 16:06:50 -0500 Subject: [PATCH 12/17] Fixes #2684: Fix custom field filtering --- CHANGELOG.md | 1 + netbox/extras/filters.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75a9b09ff..1e8459076 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ v2.5.1 (FUTURE) * [#2676](https://github.com/digitalocean/netbox/issues/2676) - Fix exception when passing dictionary value to a ChoiceField * [#2678](https://github.com/digitalocean/netbox/issues/2678) - Fix error when viewing webhook in admin UI without write permission * [#2680](https://github.com/digitalocean/netbox/issues/2680) - Disallow POST requests to `/dcim/interface-connections/` API endpoint +* [#2684](https://github.com/digitalocean/netbox/issues/2684) - Fix custom field filtering --- diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index f3301a6cc..d0a801b48 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -31,12 +31,12 @@ class CustomFieldFilter(django_filters.Filter): # Treat 0 as None if int(value) == 0: return queryset.exclude( - custom_field_values__field__name=self.name, + custom_field_values__field__name=self.field_name, ) # Match on exact CustomFieldChoice PK else: return queryset.filter( - custom_field_values__field__name=self.name, + custom_field_values__field__name=self.field_name, custom_field_values__serialized_value=value, ) except ValueError: @@ -45,12 +45,12 @@ class CustomFieldFilter(django_filters.Filter): # Apply the assigned filter logic (exact or loose) if self.cf_type == CF_TYPE_BOOLEAN or self.filter_logic == CF_FILTER_EXACT: queryset = queryset.filter( - custom_field_values__field__name=self.name, + custom_field_values__field__name=self.field_name, custom_field_values__serialized_value=value ) else: queryset = queryset.filter( - custom_field_values__field__name=self.name, + custom_field_values__field__name=self.field_name, custom_field_values__serialized_value__icontains=value ) From 0d3b1bfca4fb2b6c9779e5cfe269f9d798e34c6b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Dec 2018 16:40:34 -0500 Subject: [PATCH 13/17] Fixes #2683: Fix exception when connecting a cable to a RearPort with no corresponding FrontPort --- CHANGELOG.md | 1 + netbox/dcim/models.py | 19 ++++++++++++------- netbox/dcim/signals.py | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e8459076..40acb31cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ v2.5.1 (FUTURE) * [#2676](https://github.com/digitalocean/netbox/issues/2676) - Fix exception when passing dictionary value to a ChoiceField * [#2678](https://github.com/digitalocean/netbox/issues/2678) - Fix error when viewing webhook in admin UI without write permission * [#2680](https://github.com/digitalocean/netbox/issues/2680) - Disallow POST requests to `/dcim/interface-connections/` API endpoint +* [#2683](https://github.com/digitalocean/netbox/issues/2683) - Fix exception when connecting a cable to a RearPort with no corresponding FrontPort * [#2684](https://github.com/digitalocean/netbox/issues/2684) - Fix custom field filtering --- diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 5dcf8a492..756ae9be2 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -110,11 +110,14 @@ class CableTermination(models.Model): raise Exception("Invalid position for {} ({} positions): {})".format( termination, termination.positions, position )) - peer_port = FrontPort.objects.get( - rear_port=termination, - rear_port_position=position, - ) - return peer_port, 1 + try: + peer_port = FrontPort.objects.get( + rear_port=termination, + rear_port_position=position, + ) + return peer_port, 1 + except ObjectDoesNotExist: + return None, None # Follow a circuit to its other termination elif isinstance(termination, CircuitTermination) and follow_circuits: @@ -2629,5 +2632,7 @@ class Cable(ChangeLoggedModel): path_status = CONNECTION_STATUS_PLANNED break - # (A path end, B path end, connected/planned) - return a_path[-1][2], b_path[-1][2], path_status + a_endpoint = a_path[-1][2] + b_endpoint = b_path[-1][2] + + return a_endpoint, b_endpoint, path_status diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index 2ac3bee06..f95ede579 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -37,7 +37,7 @@ def update_connected_endpoints(instance, **kwargs): # Check if this Cable has formed a complete path. If so, update both endpoints. endpoint_a, endpoint_b, path_status = instance.get_path_endpoints() - if endpoint_a is not None and endpoint_b is not None: + if hasattr(endpoint_a, 'connected_endpoint') and hasattr(endpoint_b, 'connected_endpoint'): endpoint_a.connected_endpoint = endpoint_b endpoint_a.connection_status = path_status endpoint_a.save() @@ -62,7 +62,7 @@ def nullify_connected_endpoints(instance, **kwargs): instance.termination_b.save() # If this Cable was part of a complete path, tear it down - if endpoint_a is not None and endpoint_b is not None: + if hasattr(endpoint_a, 'connected_endpoint') and hasattr(endpoint_b, 'connected_endpoint'): endpoint_a.connected_endpoint = None endpoint_a.connection_status = None endpoint_a.save() From a6c8c615ebb433ab07eadcc62c79cf9de8071c8c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 13 Dec 2018 14:35:26 -0500 Subject: [PATCH 14/17] Closes #2674: Enable filtering changelog by object type under web UI --- CHANGELOG.md | 1 + netbox/extras/forms.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40acb31cd..78753bc2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ v2.5.1 (FUTURE) ## Enhancements * [#2655](https://github.com/digitalocean/netbox/issues/2655) - Add 128GFC Fibrechannel interface type +* [#2674](https://github.com/digitalocean/netbox/issues/2674) - Enable filtering changelog by object type under web UI ## Bug Fixes diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index c0d6732d1..40d22aafb 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -11,7 +11,7 @@ from taggit.models import Tag from dcim.models import DeviceRole, Platform, Region, Site from tenancy.models import Tenant, TenantGroup from utilities.forms import ( - add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, FilterChoiceField, + add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ContentTypeSelect, FilterChoiceField, FilterTreeNodeMultipleChoiceField, LaxURLField, JSONField, SlugField, ) from .constants import ( @@ -307,7 +307,7 @@ class ImageAttachmentForm(BootstrapMixin, forms.ModelForm): # Change logging # -class ObjectChangeFilterForm(BootstrapMixin, CustomFieldFilterForm): +class ObjectChangeFilterForm(BootstrapMixin, forms.Form): model = ObjectChange q = forms.CharField( required=False, @@ -336,3 +336,9 @@ class ObjectChangeFilterForm(BootstrapMixin, CustomFieldFilterForm): queryset=User.objects.order_by('username'), required=False ) + changed_object_type = forms.ModelChoiceField( + queryset=ContentType.objects.order_by('model'), + required=False, + widget=ContentTypeSelect(), + label='Object Type' + ) From dd2a6a41dae5d3d2ff7c4f900cbf6af8204c7362 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 13 Dec 2018 14:43:05 -0500 Subject: [PATCH 15/17] Fixes #2687: Correct naming of before/after filters for changelog entries --- CHANGELOG.md | 1 + netbox/extras/forms.py | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78753bc2f..e4d69aa0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ v2.5.1 (FUTURE) * [#2680](https://github.com/digitalocean/netbox/issues/2680) - Disallow POST requests to `/dcim/interface-connections/` API endpoint * [#2683](https://github.com/digitalocean/netbox/issues/2683) - Fix exception when connecting a cable to a RearPort with no corresponding FrontPort * [#2684](https://github.com/digitalocean/netbox/issues/2684) - Fix custom field filtering +* [#2687](https://github.com/digitalocean/netbox/issues/2687) - Correct naming of before/after filters for changelog entries --- diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index 40d22aafb..3b7b26b66 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -313,15 +313,14 @@ class ObjectChangeFilterForm(BootstrapMixin, forms.Form): required=False, label='Search' ) - # TODO: Change time_0 and time_1 to time_after and time_before for django-filter==2.0 - time_0 = forms.DateTimeField( + time_after = forms.DateTimeField( label='After', required=False, widget=forms.TextInput( attrs={'placeholder': 'YYYY-MM-DD hh:mm:ss'} ) ) - time_1 = forms.DateTimeField( + time_before = forms.DateTimeField( label='Before', required=False, widget=forms.TextInput( From bb564363d55d5b8cc4a956911fe1b2dca33a3a32 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 13 Dec 2018 14:59:37 -0500 Subject: [PATCH 16/17] Fix regression from #2683 --- netbox/dcim/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index f95ede579..67479262b 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -37,7 +37,7 @@ def update_connected_endpoints(instance, **kwargs): # Check if this Cable has formed a complete path. If so, update both endpoints. endpoint_a, endpoint_b, path_status = instance.get_path_endpoints() - if hasattr(endpoint_a, 'connected_endpoint') and hasattr(endpoint_b, 'connected_endpoint'): + if endpoint_a is not None and endpoint_b is not None: endpoint_a.connected_endpoint = endpoint_b endpoint_a.connection_status = path_status endpoint_a.save() From 9f1fcca5ea43704b0e21fa46dea55c617ad83043 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 13 Dec 2018 15:03:08 -0500 Subject: [PATCH 17/17] Release v2.5.1 --- CHANGELOG.md | 2 +- netbox/netbox/settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4d69aa0c..02ca1bd7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -v2.5.1 (FUTURE) +v2.5.1 (2018-12-13) ## Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 6ba964053..49c619962 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -22,7 +22,7 @@ except ImportError: ) -VERSION = '2.5.1-dev' +VERSION = '2.5.1' BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))