def get(self, request, pk): device = get_object_or_404(Device, pk=pk) if not device.primary_ip: raise ServiceUnavailable(detail="No IP configured for this device.") RPC = device.get_rpc_client() if not RPC: raise ServiceUnavailable(detail="No RPC client available for this platform ({}).".format(device.platform)) # Connect to device and retrieve inventory info try: with RPC(device, username=settings.NETBOX_USERNAME, password=settings.NETBOX_PASSWORD) as rpc_client: lldp_neighbors = rpc_client.get_lldp_neighbors() except: raise ServiceUnavailable(detail="Error connecting to the remote device.") return Response(lldp_neighbors)
def napalm(self, request, pk): """ Execute a NAPALM method on a Device """ 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.") if device.platform is None: raise ServiceUnavailable( "No platform is configured for this device.") if not device.platform.napalm_driver: raise ServiceUnavailable( "No NAPALM driver is configured for this device's platform ()." .format(device.platform)) # Check that NAPALM is installed try: import napalm from napalm.base.exceptions import ModuleImportError except ImportError: raise ServiceUnavailable( "NAPALM is not installed. Please see the documentation for instructions." ) # Validate the configured driver try: driver = napalm.get_network_driver(device.platform.napalm_driver) except ModuleImportError: raise ServiceUnavailable( "NAPALM driver for platform {} not found: {}.".format( device.platform, device.platform.napalm_driver)) # Verify user permission if not request.user.has_perm('dcim.napalm_read'): return HttpResponseForbidden() # Connect to the device napalm_methods = request.GET.getlist('method') response = OrderedDict([(m, None) for m in napalm_methods]) ip_address = str(device.primary_ip.address.ip) optional_args = settings.NAPALM_ARGS.copy() if device.platform.napalm_args is not None: optional_args.update(device.platform.napalm_args) d = driver(hostname=ip_address, username=settings.NAPALM_USERNAME, password=settings.NAPALM_PASSWORD, timeout=settings.NAPALM_TIMEOUT, optional_args=optional_args) try: d.open() 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( method, driver) } except Exception as e: response[method] = { 'error': 'Method {} failed: {}'.format(method, e) } d.close() return Response(response)
def napalm(self, request, pk): """ Execute a NAPALM method on a Device """ 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.") if device.platform is None: raise ServiceUnavailable( "No platform is configured for this device.") if not device.platform.napalm_driver: raise ServiceUnavailable( "No NAPALM driver is configured for this device's platform ()." .format(device.platform)) # Check that NAPALM is installed try: import napalm except ImportError: raise ServiceUnavailable( "NAPALM is not installed. Please see the documentation for instructions." ) # TODO: Remove support for NAPALM < 2.0 try: from napalm.base.exceptions import ConnectAuthError, ModuleImportError except ImportError: from napalm_base.exceptions import ConnectAuthError, ModuleImportError # Validate the configured driver try: driver = napalm.get_network_driver(device.platform.napalm_driver) except ModuleImportError: raise ServiceUnavailable( "NAPALM driver for platform {} not found: {}.".format( device.platform, device.platform.napalm_driver)) # Verify user permission if not request.user.has_perm('dcim.napalm_read'): return HttpResponseForbidden() # 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, username=settings.NAPALM_USERNAME, password=settings.NAPALM_PASSWORD, timeout=settings.NAPALM_TIMEOUT, optional_args=settings.NAPALM_ARGS) 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)) d.close() return Response(response)
def napalm(self, request, pk): """ Execute a NAPALM method on a Device """ device = get_object_or_404(self.queryset, pk=pk) if not device.primary_ip: raise ServiceUnavailable( "This device does not have a primary IP address configured.") if device.platform is None: raise ServiceUnavailable( "No platform is configured for this device.") if not device.platform.napalm_driver: raise ServiceUnavailable( "No NAPALM driver is configured for this device's platform {}." .format(device.platform)) # Check for primary IP address from NetBox object if device.primary_ip: host = str(device.primary_ip.address.ip) else: # Raise exception for no IP address and no Name if device.name does not exist if not device.name: raise ServiceUnavailable( "This device does not have a primary IP address or device name to lookup configured." ) try: # Attempt to complete a DNS name resolution if no primary_ip is set host = socket.gethostbyname(device.name) except socket.gaierror: # Name lookup failure raise ServiceUnavailable( f"Name lookup failure, unable to resolve IP address for {device.name}. Please set Primary IP or setup name resolution." ) # Check that NAPALM is installed try: import napalm from napalm.base.exceptions import ModuleImportError except ImportError: raise ServiceUnavailable( "NAPALM is not installed. Please see the documentation for instructions." ) # Validate the configured driver try: driver = napalm.get_network_driver(device.platform.napalm_driver) except ModuleImportError: raise ServiceUnavailable( "NAPALM driver for platform {} not found: {}.".format( device.platform, device.platform.napalm_driver)) # Verify user permission if not request.user.has_perm('dcim.napalm_read_device'): return HttpResponseForbidden() napalm_methods = request.GET.getlist('method') response = OrderedDict([(m, None) for m in napalm_methods]) 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 request headers for header in request.headers: if header[:9].lower() != 'x-napalm-': continue key = header[9:] 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] # Connect to the device d = driver(hostname=host, username=username, password=password, timeout=settings.NAPALM_TIMEOUT, optional_args=optional_args) try: d.open() except Exception as e: raise ServiceUnavailable( "Error connecting to the device at {}: {}".format(host, 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( method, driver) } except Exception as e: response[method] = { 'error': 'Method {} failed: {}'.format(method, e) } d.close() return Response(response)