Ejemplo n.º 1
0
async def snmp_getnext(
    address: str,
    oid: str,
    port: int = 161,
    community: str = "public",
    version: int = SNMP_v2c,
    timeout: float = 10,
    bulk: bool = False,
    filter: Optional[Callable[[bytes, Any], bool]] = None,
    max_repetitions: int = BULK_MAX_REPETITIONS,
    only_first: bool = False,
    tos: Optional[int] = None,
    udp_socket: Optional[UDPSocket] = None,
    max_retries: int = 0,
    raw_varbinds: bool = False,
    display_hints: Optional[Dict[str,
                                 Optional[Callable[[str, bytes],
                                                   Union[str,
                                                         bytes]]]]] = None,
    response_parser: Optional[_ResponseParser] = None,
    rate_limit: Optional[AsyncRateLimit] = None,
):
    """
    Perform SNMP GETNEXT/BULK request and returns Future to be used
    inside async coroutine
    """
    def true(x, y):
        return True

    logger.debug("[%s] SNMP GETNEXT %s", address, oid)
    if not filter:
        filter = true
    poid = oid + "."
    result = []
    parser = _get_parser(response_parser, raw_varbinds)
    with UDPSocketContext(udp_socket, tos=tos) as sock:
        first_oid = None
        last_oid = None
        while True:
            if rate_limit:
                await rate_limit.wait()
            # Get PDU
            if bulk:
                pdu = getbulk_pdu(
                    community,
                    oid,
                    max_repetitions=max_repetitions or BULK_MAX_REPETITIONS,
                    version=version,
                )
            else:
                pdu = getnext_pdu(community, oid, version=version)
            # Send request and wait for response
            try:
                data, addr = await asyncio.wait_for(
                    sock.send_and_receive(pdu, (address, port)), timeout)
            except asyncio.TimeoutError:
                if not max_retries:
                    raise SNMPError(code=TIMED_OUT, oid=oid)
                max_retries -= 1
                continue
            except socket.gaierror as e:
                logger.debug("[%s] Cannot resolve address: %s", address, e)
                raise SNMPError(code=UNREACHABLE, oid=oid)
            except OSError as e:
                logger.debug("[%s] Socket error: %s", address, e)
                raise SNMPError(code=UNREACHABLE, oid=oid)
            # Parse response
            try:
                resp = parser(data, display_hints)
            except ValueError:
                raise SNMPError(code=BER_ERROR, oid=oid)
            if resp.error_status == NO_SUCH_NAME:
                # NULL result
                break
            elif resp.error_status == END_OID_TREE:
                # End OID Tree
                return result
            elif resp.error_status != NO_ERROR:
                # Error
                raise SNMPError(code=resp.error_status, oid=oid)
            elif not raw_varbinds:
                # Success value
                for oid, v in resp.varbinds:
                    if oid == first_oid:
                        logger.warning("[%s] GETNEXT Oid wrap detected",
                                       address)
                        return result
                    elif oid.startswith(poid) and not (
                            only_first and result) and oid != last_oid:
                        # Next value
                        if filter(oid, v):
                            result += [(oid, v)]
                        last_oid = oid
                        first_oid = first_oid or oid
                    else:
                        logger.debug("[%s] GETNEXT result: %s", address,
                                     result)
                        return result
            else:
                # Raw varbinds
                for oid, v in resp.varbinds:
                    s_oid = smart_text(oid)
                    if s_oid.startswith(poid) and not (
                            only_first and result) and oid != last_oid:
                        # Next value
                        if filter(s_oid, v):
                            result += [(oid, v)]
                        last_oid = oid
                        first_oid = first_oid or oid
                    else:
                        logger.debug("[%s] GETNEXT result: %s", address,
                                     result)
                        return result
Ejemplo n.º 2
0
Archivo: snmp.py Proyecto: skripkar/noc
def snmp_getnext(address,
                 oid,
                 port=161,
                 community="public",
                 version=SNMP_v2c,
                 timeout=10,
                 bulk=False,
                 filter=None,
                 max_repetitions=BULK_MAX_REPETITIONS,
                 only_first=False,
                 tos=None,
                 ioloop=None,
                 udp_socket=None,
                 max_retries=0,
                 raw_varbinds=False):
    """
    Perform SNMP GETNEXT/BULK request and returns Future to be used
    inside @tornado.gen.coroutine
    """
    def true(x, y):
        return True

    def close_socket():
        if udp_socket:
            sock.settimeout(prev_timeout)
        else:
            sock.close()

    logger.debug("[%s] SNMP GETNEXT %s", address, oid)
    if not filter:
        filter = true
    poid = oid + "."
    result = []
    if udp_socket:
        sock = udp_socket
        prev_timeout = sock.get_timeout()
    else:
        sock = UDPSocket(ioloop=ioloop, tos=tos)
    sock.settimeout(timeout)
    last_oid = None
    while True:
        # Get PDU
        if bulk:
            pdu = getbulk_pdu(community,
                              oid,
                              max_repetitions=max_repetitions
                              or BULK_MAX_REPETITIONS,
                              version=version)
        else:
            pdu = getnext_pdu(community, oid, version=version)
        # Send request and wait for response
        try:
            yield sock.sendto(pdu, (address, port))
            data, addr = yield sock.recvfrom(4096)
        except socket.timeout:
            if not max_retries:
                close_socket()
                raise SNMPError(code=TIMED_OUT, oid=oid)
            max_retries -= 1
            continue
        except socket.gaierror as e:
            logger.debug("[%s] Cannot resolve address: %s", address, e)
            close_socket()
            raise SNMPError(code=UNREACHABLE, oid=oid)
        except socket.error as e:
            logger.debug("[%s] Socket error: %s", address, e)
            close_socket()
            raise SNMPError(code=UNREACHABLE, oid=oid)
        # Parse response
        try:
            if raw_varbinds:
                resp = parse_get_response_raw(data)
            else:
                resp = parse_get_response(data)
        except ValueError:
            raise SNMPError(code=BER_ERROR, oid=oid)
        if resp.error_status == NO_SUCH_NAME:
            # NULL result
            break
        elif resp.error_status != NO_ERROR:
            # Error
            close_socket()
            raise SNMPError(code=resp.error_status, oid=oid)
        else:
            # Success value
            for oid, v in resp.varbinds:
                if oid.startswith(poid) and not (only_first and
                                                 result) and oid != last_oid:
                    # Next value
                    if filter(oid, v):
                        result += [(oid, v)]
                    last_oid = oid
                else:
                    logger.debug("[%s] GETNEXT result: %s", address, result)
                    close_socket()
                    raise Return(result)
    close_socket()
