Просмотр исходного кода

Fixes #1992: Isolate errors when one of multiple NAPALM methods fails

Jeremy Stretch 7 лет назад
Родитель
Сommit
d665d4d62a
1 измененных файлов с 15 добавлено и 12 удалено
  1. 15 12
      netbox/dcim/api/views.py

+ 15 - 12
netbox/dcim/api/views.py

@@ -267,7 +267,7 @@ class DeviceViewSet(CustomFieldModelViewSet):
             import napalm
         except ImportError:
             raise ServiceUnavailable("NAPALM is not installed. Please see the documentation for instructions.")
-        from napalm.base.exceptions import ConnectAuthError, ModuleImportError
+        from napalm.base.exceptions import ModuleImportError
 
         # Validate the configured driver
         try:
@@ -281,16 +281,8 @@ class DeviceViewSet(CustomFieldModelViewSet):
         if not request.user.has_perm('dcim.napalm_read'):
             return HttpResponseForbidden()
 
-        # Validate requested NAPALM methods
+        # Connect to the device
         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(
@@ -302,12 +294,23 @@ class DeviceViewSet(CustomFieldModelViewSet):
         )
         try:
             d.open()
-            for method in napalm_methods:
-                response[method] = getattr(d, method)()
         except Exception as e:
             raise ServiceUnavailable("Error connecting to the device at {}: {}".format(ip_address, e))
 
+        # Validate and execute each specified NAPALM method
+        for method in napalm_methods:
+            if not hasattr(driver, method):
+                response[method] = {'error': 'Unknown NAPALM method'}
+                continue
+            if not method.startswith('get_'):
+                response[method] = {'error': 'Only get_* NAPALM methods are supported'}
+                continue
+            try:
+                response[method] = getattr(d, method)()
+            except NotImplementedError:
+                response[method] = {'error': 'Method not implemented for NAPALM driver {}'.format(driver)}
         d.close()
+
         return Response(response)