diff --git a/CHANGELOG.md b/CHANGELOG.md index b8c1e29da..05708bea1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,9 @@ the Config Context from being included in any results. ### Tag Permissions Changed -NetBox now makes use of its own `Tag` model instead of the vanilla model which ships with django-taggit. This new model lives in the `extras` app and thus any permissions that you may have configured using "Taggit | Tag" should be changed to now use "Extras | Tag." +NetBox now makes use of its own `Tag` model instead of the vanilla model which ships with django-taggit. This new model +lives in the `extras` app and thus any permissions that you may have configured using "Taggit | Tag" should be changed +to now use "Extras | Tag." ## Enhancements @@ -23,22 +25,31 @@ NetBox now makes use of its own `Tag` model instead of the vanilla model which s --- -v2.5.7 (FUTURE) +v2.5.7 (2019-02-21) ## Enhancements * [#2357](https://github.com/digitalocean/netbox/issues/2357) - Enable filtering of devices by rack face +* [#2638](https://github.com/digitalocean/netbox/issues/2638) - Add button to copy unlocked secret to clipboard +* [#2870](https://github.com/digitalocean/netbox/issues/2870) - Add Markdown rendering for provider NOC/admin contact fields * [#2878](https://github.com/digitalocean/netbox/issues/2878) - Add cable types for OS1/OS2 singlemode fiber +* [#2890](https://github.com/digitalocean/netbox/issues/2890) - Add port types for APC fiber +* [#2898](https://github.com/digitalocean/netbox/issues/2898) - Enable filtering cables list by connection status * [#2903](https://github.com/digitalocean/netbox/issues/2903) - Clarify purpose of tags field on interface edit form ## Bug Fixes +* [#2852](https://github.com/digitalocean/netbox/issues/2852) - Allow filtering devices by null rack position * [#2884](https://github.com/digitalocean/netbox/issues/2884) - Don't display connect button for wireless interfaces * [#2888](https://github.com/digitalocean/netbox/issues/2888) - Correct foreground color of device roles in rack elevations * [#2893](https://github.com/digitalocean/netbox/issues/2893) - Remove duplicate display of VRF RD on IP address view * [#2895](https://github.com/digitalocean/netbox/issues/2895) - Fix filtering of nullable character fields * [#2901](https://github.com/digitalocean/netbox/issues/2901) - Fix ordering regions by site count * [#2910](https://github.com/digitalocean/netbox/issues/2910) - Fix config context list and edit forms to use Select2 elements +* [#2912](https://github.com/digitalocean/netbox/issues/2912) - Cable type in filter form should be blank by default +* [#2913](https://github.com/digitalocean/netbox/issues/2913) - Fix assigned prefixes link on VRF view +* [#2914](https://github.com/digitalocean/netbox/issues/2914) - Fix empty connected circuit link on device interfaces list +* [#2915](https://github.com/digitalocean/netbox/issues/2915) - Fix bulk editing of pass-through ports v2.5.6 (2019-02-13) diff --git a/docs/additional-features/reports.md b/docs/additional-features/reports.md index 2c73850eb..33c3d95ae 100644 --- a/docs/additional-features/reports.md +++ b/docs/additional-features/reports.md @@ -128,4 +128,4 @@ Reports can be run on the CLI by invoking the management command: python3 manage.py runreport ``` -One or more report modules may be specified. +where ```` is the name of the python file in the ``reports`` directory without the ``.py`` extension. One or more report modules may be specified. diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 75a18e36f..0b81e68bf 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -43,6 +43,12 @@ RACK_STATUS_CHOICES = [ [RACK_STATUS_DEPRECATED, 'Deprecated'], ] +# Device rack position +DEVICE_POSITION_CHOICES = [ + # Rack.u_height is limited to 100 + (i, 'Unit {}'.format(i)) for i in range(1, 101) +] + # Parent/child device roles SUBDEVICE_ROLE_PARENT = True SUBDEVICE_ROLE_CHILD = False @@ -270,11 +276,14 @@ PORT_TYPE_8P8C = 1000 PORT_TYPE_110_PUNCH = 1100 PORT_TYPE_ST = 2000 PORT_TYPE_SC = 2100 +PORT_TYPE_SC_APC = 2110 PORT_TYPE_FC = 2200 PORT_TYPE_LC = 2300 +PORT_TYPE_LC_APC = 2310 PORT_TYPE_MTRJ = 2400 PORT_TYPE_MPO = 2500 PORT_TYPE_LSH = 2600 +PORT_TYPE_LSH_APC = 2610 PORT_TYPE_CHOICES = [ [ 'Copper', @@ -288,10 +297,13 @@ PORT_TYPE_CHOICES = [ [ [PORT_TYPE_FC, 'FC'], [PORT_TYPE_LC, 'LC'], + [PORT_TYPE_LC_APC, 'LC/APC'], [PORT_TYPE_LSH, 'LSH'], + [PORT_TYPE_LSH_APC, 'LSH/APC'], [PORT_TYPE_MPO, 'MPO'], [PORT_TYPE_MTRJ, 'MTRJ'], [PORT_TYPE_SC, 'SC'], + [PORT_TYPE_SC_APC, 'SC/APC'], [PORT_TYPE_ST, 'ST'], ] ] diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 4b22b2002..1307d6155 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -543,6 +543,10 @@ class DeviceFilter(CustomFieldFilterSet): queryset=Rack.objects.all(), label='Rack (ID)', ) + position = django_filters.ChoiceFilter( + choices=DEVICE_POSITION_CHOICES, + null_label='Non-racked' + ) cluster_id = django_filters.ModelMultipleChoiceFilter( queryset=Cluster.objects.all(), label='VM cluster (ID)', @@ -602,7 +606,7 @@ class DeviceFilter(CustomFieldFilterSet): class Meta: model = Device - fields = ['serial', 'position', 'face'] + fields = ['serial', 'face'] def search(self, queryset, name, value): if not value.strip(): diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 18627c2f5..ab3da181f 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2410,7 +2410,7 @@ class FrontPortCreateForm(ComponentForm): class FrontPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): pk = forms.ModelMultipleChoiceField( - queryset=Interface.objects.all(), + queryset=FrontPort.objects.all(), widget=forms.MultipleHiddenInput() ) type = forms.ChoiceField( @@ -2484,7 +2484,7 @@ class RearPortCreateForm(ComponentForm): class RearPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): pk = forms.ModelMultipleChoiceField( - queryset=Interface.objects.all(), + queryset=RearPort.objects.all(), widget=forms.MultipleHiddenInput() ) type = forms.ChoiceField( @@ -2801,10 +2801,15 @@ class CableFilterForm(BootstrapMixin, forms.Form): label='Search' ) type = forms.MultipleChoiceField( - choices=CABLE_TYPE_CHOICES, + choices=add_blank_choice(CABLE_TYPE_CHOICES), required=False, widget=StaticSelect2() ) + status = forms.ChoiceField( + required=False, + choices=add_blank_choice(CONNECTION_STATUS_CHOICES), + widget=StaticSelect2() + ) color = forms.CharField( max_length=6, required=False, diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index b7675b34e..7fb789235 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -2644,6 +2644,9 @@ class Cable(ChangeLoggedModel): self.length_unit, ) + def get_status_class(self): + return 'success' if self.status else 'info' + def get_path_endpoints(self): """ Traverse both ends of a cable path and return its connected endpoints. Note that one or both endpoints may be diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index 3cbd9378d..5649c10ef 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -647,6 +647,9 @@ class CableTable(BaseTable): orderable=False, verbose_name='' ) + status = tables.TemplateColumn( + template_code=STATUS_LABEL + ) length = tables.TemplateColumn( template_code=CABLE_LENGTH, order_by='_abs_length' diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 07d46bad3..a85a5d78e 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -22,7 +22,7 @@ except ImportError: ) -VERSION = '2.5.7-dev' +VERSION = '2.5.8-dev' BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/netbox/project-static/clipboard-2.0.4.min.js b/netbox/project-static/clipboard-2.0.4.min.js new file mode 100755 index 000000000..02c549e35 --- /dev/null +++ b/netbox/project-static/clipboard-2.0.4.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.4 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n +