From 37bc17d3a28ca1149cd2bded2213f877daadce99 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 2 Jan 2020 09:16:18 +0000 Subject: [PATCH 01/26] Fixes #2365: Toggle for showing available prefixes/ip addresses --- docs/release-notes/version-2.6.md | 1 + netbox/ipam/views.py | 29 ++++++++++++++++++++++++---- netbox/templates/ipam/aggregate.html | 8 ++++++++ netbox/templates/ipam/prefix.html | 8 ++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 548492438..f916f5083 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -2,6 +2,7 @@ ## Enhancements +* [#2365](https://github.com/netbox-community/netbox/issues/2365) - Toggle for showing available prefixes/ip addresses * [#3705](https://github.com/netbox-community/netbox/issues/3705) - Provide request context when executing custom scripts * [#3762](https://github.com/netbox-community/netbox/issues/3762) - Add date/time picker widgets * [#3788](https://github.com/netbox-community/netbox/issues/3788) - Enable partial search for inventory items diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 2cc1a0ea8..24d8efa82 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -333,7 +333,14 @@ class AggregateView(PermissionRequiredMixin, View): ).annotate_depth( limit=0 ) - child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) + + # Update the ipam_show_available cookie if request specifies it + if request.GET.get('show_available') is not None: + request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' + + # Add available prefixes to the table if the cookie requested it + if request.session.get('ipam_show_available'): + child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): @@ -356,6 +363,7 @@ class AggregateView(PermissionRequiredMixin, View): 'aggregate': aggregate, 'prefix_table': prefix_table, 'permissions': permissions, + 'show_available': request.session.get('ipam_show_available'), }) @@ -511,8 +519,12 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'site', 'vlan', 'role', ).annotate_depth(limit=0) - # Annotate available prefixes - if child_prefixes: + # Update the ipam_show_available cookie if request specifies it + if request.GET.get('show_available') is not None: + request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' + + # Add available prefixes to the table if the cookie requested it + if child_prefixes and request.session.get('ipam_show_available'): child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) @@ -539,6 +551,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'prefixes', + 'show_available': request.session.get('ipam_show_available'), }) @@ -553,7 +566,14 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): ipaddresses = prefix.get_child_ips().prefetch_related( 'vrf', 'interface__device', 'primary_ip4_for', 'primary_ip6_for' ) - ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) + + # Update the ipam_show_available cookie if request specifies it + if request.GET.get('show_available') is not None: + request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' + + # Add available IP addresses to the table if the cookie requested it + if request.session.get('ipam_show_available'): + ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) ip_table = tables.IPAddressTable(ipaddresses) if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'): @@ -579,6 +599,7 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'ip-addresses', + 'show_available': request.session.get('ipam_show_available'), }) diff --git a/netbox/templates/ipam/aggregate.html b/netbox/templates/ipam/aggregate.html index daa7b5107..ae79e9b66 100644 --- a/netbox/templates/ipam/aggregate.html +++ b/netbox/templates/ipam/aggregate.html @@ -40,6 +40,14 @@

{% block title %}{{ aggregate }}{% endblock %}

{% include 'inc/created_updated.html' with obj=aggregate %} + {% if show_available is not None %} +
+ +
+ {% endif %}
{% custom_links aggregate %}
diff --git a/netbox/templates/ipam/prefix.html b/netbox/templates/ipam/prefix.html index 9ea34804e..43b723553 100644 --- a/netbox/templates/ipam/prefix.html +++ b/netbox/templates/ipam/prefix.html @@ -53,6 +53,14 @@

{% block title %}{{ prefix }}{% endblock %}