Ejemplo n.º 3
0
async def snmp_count(
    address,
    oid,
    port=161,
    community="public",
    version=SNMP_v2c,
    timeout=10,
    bulk=False,
    filter=None,
    max_repetitions=BULK_MAX_REPETITIONS,
    tos=None,
    udp_socket: Optional[UDPSocket] = None,
    rate_limit: Optional[AsyncRateLimit] = None,
):
    """
    Perform SNMP get request and returns Future to be used
    inside async coroutine
    """
    def true(x, y):
        return true

    logger.debug("[%s] SNMP COUNT %s", address, oid)
    if not filter:
        filter = true
    poid = oid + "."
    result = 0
    with UDPSocketContext(udp_socket, tos=tos) as sock:
        while True:
            if rate_limit:
                await rate_limit.wait()
            # Get PDU
            if bulk:
                pdu = getbulk_pdu(community,
                                  oid,
                                  max_repetitions=max_repetitions,
                                  version=version)
            else:
                pdu = getnext_pdu(community, oid, version=version)
            # Send request and wait for response
            try:
                data, addr = await asyncio.wait_for(
                    sock.send_and_receive(pdu, (address, port)), timeout)
            except asyncio.TimeoutError:
                raise SNMPError(code=TIMED_OUT, oid=oid)
            except socket.gaierror as e:
                logger.debug("[%s] Cannot resolve address: %s", address, e)
                raise SNMPError(code=UNREACHABLE, oid=oid)
            except OSError as e:
                logger.debug("[%s] Socket error: %s", address, e)
                raise SNMPError(code=UNREACHABLE, oid=oid)
            # Parse response
            try:
                resp = parse_get_response(data)
            except ValueError:
                raise SNMPError(code=BER_ERROR, oid=oid)
            if resp.error_status == NO_SUCH_NAME:
                # NULL result
                break
            elif resp.error_status != NO_ERROR:
                # Error
                raise SNMPError(code=resp.error_status, oid=oid)
            else:
                # Success value
                for oid, v in resp.varbinds:
                    if oid.startswith(poid):
                        # Next value
                        if filter(oid, v):
                            result += 1
                    else:
                        logger.debug("[%s] COUNT result: %s", address, result)
                        sock.close()
                        return result
Ejemplo n.º 4
0
Archivo: snmp.py Proyecto: skripkar/noc
def snmp_count(address,
               oid,
               port=161,
               community="public",
               version=SNMP_v2c,
               timeout=10,
               bulk=False,
               filter=None,
               max_repetitions=BULK_MAX_REPETITIONS,
               tos=None,
               ioloop=None,
               udp_socket=None):
    """
    Perform SNMP get request and returns Future to be used
    inside @tornado.gen.coroutine
    """
    def true(x, y):
        return true

    logger.debug("[%s] SNMP COUNT %s", address, oid)
    if not filter:
        filter = true
    poid = oid + "."
    result = 0
    if udp_socket:
        sock = udp_socket
        prev_timeout = sock.get_timeout()
    else:
        sock = UDPSocket(ioloop=ioloop, tos=tos)
    sock.settimeout(timeout)
    while True:
        # Get PDU
        if bulk:
            pdu = getbulk_pdu(community,
                              oid,
                              max_repetitions=max_repetitions,
                              version=version)
        else:
            pdu = getnext_pdu(community, oid, version=version)
        # Send request and wait for response
        try:
            yield sock.sendto(pdu, (address, port))
            data, addr = yield sock.recvfrom(4096)
        except socket.timeout:
            raise SNMPError(code=TIMED_OUT, oid=oid)
        except socket.gaierror as e:
            logger.debug("[%s] Cannot resolve address: %s", address, e)
            raise SNMPError(code=UNREACHABLE, oid=oid)
        except socket.error as e:
            logger.debug("[%s] Socket error: %s", address, e)
            raise SNMPError(code=UNREACHABLE, oid=oid)
        finally:
            if udp_socket:
                sock.settimeout(prev_timeout)
            else:
                sock.close()
        # Parse response
        try:
            resp = parse_get_response(data)
        except ValueError:
            raise SNMPError(code=BER_ERROR, oid=oid)
        if resp.error_status == NO_SUCH_NAME:
            # NULL result
            break
        elif resp.error_status != NO_ERROR:
            # Error
            raise SNMPError(code=resp.error_status, oid=oid)
        else:
            # Success value
            for oid, v in resp.varbinds:
                if oid.startswith(poid):
                    # Next value
                    if filter(oid, v):
                        result += 1
                else:
                    logger.debug("[%s] COUNT result: %s", address, result)
                    sock.close()
                    raise Return(result)