From dc475f4755a6ab8d77e60de40e9142c795581317 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Wed, 8 Jan 2020 15:53:48 +0000 Subject: [PATCH 1/5] 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 2/5] 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 3/5] 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 4/5] 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 9d085ad83a26aa90eeed4c36c123171bf6ae0c80 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Thu, 9 Jan 2020 16:48:26 +0000 Subject: [PATCH 5/5] 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':