{% include 'inc/created_updated.html' with obj=prefix %} + {% if show_available is not None %} +
+ +
+ {% endif %}
{% custom_links prefix %}
From f81641ae961e0a776f8a298285c2d45f0070ec73 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 2 Jan 2020 15:48:30 +0000 Subject: [PATCH 02/26] Corrected ticket number --- docs/release-notes/version-2.6.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index ce72351b3..d1c7f6619 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -2,7 +2,7 @@ ## Enhancements -* [#2365](https://github.com/netbox-community/netbox/issues/2365) - Toggle for showing available prefixes/ip addresses +* [#2589](https://github.com/netbox-community/netbox/issues/2589) - Toggle for showing available prefixes/ip addresses * [#2892](https://github.com/netbox-community/netbox/issues/2892) - Extend admin UI to allow deleting old report results * [#3062](https://github.com/netbox-community/netbox/issues/3062) - Add `assigned_to_interface` filter for IP addresses * [#3461](https://github.com/netbox-community/netbox/issues/3461) - Fail gracefully on custom link rendering exception From 2a219eff23332bd9e4429340033f10e32cb7bd07 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 2 Jan 2020 16:13:47 +0000 Subject: [PATCH 03/26] `is not None` not needed as the value 'false' is a string --- netbox/ipam/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 24d8efa82..590b63703 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -335,7 +335,7 @@ class AggregateView(PermissionRequiredMixin, View): ) # Update the ipam_show_available cookie if request specifies it - if request.GET.get('show_available') is not None: + if request.GET.get('show_available'): request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' # Add available prefixes to the table if the cookie requested it @@ -520,7 +520,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): ).annotate_depth(limit=0) # Update the ipam_show_available cookie if request specifies it - if request.GET.get('show_available') is not None: + if request.GET.get('show_available'): request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' # Add available prefixes to the table if the cookie requested it @@ -568,7 +568,7 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): ) # Update the ipam_show_available cookie if request specifies it - if request.GET.get('show_available') is not None: + if request.GET.get('show_available'): request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' # Add available IP addresses to the table if the cookie requested it From 8e3a37168848fa7e13c6fd2fba6051d9c905ecc3 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 2 Jan 2020 16:19:12 +0000 Subject: [PATCH 04/26] Added default to cookie --- netbox/ipam/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 590b63703..1ea9a717d 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -363,7 +363,7 @@ class AggregateView(PermissionRequiredMixin, View): 'aggregate': aggregate, 'prefix_table': prefix_table, 'permissions': permissions, - 'show_available': request.session.get('ipam_show_available'), + 'show_available': request.session.get('ipam_show_available', False), }) @@ -551,7 +551,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'prefixes', - 'show_available': request.session.get('ipam_show_available'), + 'show_available': request.session.get('ipam_show_available', False), }) @@ -599,7 +599,7 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'ip-addresses', - 'show_available': request.session.get('ipam_show_available'), + 'show_available': request.session.get('ipam_show_available', False), }) From 28ae6849b4fe276e775a0bd745c67be2ebb69ead Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 2 Jan 2020 16:29:11 +0000 Subject: [PATCH 05/26] Templatized show_available toggle --- netbox/templates/ipam/aggregate.html | 9 +-------- netbox/templates/ipam/inc/toggle_available.html | 9 +++++++++ netbox/templates/ipam/prefix.html | 9 +-------- 3 files changed, 11 insertions(+), 16 deletions(-) create mode 100644 netbox/templates/ipam/inc/toggle_available.html diff --git a/netbox/templates/ipam/aggregate.html b/netbox/templates/ipam/aggregate.html index ae79e9b66..d2dfe8888 100644 --- a/netbox/templates/ipam/aggregate.html +++ b/netbox/templates/ipam/aggregate.html @@ -40,14 +40,7 @@

{% block title %}{{ aggregate }}{% endblock %}

{% include 'inc/created_updated.html' with obj=aggregate %} - {% if show_available is not None %} - - {% endif %} + {% include 'ipam/inc/toggle_available.html' %}
{% custom_links aggregate %}
diff --git a/netbox/templates/ipam/inc/toggle_available.html b/netbox/templates/ipam/inc/toggle_available.html new file mode 100644 index 000000000..21d734d2d --- /dev/null +++ b/netbox/templates/ipam/inc/toggle_available.html @@ -0,0 +1,9 @@ +{% load helpers %} +{% if show_available is not None %} + +{% endif %} diff --git a/netbox/templates/ipam/prefix.html b/netbox/templates/ipam/prefix.html index 43b723553..56267786f 100644 --- a/netbox/templates/ipam/prefix.html +++ b/netbox/templates/ipam/prefix.html @@ -53,14 +53,7 @@

{% block title %}{{ prefix }}{% endblock %}

