示例#1
0
def basic_demo():
    """
    Enable this to be run as a CLI script, as well as used as a library.
    Mostly intended for testing or a basic demo.
    """
    # Get the command-line arguments
    parser = argparse.ArgumentParser(
        description='Perform SNMP discovery on a host, \
    returning its data in a single structure.')
    parser.add_argument(
        '--hostname',
        type=str,
        action='store',
        default='localhost',
        help=
        'The hostname or address to perform discovery on. Default: localhost')
    parser.add_argument('--community',
                        type=str,
                        action='store',
                        dest='community',
                        default='public',
                        help='SNMP v2 community string. Default: public')
    parser.add_argument(
        '--file',
        type=str,
        action='store',
        dest='filepath',
        default=None,
        help='Filepath to write the results to. Default: STDOUT.')
    parser.add_argument('--debug',
                        action='store_true',
                        help='Enable debug logging')
    args = parser.parse_args()
    # Set debug logging, if requested
    if args.debug:
        logger = create_logger(loglevel="debug")
    # Normal logging if we're writing to a file
    elif args.filepath:
        logger = create_logger()
    # Suppress INFO output if we're returning it to STDOUT:
    # don't require the user to filter the output to make it useful.
    else:
        logger = create_logger(loglevel="warning")
    # Perform SNMP discovery on a device,
    # sending the result to STDOUT or a file, depending on what the user told us.
    if args.filepath:
        netdescribe.files.snmp_to_json(args.hostname, args.community,
                                       args.filepath, logger)
    else:
        netdescribe.stdout.snmp_to_json(args.hostname, args.community, logger)
示例#2
0
def explore_device(hostname: str,
                   logger: Optional[logging.Logger] = None,
                   community: str = 'public',
                   port: int = 161) -> Union[None, Brocade, Linux, Mib2]:
    '''
    Build up a picture of a device via SNMP queries.
    Return the results as a nest of dicts:
    - sysinfo: output of identify_host()
    - network: output of discover_host_networking()
    '''
    # Ensure we have a logger
    if not logger:
        logger = create_logger()
    # Now get to work
    logger.info('Performing discovery on %s', hostname)
    # Create an object to represent this device,
    # taking its SNMP capabilities into account
    try:
        device: Union[None, Brocade, Linux,
                      Mib2] = create_device(hostname, logger, community, port)
        if device:
            # Perform discovery as appropriate to this device type
            device.discover()
            # Return the device object, complete with its discovered data
            return device
        return None
    except RuntimeError as err:
        logger.error('Error caught: %s', str(err))
        return None
def main(args):
    "Replicate ThousandEyes data to Syscat"
    # Setup and configuration
    logger = create_logger(loglevel=args.loglevel)
    te_api = ApiServer(username=args.te_user, api_key=args.te_key)
    syscat = Syscat(fqdn=args.syscat_fqdn, port=args.syscat_port)
    ## Agents
    logger.info('Retrieving a list of agents from ThousandEyes')
    agents = map(lambda x: make_agent(x, logger),
                 te_api.get_list('agents')['agents'])
    # Individual agents
    for agent in agents:
        logger.info('Adding {} {} with agent ID {}'.format(
            agent.syscat_type, agent.agentname, agent.agentid))
        agent.store_in_syscat(syscat)
        if agent.syscat_type == 'thousandeyesEnterpriseClusters':
            # Add cluster members
            details = te_api.get_details('agents', agent.agentid)['agents'][0]
            logger.debug('agent details: {}'.format(details))
            logger.info('Enumerating members')
            for member in details['clusterMembers']:
                logger.debug('clusterMember details: {}'.format(member))
                logger.info('Adding clusterMember {}'.format(member['name']))
                EnterpriseClusterMember(
                    name=member['name'],
                    ipaddresses=member['ipAddresses'],
                    publicipaddresses=member['publicIpAddresses'],
                    prefix=member['prefix'],
                    network=member['network'],
                    agentstate=member['agentState']).store_in_syscat(
                        syscat, agent)
            # Add tests
            logger.info('Enumerating tests')
            for test in details['tests']:
                logger.debug('Test details: {}'.format(test))
                logger.info('Adding test {}'.format(test['testName']))
                if 'modifiedBy' not in test:
                    test['modifiedBy'] = ''
                if 'modifiedDate' not in test:
                    test['modifiedDate'] = ''
                GenericTest(
                    testname=test['testName'],
                    testid=test['testId'],
                    test_type=test['type'],
                    enabled=test['enabled'],
                    savedevent=test['savedEvent'],
                    interval=test['interval'],
                    modifiedby=test['modifiedBy'],
                    modifieddate=test['modifiedDate'],
                    createdby=test['createdBy'],
                    createddate=test['createdDate']).store_in_syscat(syscat)
                syscat.link_resources(
                    '/{ttype}/{tuid}/Agents'.format(
                        ttype='thousandeyesTests',
                        tuid=syscat_utils.sanitise_uid(test['testName'])),
                    '/{atype}/{auid}'.format(atype=agent.syscat_type,
                                             auid=syscat_utils.sanitise_uid(
                                                 agent.agentname)))
