mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Live device status PoC
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
from collections import OrderedDict
|
||||
|
||||
from rest_framework.decorators import detail_route
|
||||
from rest_framework.mixins import ListModelMixin
|
||||
@@ -7,7 +8,7 @@ from rest_framework.response import Response
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ViewSet
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import Http404, HttpResponseForbidden
|
||||
from django.http import HttpResponseBadRequest, HttpResponseForbidden
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from dcim.models import (
|
||||
@@ -225,8 +226,8 @@ class DeviceViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
|
||||
write_serializer_class = serializers.WritableDeviceSerializer
|
||||
filter_class = filters.DeviceFilter
|
||||
|
||||
@detail_route(url_path='napalm/(?P<method>get_[a-z_]+)')
|
||||
def napalm(self, request, pk, method):
|
||||
@detail_route(url_path='napalm')
|
||||
def napalm(self, request, pk):
|
||||
"""
|
||||
Execute a NAPALM method on a Device
|
||||
"""
|
||||
@@ -253,16 +254,21 @@ class DeviceViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
|
||||
device.platform, device.platform.napalm_driver
|
||||
))
|
||||
|
||||
# Raise a 404 for invalid NAPALM methods
|
||||
if not hasattr(driver, method):
|
||||
raise Http404()
|
||||
|
||||
# Verify user permission
|
||||
if not request.user.has_perm('dcim.napalm_read'):
|
||||
return HttpResponseForbidden()
|
||||
|
||||
# Connect to the device and execute the given method
|
||||
# Validate requested NAPALM methods
|
||||
napalm_methods = request.GET.getlist('method')
|
||||
for method in napalm_methods:
|
||||
if not hasattr(driver, method):
|
||||
return HttpResponseBadRequest("Unknown NAPALM method: {}".format(method))
|
||||
elif not method.startswith('get_'):
|
||||
return HttpResponseBadRequest("Unsupported NAPALM method: {}".format(method))
|
||||
|
||||
# Connect to the device and execute the requested methods
|
||||
# TODO: Improve error handling
|
||||
response = OrderedDict([(m, None) for m in napalm_methods])
|
||||
ip_address = str(device.primary_ip.address.ip)
|
||||
d = driver(
|
||||
hostname=ip_address,
|
||||
@@ -271,10 +277,12 @@ class DeviceViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
|
||||
)
|
||||
try:
|
||||
d.open()
|
||||
response = getattr(d, method)()
|
||||
for method in napalm_methods:
|
||||
response[method] = getattr(d, method)()
|
||||
except Exception as e:
|
||||
raise ServiceUnavailable("Error connecting to the device: {}".format(e))
|
||||
|
||||
d.close()
|
||||
return Response(response)
|
||||
|
||||
|
||||
|
@@ -122,6 +122,7 @@ urlpatterns = [
|
||||
url(r'^devices/(?P<pk>\d+)/edit/$', views.DeviceEditView.as_view(), name='device_edit'),
|
||||
url(r'^devices/(?P<pk>\d+)/delete/$', views.DeviceDeleteView.as_view(), name='device_delete'),
|
||||
url(r'^devices/(?P<pk>\d+)/inventory/$', views.DeviceInventoryView.as_view(), name='device_inventory'),
|
||||
url(r'^devices/(?P<pk>\d+)/status/$', views.DeviceStatusView.as_view(), name='device_status'),
|
||||
url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', views.DeviceLLDPNeighborsView.as_view(), name='device_lldp_neighbors'),
|
||||
url(r'^devices/(?P<pk>\d+)/add-secret/$', secret_add, name='device_addsecret'),
|
||||
url(r'^devices/(?P<device>\d+)/services/assign/$', ServiceCreateView.as_view(), name='service_assign'),
|
||||
|
@@ -921,6 +921,27 @@ class DeviceInventoryView(View):
|
||||
})
|
||||
|
||||
|
||||
class DeviceStatusView(View):
|
||||
|
||||
def get(self, request, pk):
|
||||
|
||||
device = get_object_or_404(Device, pk=pk)
|
||||
method = request.GET.get('method', 'get_facts')
|
||||
|
||||
interfaces = Interface.objects.order_naturally(
|
||||
device.device_type.interface_ordering
|
||||
).filter(
|
||||
device=device
|
||||
).select_related(
|
||||
'connected_as_a', 'connected_as_b'
|
||||
)
|
||||
|
||||
return render(request, 'dcim/device_status.html', {
|
||||
'device': device,
|
||||
'interfaces': interfaces,
|
||||
})
|
||||
|
||||
|
||||
class DeviceLLDPNeighborsView(View):
|
||||
|
||||
def get(self, request, pk):
|
||||
|
Reference in New Issue
Block a user