{% include 'inc/created_updated.html' with obj=prefix %} - {% if show_available is not None %} - - {% endif %} + {% include 'ipam/inc/toggle_available.html' %}
{% custom_links prefix %}
From 9d8ab81e3adb23f50f942d5b1eea523996edbefd Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Fri, 3 Jan 2020 19:24:39 +0000 Subject: [PATCH 06/26] Removed changelog (temporarily while merging) --- docs/release-notes/version-2.6.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index d1c7f6619..36afbc3e2 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -2,7 +2,6 @@ ## Enhancements -* [#2589](https://github.com/netbox-community/netbox/issues/2589) - Toggle for showing available prefixes/ip addresses * [#2892](https://github.com/netbox-community/netbox/issues/2892) - Extend admin UI to allow deleting old report results * [#3062](https://github.com/netbox-community/netbox/issues/3062) - Add `assigned_to_interface` filter for IP addresses * [#3461](https://github.com/netbox-community/netbox/issues/3461) - Fail gracefully on custom link rendering exception From e1c61c5019e79fc6f17cfd31a852202d1e67786a Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Fri, 3 Jan 2020 19:25:33 +0000 Subject: [PATCH 07/26] Changelog --- docs/release-notes/version-2.6.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 2bf55d857..9aa23200f 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -1,3 +1,9 @@ +# v2.6.12 (FUTURE) + +## Enhancements + +* [#2589](https://github.com/netbox-community/netbox/issues/2589) - Toggle for showing available prefixes/ip addresses + # v2.6.11 (2020-01-03) ## Bug Fixes From 04f3e58ab4d1ca920edef902ad5c68c204b9dc4a Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Fri, 3 Jan 2020 19:27:02 +0000 Subject: [PATCH 08/26] Line seperator --- docs/release-notes/version-2.6.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 9aa23200f..ffd1e3ee7 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -4,6 +4,8 @@ * [#2589](https://github.com/netbox-community/netbox/issues/2589) - Toggle for showing available prefixes/ip addresses +--- + # v2.6.11 (2020-01-03) ## Bug Fixes From e1d1f522ff07c573979eb494c02c9befb07cd202 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Fri, 3 Jan 2020 19:38:51 +0000 Subject: [PATCH 09/26] Closes #3090: Filter field for interface --- docs/release-notes/version-2.6.md | 6 ++++++ netbox/templates/dcim/device.html | 19 +++++++++++++++++++ .../virtualization/virtualmachine.html | 19 +++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 2bf55d857..c4589a009 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -1,3 +1,9 @@ +# v2.6.12 (FUTURE) + +## Enhancements + +* [#3090](https://github.com/netbox-community/netbox/issues/3090) - Add filter field for device interfaces + # v2.6.11 (2020-01-03) ## Bug Fixes diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 57e2b03b8..55332ca80 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -556,6 +556,9 @@ Show IPs +
+ +
@@ -912,6 +915,22 @@ $('button.toggle-ips').click(function() { $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked'); return false; }); +$('input.interface-filter').on('input', function() { + var filter = new RegExp(this.value); + + for (interface of $(this).closest('form').find('tbody > tr')) { + // Slice off 'interface_' at the start of the ID + if (filter && filter.test(interface.id.slice(10))) { + // Match the toggle in case the filter now matches the interface + $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked')); + $(interface).show(); + } else { + // Uncheck to prevent actions from including it when it doesn't match + $(interface).find('input:checkbox[name=pk]').prop('checked', false); + $(interface).hide(); + } + } +}); diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 2498039ff..736d6bc5c 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -253,6 +253,9 @@ Show IPs +
+ +
@@ -325,5 +328,21 @@ $('button.toggle-ips').click(function() { $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked'); return false; }); +$('input.interface-filter').on('input', function() { + var filter = new RegExp(this.value); + + for (interface of $(this).closest('form').find('tbody > tr')) { + // Slice off 'interface_' at the start of the ID + if (filter && filter.test(interface.id.slice(10))) { + // Match the toggle in case the filter now matches the interface + $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked')); + $(interface).show(); + } else { + // Uncheck to prevent actions from including it when it doesn't match + $(interface).find('input:checkbox[name=pk]').prop('checked', false); + $(interface).hide(); + } + } +}); {% endblock %} From 3556051d14b71de5785339976b1a992d8c2c115d Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Fri, 3 Jan 2020 19:58:41 +0000 Subject: [PATCH 10/26] Height was a touch off --- netbox/templates/dcim/device.html | 2 +- netbox/templates/virtualization/virtualmachine.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 55332ca80..3b3beb3e0 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -557,7 +557,7 @@
- +
diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 736d6bc5c..298daf94f 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -254,7 +254,7 @@
- +
From 28eca9a02606e4ee11dde3b6b157ca20c5dc2396 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Fri, 3 Jan 2020 20:12:21 +0000 Subject: [PATCH 11/26] Forgot le seperator --- docs/release-notes/version-2.6.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index c4589a009..c099d5115 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -4,6 +4,8 @@ * [#3090](https://github.com/netbox-community/netbox/issues/3090) - Add filter field for device interfaces +--- + # v2.6.11 (2020-01-03) ## Bug Fixes From 07a1baef13e0a4251f7aa28db4a4ce40a5193b16 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Mon, 6 Jan 2020 20:05:07 +0000 Subject: [PATCH 12/26] Limit toggle selector to visible input fields --- netbox/project-static/js/forms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/project-static/js/forms.js b/netbox/project-static/js/forms.js index 55f9afbd5..20d6c9126 100644 --- a/netbox/project-static/js/forms.js +++ b/netbox/project-static/js/forms.js @@ -7,7 +7,7 @@ $(document).ready(function() { // "Toggle" checkbox for object lists (PK column) $('input:checkbox.toggle').click(function() { - $(this).closest('table').find('input:checkbox[name=pk]').prop('checked', $(this).prop('checked')); + $(this).closest('table').find('input:checkbox[name=pk]:visible').prop('checked', $(this).prop('checked')); // Show the "select all" box if present if ($(this).is(':checked')) { From a7ec0c14f75fd201efb7c408d40aaed78aea94a3 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Mon, 6 Jan 2020 20:18:44 +0000 Subject: [PATCH 13/26] Move toggles js code to static --- netbox/project-static/js/interface_toggles.js | 30 +++++++++++++++++ netbox/templates/dcim/device.html | 29 +---------------- .../virtualization/virtualmachine.html | 32 ++----------------- 3 files changed, 33 insertions(+), 58 deletions(-) create mode 100644 netbox/project-static/js/interface_toggles.js diff --git a/netbox/project-static/js/interface_toggles.js b/netbox/project-static/js/interface_toggles.js new file mode 100644 index 000000000..a3649558a --- /dev/null +++ b/netbox/project-static/js/interface_toggles.js @@ -0,0 +1,30 @@ +// Toggle the display of IP addresses under interfaces +$('button.toggle-ips').click(function() { + var selected = $(this).attr('selected'); + if (selected) { + $('#interfaces_table tr.ipaddresses').hide(); + } else { + $('#interfaces_table tr.ipaddresses').show(); + } + $(this).attr('selected', !selected); + $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked'); + return false; +}); + +// Inteface filtering +$('input.interface-filter').on('input', function() { + var filter = new RegExp(this.value); + + for (interface of $(this).closest('form').find('tbody > tr')) { + // Slice off 'interface_' at the start of the ID + if (filter && filter.test(interface.id.slice(10))) { + // Match the toggle in case the filter now matches the interface + $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked')); + $(interface).show(); + } else { + // Uncheck to prevent actions from including it when it doesn't match + $(interface).find('input:checkbox[name=pk]').prop('checked', false); + $(interface).hide(); + } + } +}); diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 3b3beb3e0..f88838028 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -903,35 +903,8 @@ function toggleConnection(elem) { $(".cable-toggle").click(function() { return toggleConnection($(this)); }); -// Toggle the display of IP addresses under interfaces -$('button.toggle-ips').click(function() { - var selected = $(this).attr('selected'); - if (selected) { - $('#interfaces_table tr.ipaddresses').hide(); - } else { - $('#interfaces_table tr.ipaddresses').show(); - } - $(this).attr('selected', !selected); - $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked'); - return false; -}); -$('input.interface-filter').on('input', function() { - var filter = new RegExp(this.value); - - for (interface of $(this).closest('form').find('tbody > tr')) { - // Slice off 'interface_' at the start of the ID - if (filter && filter.test(interface.id.slice(10))) { - // Match the toggle in case the filter now matches the interface - $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked')); - $(interface).show(); - } else { - // Uncheck to prevent actions from including it when it doesn't match - $(interface).find('input:checkbox[name=pk]').prop('checked', false); - $(interface).hide(); - } - } -}); + {% endblock %} diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 298daf94f..6477c71ad 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -1,5 +1,6 @@ {% extends '_base.html' %} {% load custom_links %} +{% load static %} {% load helpers %} {% block header %} @@ -315,34 +316,5 @@ {% endblock %} {% block javascript %} - + {% endblock %} From 6a3cd83efcecc21a157cca164a7913852158597d Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Mon, 6 Jan 2020 23:33:18 +0000 Subject: [PATCH 14/26] Moved regex note to tooltip --- netbox/project-static/js/forms.js | 6 +++--- netbox/templates/dcim/device.html | 2 +- netbox/templates/virtualization/virtualmachine.html | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/netbox/project-static/js/forms.js b/netbox/project-static/js/forms.js index 0b8c7d719..b7dbb1cfa 100644 --- a/netbox/project-static/js/forms.js +++ b/netbox/project-static/js/forms.js @@ -400,8 +400,8 @@ $(document).ready(function() { window.addEventListener('hashchange', headerOffsetScroll); // Offset between the preview window and the window edges - const IMAGE_PREVIEW_OFFSET_X = 20 - const IMAGE_PREVIEW_OFFSET_Y = 10 + const IMAGE_PREVIEW_OFFSET_X = 20; + const IMAGE_PREVIEW_OFFSET_Y = 10; // Preview an image attachment when the link is hovered over $('a.image-preview').on('mouseover', function(e) { @@ -435,6 +435,6 @@ $(document).ready(function() { // Fade the image out; it will be deleted when another one is previewed $('a.image-preview').on('mouseout', function() { - $('#image-preview-window').fadeOut('fast') + $('#image-preview-window').fadeOut('fast'); }); }); diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index f88838028..74d469a12 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -557,7 +557,7 @@
- +
diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 6477c71ad..5e73935d0 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -255,7 +255,7 @@
- +
From 190e68365468551e729e7c1b0a4830561be19fc0 Mon Sep 17 00:00:00 2001 From: hSaria <34197532+hSaria@users.noreply.github.com> Date: Tue, 7 Jan 2020 17:18:36 +0000 Subject: [PATCH 15/26] Removed cookie-based storage; now based on request --- netbox/ipam/views.py | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 1ea9a717d..5f727a5ac 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -334,12 +334,8 @@ class AggregateView(PermissionRequiredMixin, View): limit=0 ) - # Update the ipam_show_available cookie if request specifies it - if request.GET.get('show_available'): - request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' - - # Add available prefixes to the table if the cookie requested it - if request.session.get('ipam_show_available'): + # Add available prefixes to the table if requested + if request.GET.get('show_available', False): child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) @@ -363,7 +359,7 @@ class AggregateView(PermissionRequiredMixin, View): 'aggregate': aggregate, 'prefix_table': prefix_table, 'permissions': permissions, - 'show_available': request.session.get('ipam_show_available', False), + 'show_available': request.GET.get('show_available', False), }) @@ -519,12 +515,8 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'site', 'vlan', 'role', ).annotate_depth(limit=0) - # Update the ipam_show_available cookie if request specifies it - if request.GET.get('show_available'): - request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' - - # Add available prefixes to the table if the cookie requested it - if child_prefixes and request.session.get('ipam_show_available'): + # Add available prefixes to the table if requested + if child_prefixes and request.GET.get('show_available', False): child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) @@ -551,7 +543,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'prefixes', - 'show_available': request.session.get('ipam_show_available', False), + 'show_available': request.GET.get('show_available', False), }) @@ -567,12 +559,8 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): 'vrf', 'interface__device', 'primary_ip4_for', 'primary_ip6_for' ) - # Update the ipam_show_available cookie if request specifies it - if request.GET.get('show_available'): - request.session['ipam_show_available'] = request.GET.get('show_available') == 'true' - - # Add available IP addresses to the table if the cookie requested it - if request.session.get('ipam_show_available'): + # Add available IP addresses to the table if requested + if request.GET.get('show_available', False): ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) ip_table = tables.IPAddressTable(ipaddresses) @@ -599,7 +587,7 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'ip-addresses', - 'show_available': request.session.get('ipam_show_available', False), + 'show_available': request.GET.get('show_available', False), }) From 32f39e10c9f94fe079cf31a1f96020e59346bfb5 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Tue, 7 Jan 2020 17:58:30 +0000 Subject: [PATCH 16/26] Changed default to showing available --- netbox/ipam/views.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 5f727a5ac..26df90c93 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -335,7 +335,7 @@ class AggregateView(PermissionRequiredMixin, View): ) # Add available prefixes to the table if requested - if request.GET.get('show_available', False): + if request.GET.get('show_available', 'true') == 'true': child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) @@ -359,7 +359,7 @@ class AggregateView(PermissionRequiredMixin, View): 'aggregate': aggregate, 'prefix_table': prefix_table, 'permissions': permissions, - 'show_available': request.GET.get('show_available', False), + 'show_available': request.GET.get('show_available', 'true') == 'true', }) @@ -516,7 +516,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): ).annotate_depth(limit=0) # Add available prefixes to the table if requested - if child_prefixes and request.GET.get('show_available', False): + if child_prefixes and request.GET.get('show_available', 'true') == 'true': child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) @@ -543,7 +543,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'prefixes', - 'show_available': request.GET.get('show_available', False), + 'show_available': request.GET.get('show_available', 'true') == 'true', }) @@ -560,7 +560,7 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): ) # Add available IP addresses to the table if requested - if request.GET.get('show_available', False): + if request.GET.get('show_available', 'true') == 'true': ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) ip_table = tables.IPAddressTable(ipaddresses) @@ -587,7 +587,7 @@ class PrefixIPAddressesView(PermissionRequiredMixin, View): 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), 'active_tab': 'ip-addresses', - 'show_available': request.GET.get('show_available', False), + 'show_available': request.GET.get('show_available', 'true') == 'true', }) From 996d49de670159d62b6ca82c76830901b3f702c2 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 8 Jan 2020 10:49:58 +0000 Subject: [PATCH 17/26] Fixes #3440: Total cable trace length --- docs/release-notes/version-2.6.md | 1 + netbox/dcim/models.py | 2 ++ netbox/dcim/views.py | 5 ++++- netbox/templates/dcim/cable_trace.html | 5 ++++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index f3ff8798a..86bdc44c7 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -4,6 +4,7 @@ * [#2050](https://github.com/netbox-community/netbox/issues/2050) - Preview image attachments when hovering the link * [#3187](https://github.com/netbox-community/netbox/issues/3187) - Add rack selection field to rack elevations +* [#3440](https://github.com/netbox-community/netbox/issues/3440) - Add total length to cable trace ## Bug Fixes diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 8f95fa19a..2c7105a80 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -2950,6 +2950,8 @@ class Cable(ChangeLoggedModel): # Store the given length (if any) in meters for use in database ordering if self.length and self.length_unit: self._abs_length = to_meters(self.length, self.length_unit) + else: + self._abs_length = None # Store the parent Device for the A and B terminations (if applicable) to enable filtering if hasattr(self.termination_a, 'device'): diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 2d98515cf..55a08fdb8 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1754,10 +1754,13 @@ class CableTraceView(PermissionRequiredMixin, View): def get(self, request, model, pk): obj = get_object_or_404(model, pk=pk) + trace = obj.trace(follow_circuits=True) + total_length = sum([entry[1]._abs_length for entry in trace if entry[1] and entry[1]._abs_length]) return render(request, 'dcim/cable_trace.html', { 'obj': obj, - 'trace': obj.trace(follow_circuits=True), + 'trace': trace, + 'total_length': total_length, }) diff --git a/netbox/templates/dcim/cable_trace.html b/netbox/templates/dcim/cable_trace.html index c9da88c46..4dd145058 100644 --- a/netbox/templates/dcim/cable_trace.html +++ b/netbox/templates/dcim/cable_trace.html @@ -10,7 +10,10 @@

Near End

-
+
+ {% if total_length %}
Total length: {{ total_length|floatformat:"-2" }} Meters
{% endif %} +
+

Far End

From ea05b5b60614940561931d52bd06e5f5735bfcf1 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 8 Jan 2020 13:34:46 +0000 Subject: [PATCH 18/26] Fixes #1982: Swagger NAPALM documentation --- docs/release-notes/version-2.6.md | 1 + netbox/dcim/api/serializers.py | 4 ++++ netbox/dcim/api/views.py | 11 +++++++++++ 3 files changed, 16 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index f3ff8798a..90eba7327 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -2,6 +2,7 @@ ## Enhancements +* [#1982](https://github.com/netbox-community/netbox/issues/1982) - Improved NAPALM method documentation in Swagger * [#2050](https://github.com/netbox-community/netbox/issues/2050) - Preview image attachments when hovering the link * [#3187](https://github.com/netbox-community/netbox/issues/3187) - Add rack selection field to rack elevations diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 495709268..db5fe992f 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -370,6 +370,10 @@ class DeviceWithConfigContextSerializer(DeviceSerializer): return obj.get_config_context() +class DeviceNAPALMSerializer(serializers.Serializer): + method = serializers.DictField() + + class ConsoleServerPortSerializer(TaggitSerializer, ConnectedEndpointSerializer): device = NestedDeviceSerializer() cable = NestedCableSerializer(read_only=True) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 12774e4be..9bfe0f421 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -327,6 +327,13 @@ class DeviceViewSet(CustomFieldModelViewSet): ) filterset_class = filters.DeviceFilter + _method = Parameter( + name='method', + in_='query', + required=True, + type=openapi.TYPE_STRING + ) + def get_serializer_class(self): """ Select the specific serializer based on the request context. @@ -358,11 +365,15 @@ class DeviceViewSet(CustomFieldModelViewSet): return Response(serializer.data) + @swagger_auto_schema(manual_parameters=[_method], responses={'200': serializers.DeviceNAPALMSerializer}) @action(detail=True, url_path='napalm') def napalm(self, request, pk): """ Execute a NAPALM method on a Device """ + if not request.GET.get('method'): + raise ServiceUnavailable('No NAPALM methods were specified.') + device = get_object_or_404(Device, pk=pk) if not device.primary_ip: raise ServiceUnavailable("This device does not have a primary IP address configured.") From dc475f4755a6ab8d77e60de40e9142c795581317 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 8 Jan 2020 15:53:48 +0000 Subject: [PATCH 19/26] Fixes #2113: Adjust NAPALM settings with headers --- netbox/dcim/api/views.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 12774e4be..205bc0af0 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -396,13 +396,29 @@ class DeviceViewSet(CustomFieldModelViewSet): napalm_methods = request.GET.getlist('method') response = OrderedDict([(m, None) for m in napalm_methods]) ip_address = str(device.primary_ip.address.ip) + username = settings.NAPALM_USERNAME + password = settings.NAPALM_PASSWORD optional_args = settings.NAPALM_ARGS.copy() if device.platform.napalm_args is not None: optional_args.update(device.platform.napalm_args) + + # Update NAPALM parameters according to the provided headers + for header in request.headers: + if header[:7].lower() != 'napalm-': + continue + + key = header[7:] + if key.lower() == 'username': + username = request.headers[header] + elif key.lower() == 'password': + password = request.headers[header] + elif key: + optional_args[key.lower()] == request.headers[header] + d = driver( hostname=ip_address, - username=settings.NAPALM_USERNAME, - password=settings.NAPALM_PASSWORD, + username=username, + password=password, timeout=settings.NAPALM_TIMEOUT, optional_args=optional_args ) From ce8d47086033cee2e707bb27f769eb9d6d1dd36e Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 8 Jan 2020 15:54:09 +0000 Subject: [PATCH 20/26] Added NAPALM documentation --- docs/additional-features/napalm.md | 65 ++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 66 insertions(+) create mode 100644 docs/additional-features/napalm.md diff --git a/docs/additional-features/napalm.md b/docs/additional-features/napalm.md new file mode 100644 index 000000000..a7b91128b --- /dev/null +++ b/docs/additional-features/napalm.md @@ -0,0 +1,65 @@ +# NAPALM + +NetBox supports integration with the [NAPALM automation](https://napalm-automation.net/) library. NAPALM allows NetBox to fetch live data from devices and return it to a requester via its REST API. + +!!! info + To enable the integration, the NAPALM library must be installed. See [installation steps](../../installation/2-netbox/#napalm-automation-optional) for more information. + +``` +GET /api/dcim/devices/1/napalm/?method=get_environment + +{ + "get_environment": { + ... + } +} +``` + +## Authentication + +By default, the [`NAPALM_USERNAME`](../../configuration/optional-settings/#napalm_username) and [`NAPALM_PASSWORD`](../../configuration/optional-settings/#napalm_password) are used for NAPALM authentication. They can be overridden for an individual API call through the `NAPALM-Username` and `NAPALM-Password` headers. + +``` +$ curl "http://localhost/api/dcim/devices/1/napalm/?method=get_environment" \ +-H "Authorization: Token f4b378553dacfcfd44c5a0b9ae49b57e29c552b5" \ +-H "Content-Type: application/json" \ +-H "Accept: application/json; indent=4" \ +-H "NAPALM-Username: foo" \ +-H "NAPALM-Password: bar" +``` + +## Method Support + +The list of supported NAPALM methods depends on the [NAPALM driver](https://napalm.readthedocs.io/en/latest/support/index.html#general-support-matrix) configured for the platform of a device. NetBox only supports [get](https://napalm.readthedocs.io/en/latest/support/index.html#getters-support-matrix) methods. + +## Multiple Methods + +More than one method in an API call can be invoked by adding multiple `method` parameters. For example: + +``` +GET /api/dcim/devices/1/napalm/?method=get_ntp_servers&method=get_ntp_peers + +{ + "get_ntp_servers": { + ... + }, + "get_ntp_peers": { + ... + } +} +``` + +## Optional Arguments + +The behavior of NAPALM drivers can be adjusted according to the [optional arguments](https://napalm.readthedocs.io/en/latest/support/index.html#optional-arguments). NetBox exposes those arguments using headers prefixed with `NAPALM-`. + + +For instance, the SSH port is changed to 2222 in this API call: + +``` +$ curl "http://localhost/api/dcim/devices/1/napalm/?method=get_environment" \ +-H "Authorization: Token f4b378553dacfcfd44c5a0b9ae49b57e29c552b5" \ +-H "Content-Type: application/json" \ +-H "Accept: application/json; indent=4" \ +-H "NAPALM-port: 2222" +``` diff --git a/mkdocs.yml b/mkdocs.yml index cc44921b6..b493a799b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -35,6 +35,7 @@ pages: - Custom Scripts: 'additional-features/custom-scripts.md' - Export Templates: 'additional-features/export-templates.md' - Graphs: 'additional-features/graphs.md' + - NAPALM: 'additional-features/napalm.md' - Prometheus Metrics: 'additional-features/prometheus-metrics.md' - Reports: 'additional-features/reports.md' - Tags: 'additional-features/tags.md' From 98a66f7fbe77ef849ce0b27bb9dca80a7edc36c5 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 8 Jan 2020 15:55:36 +0000 Subject: [PATCH 21/26] NAPALM settings changelog --- docs/release-notes/version-2.6.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index f3ff8798a..61683fc75 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -3,6 +3,7 @@ ## Enhancements * [#2050](https://github.com/netbox-community/netbox/issues/2050) - Preview image attachments when hovering the link +* [#2113](https://github.com/netbox-community/netbox/issues/2113) - Allow NAPALM driver settings to be changed with request headers * [#3187](https://github.com/netbox-community/netbox/issues/3187) - Add rack selection field to rack elevations ## Bug Fixes From f49467bcb5370f6bd39cbc786328874981c88c71 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 8 Jan 2020 16:01:18 +0000 Subject: [PATCH 22/26] Corrected optional arg assignment --- netbox/dcim/api/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 205bc0af0..18da2f9a3 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -402,7 +402,7 @@ class DeviceViewSet(CustomFieldModelViewSet): if device.platform.napalm_args is not None: optional_args.update(device.platform.napalm_args) - # Update NAPALM parameters according to the provided headers + # Update NAPALM parameters according to the request headers for header in request.headers: if header[:7].lower() != 'napalm-': continue @@ -413,7 +413,7 @@ class DeviceViewSet(CustomFieldModelViewSet): elif key.lower() == 'password': password = request.headers[header] elif key: - optional_args[key.lower()] == request.headers[header] + optional_args[key.lower()] = request.headers[header] d = driver( hostname=ip_address, From 6537f35176594e57bd3919074ffbecb868af38bd Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 9 Jan 2020 14:33:49 +0000 Subject: [PATCH 23/26] Fixes #3864: Disallow /0 masks --- docs/release-notes/version-2.6.md | 1 + netbox/ipam/models.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index f3ff8798a..2cd240e15 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -10,6 +10,7 @@ * [#3589](https://github.com/netbox-community/netbox/issues/3589) - Fix validation on tagged VLANs of an interface * [#3853](https://github.com/netbox-community/netbox/issues/3853) - Fix device role link on config context view * [#3856](https://github.com/netbox-community/netbox/issues/3856) - Allow filtering VM interfaces by multiple MAC addresses +* [#3864](https://github.com/netbox-community/netbox/issues/3864) - Disallow /0 masks --- diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 8f9b64b59..a67ff4a86 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -177,6 +177,12 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel): # Clear host bits from prefix self.prefix = self.prefix.cidr + # /0 masks are not acceptable + if self.prefix.prefixlen == 0: + raise ValidationError({ + 'prefix': "Cannot create aggregate with /0 mask." + }) + # Ensure that the aggregate being added is not covered by an existing aggregate covering_aggregates = Aggregate.objects.filter(prefix__net_contains_or_equals=str(self.prefix)) if self.pk: @@ -347,6 +353,12 @@ class Prefix(ChangeLoggedModel, CustomFieldModel): if self.prefix: + # /0 masks are not acceptable + if self.prefix.prefixlen == 0: + raise ValidationError({ + 'prefix': "Cannot create prefix with /0 mask." + }) + # Disallow host masks if self.prefix.version == 4 and self.prefix.prefixlen == 32: raise ValidationError({ @@ -622,6 +634,12 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): if self.address: + # /0 masks are not acceptable + if self.address.prefixlen == 0: + raise ValidationError({ + 'address': "Cannot create IP address with /0 mask." + }) + # Enforce unique IP space (if applicable) if self.role not in IPADDRESS_ROLES_NONUNIQUE and (( self.vrf is None and settings.ENFORCE_GLOBAL_UNIQUE From 46c712e735702b27e79cf2a6019963212867616b Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 9 Jan 2020 16:39:13 +0000 Subject: [PATCH 24/26] Moved NAPALM parameter to decorator --- netbox/dcim/api/views.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 9bfe0f421..3c953bbfc 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -327,13 +327,6 @@ class DeviceViewSet(CustomFieldModelViewSet): ) filterset_class = filters.DeviceFilter - _method = Parameter( - name='method', - in_='query', - required=True, - type=openapi.TYPE_STRING - ) - def get_serializer_class(self): """ Select the specific serializer based on the request context. @@ -365,7 +358,17 @@ class DeviceViewSet(CustomFieldModelViewSet): return Response(serializer.data) - @swagger_auto_schema(manual_parameters=[_method], responses={'200': serializers.DeviceNAPALMSerializer}) + @swagger_auto_schema( + manual_parameters=[ + Parameter( + name='method', + in_='query', + required=True, + type=openapi.TYPE_STRING + ) + ], + responses={'200': serializers.DeviceNAPALMSerializer} + ) @action(detail=True, url_path='napalm') def napalm(self, request, pk): """ From ad565e55f1ee9c1a975202f1d314f78e48a0718a Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 9 Jan 2020 16:40:13 +0000 Subject: [PATCH 25/26] Removed exception for empty methods I'll create a seperate ticket for that --- netbox/dcim/api/views.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 3c953bbfc..e345210fd 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -374,9 +374,6 @@ class DeviceViewSet(CustomFieldModelViewSet): """ Execute a NAPALM method on a Device """ - if not request.GET.get('method'): - raise ServiceUnavailable('No NAPALM methods were specified.') - device = get_object_or_404(Device, pk=pk) if not device.primary_ip: raise ServiceUnavailable("This device does not have a primary IP address configured.") From 9d085ad83a26aa90eeed4c36c123171bf6ae0c80 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 9 Jan 2020 16:48:26 +0000 Subject: [PATCH 26/26] Changed `NAPALM-` prefix to `X-NAPALM-` --- docs/additional-features/napalm.md | 10 +++++----- netbox/dcim/api/views.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/additional-features/napalm.md b/docs/additional-features/napalm.md index a7b91128b..c8e8b8b3a 100644 --- a/docs/additional-features/napalm.md +++ b/docs/additional-features/napalm.md @@ -17,15 +17,15 @@ GET /api/dcim/devices/1/napalm/?method=get_environment ## Authentication -By default, the [`NAPALM_USERNAME`](../../configuration/optional-settings/#napalm_username) and [`NAPALM_PASSWORD`](../../configuration/optional-settings/#napalm_password) are used for NAPALM authentication. They can be overridden for an individual API call through the `NAPALM-Username` and `NAPALM-Password` headers. +By default, the [`NAPALM_USERNAME`](../../configuration/optional-settings/#napalm_username) and [`NAPALM_PASSWORD`](../../configuration/optional-settings/#napalm_password) are used for NAPALM authentication. They can be overridden for an individual API call through the `X-NAPALM-Username` and `X-NAPALM-Password` headers. ``` $ curl "http://localhost/api/dcim/devices/1/napalm/?method=get_environment" \ -H "Authorization: Token f4b378553dacfcfd44c5a0b9ae49b57e29c552b5" \ -H "Content-Type: application/json" \ -H "Accept: application/json; indent=4" \ --H "NAPALM-Username: foo" \ --H "NAPALM-Password: bar" +-H "X-NAPALM-Username: foo" \ +-H "X-NAPALM-Password: bar" ``` ## Method Support @@ -51,7 +51,7 @@ GET /api/dcim/devices/1/napalm/?method=get_ntp_servers&method=get_ntp_peers ## Optional Arguments -The behavior of NAPALM drivers can be adjusted according to the [optional arguments](https://napalm.readthedocs.io/en/latest/support/index.html#optional-arguments). NetBox exposes those arguments using headers prefixed with `NAPALM-`. +The behavior of NAPALM drivers can be adjusted according to the [optional arguments](https://napalm.readthedocs.io/en/latest/support/index.html#optional-arguments). NetBox exposes those arguments using headers prefixed with `X-NAPALM-`. For instance, the SSH port is changed to 2222 in this API call: @@ -61,5 +61,5 @@ $ curl "http://localhost/api/dcim/devices/1/napalm/?method=get_environment" \ -H "Authorization: Token f4b378553dacfcfd44c5a0b9ae49b57e29c552b5" \ -H "Content-Type: application/json" \ -H "Accept: application/json; indent=4" \ --H "NAPALM-port: 2222" +-H "X-NAPALM-port: 2222" ``` diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 18da2f9a3..a7dfb39ff 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -404,10 +404,10 @@ class DeviceViewSet(CustomFieldModelViewSet): # Update NAPALM parameters according to the request headers for header in request.headers: - if header[:7].lower() != 'napalm-': + if header[:9].lower() != 'x-napalm-': continue - key = header[7:] + key = header[9:] if key.lower() == 'username': username = request.headers[header] elif key.lower() == 'password':