示例#4
0
def main(syscat_url, community, loglevel=logging.INFO):
    """
    Wrapper around discover_into_syscat.
    """
    logger = create_logger(loglevel=loglevel)
    logger.info('Beginning discovery')
    response = requests.get('{}/raw/v1/devices'.format(syscat_url))
    if response.status_code == 200:
        for device in response.json():
            discover_device(syscat_url, community, logger, device)
    else:
        logger.error('Initial query failed: {} - {}'.format(response.status_code,
                                                            response.text))
示例#5
0
def snmp_to_json(target, community, logger=None):
    """
    Explore a device via SNMP, and return the results to STDOUT in JSON.
    """
    # Ensure we have a logging object.
    # Normally I'd default the loglevel to INFO, but this function will be more
    # useful if its output can be consumed directly, without having to filter
    # out any log messages.
    if logger:
        slogger = logger
    else:
        slogger = create_logger(loglevel="warn")
    # Perform SNMP discovery on a device and print the result to STDOUT.
    # Do basic pretty-printing of the output, for human-readability.
    response = device_discovery.explore_device(target,
                                               slogger,
                                               community=community)
    print(response)
def discover_into_syscat(
        address,  # IP address, FQDN or otherwise resolvable address
        name=None,  # Name of target device, to override the discovered one
        use_sysname=False,  # Use the discovered sysName as the Syscat UID
        snmpcommunity="public",
        syscat_url="http://localhost:4950",  # Default base URL for Syscat
        loglevel="info",  # Default loglevel
        logger_arg=None):
    """
    Ensure that there's an entry in Syscat for the device we just discovered.
    Update existing instances, and return a dict describing any updates.
    Return True if the result was a new entry; otherwise, return a dict describing the updates.
    Assumes version 1 of the Syscat API.
    Structure of the return value:
    - system
        - <attribute-name>
            - existing: <value currently in Syscat>
            - discovered: <value discovered just now>
    """
    # Establish logging
    if logger_arg:
        logger = logger_arg
    else:
        logger = create_logger(loglevel=loglevel)
        logger.info("Performing discovery on device at %s", address)
    # Perform discovery
    response = netdescribe.snmp.device_discovery.explore_device(
        address, logger, snmpcommunity)
    if not response:
        logger.error('Failed to perform discovery on device at address %s',
                     address)
        return False
    logger.debug("Result of discovery was:\n%s", response.as_json())
    # Get the "raw" dict of namedtuples, not the JSON transformation
    device = response.as_dict()
    # Resolve the device's UID
    if name:
        uid = name
    elif use_sysname and device['system'][
            'sysName'] and device['system']['sysName'] != "":
        uid = device['system']['sysName']
    else:
        uid = address
    logger.debug("Using name '%s' for device", uid)
    # Is it already there?
    existing_response = requests.get("%s/raw/v1/devices/%s" %
                                     (syscat_url, uid))
    # No existing entry; create one
    if existing_response.json() == []:
        logger.debug("%s is not present in Syscat; creating it.", uid)
        # Create the device entry itself
        add_device(uid, device['system']['sysName'],
                   device['system']['sysDescr'], syscat_url, logger)
        created_new_device = True
    # We already have one of these; log the fact and ensure it's up to date
    elif existing_response.json() != []:
        logger.debug(
            "%s is already present in Syscat. Ensuring it's up to date...",
            uid)
        created_new_device = False
        # Compare the system attributes
        diffs = compare_discovered_device_to_syscat(device,
                                                    existing_response.json(),
                                                    logger)
        # Perform any necessary updates to the device's own attributes
        if diffs and 'system' in diffs:
            devices_url = "%s/raw/v1/devices" % syscat_url
            payload = {}
            for attr, vals in diffs['system'].items():
                payload[attr] = vals['discovered']
            logger.info('Updating system for %s with details %s', uid, payload)
            requests.put('%s/%s' % (devices_url, uid), data=payload)
        # No updates needed. Do mention this, so the user knows where we're up to
        else:
            logger.debug('No system updates needed.')
    # Something else happened.
    else:
        logger.critical("Syscat returned an unexpected result: %s %s",
                        existing_response.status_code, existing_response.text)
        sys.exit(1)
    # Now ensure its interfaces are correctly described
    populate_interfaces_flat(uid,
                             device['interfaces'],
                             syscat_url,
                             logger,
                             newdevice=created_new_device)
    # Return a report on what we updated.
    if created_new_device:
        return True
    return diffs