Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)