Exemplo n.º 1
0
async def init_hosts(**kwargs):
    """Process list of devices to gather data from.
    This involves creating a node for each device listed, and connecting to
    those devices and initializing state about those devices
    """

    nodes = {}

    inventory = kwargs.pop('inventory', None)
    if not inventory:
        ans_inventory = kwargs.pop('ans_inventory', None)
    else:
        _ = kwargs.pop('ans_inventory', None)

    namespace = kwargs.pop('namespace', 'default')
    passphrase = kwargs.pop('passphrase', None)
    ssh_config_file = kwargs.pop('ssh_config_file', None)
    jump_host = kwargs.pop('jump_host', None)
    ignore_known_hosts = kwargs.pop('ignore_known_hosts', False)

    if kwargs:
        logger.error(f'Received unrecognized keywords {kwargs}, aborting')
        sys.exit(1)

    if inventory:
        hostsconf = get_hostsdata_from_hostsfile(inventory)
    else:
        hostsconf = yaml.safe_load('\n'.join(
            convert_ansible_inventory(ans_inventory, namespace)))

    if not hostsconf:
        logger.error("No hosts specified in inventory file")
        print("ERROR: No hosts specified in inventory file")
        sys.exit(1)

    for namespace in hostsconf:
        if "namespace" not in namespace:
            logger.warning('No namespace specified, assuming "default"')
            nsname = "default"
        else:
            nsname = namespace["namespace"]

        tasks = []
        for host in namespace.get("hosts", []):
            entry = host.get("url", None)
            if entry:
                words = entry.split()
                result = urlparse(words[0])

                username = result.username
                password = result.password or "vagrant"
                port = result.port
                host = result.hostname
                devtype = None
                keyfile = None

                for i in range(1, len(words[1:]) + 1):
                    if words[i].startswith('keyfile'):
                        keyfile = words[i].split("=")[1]
                    elif words[i].startswith('devtype'):
                        devtype = words[i].split("=")[1]

                newnode = Node()
                tasks += [
                    newnode._init(
                        address=host,
                        username=username,
                        port=port,
                        password=password,
                        passphrase=passphrase,
                        transport=result.scheme,
                        devtype=devtype,
                        ssh_keyfile=keyfile,
                        ssh_config_file=ssh_config_file,
                        jump_host=jump_host,
                        namespace=nsname,
                        ignore_known_hosts=ignore_known_hosts,
                    )
                ]

        if not tasks:
            logger.error("No hosts detected in provided inventory file")
            return []

        for f in asyncio.as_completed(tasks):
            newnode = await f
            if newnode.devtype is None:
                logger.error(
                    "Unable to determine device type for {}".format(host))
            else:
                logger.info(f"Added node {newnode.hostname}")

            nodes.update({"{}.{}".format(nsname, newnode.hostname): newnode})

    return nodes
Exemplo n.º 2
0
async def init_hosts(**kwargs):
    """Process list of devices to gather data from.
    This involves creating a node for each device listed, and connecting to
    those devices and initializing state about those devices
    """

    nodes = {}

    inventory = kwargs.pop('inventory', None)
    if not inventory:
        ans_inventory = kwargs.pop('ans_inventory', None)
    else:
        _ = kwargs.pop('ans_inventory', None)
        ans_inventory = None

    namespace = kwargs.pop('namespace', 'default')
    passphrase = kwargs.pop('passphrase', None)
    ssh_config_file = kwargs.pop('ssh_config_file', None)
    jump_host = kwargs.pop('jump_host', None)
    jump_host_key_file = kwargs.pop('jump_host_key_file', None)
    ignore_known_hosts = kwargs.pop('ignore_known_hosts', False)
    user_password = kwargs.pop('password', None)

    if kwargs:
        logger.error(f'Received unrecognized keywords {kwargs}, aborting')
        sys.exit(1)

    if inventory:
        hostsconf = get_hostsdata_from_hostsfile(inventory)
    else:
        hostsconf = yaml.safe_load('\n'.join(
            convert_ansible_inventory(ans_inventory, namespace)))

    if not hostsconf:
        logger.error("No hosts specified in inventory file")
        print("ERROR: No hosts specified in inventory file")
        sys.exit(1)

    if jump_host_key_file:
        if not jump_host:
            logger.error("Jump host key file specified without jump host")
            print("ERROR: Jump host key file specified without jump host")
            sys.exit(1)
        else:
            if not os.access(jump_host_key_file, os.F_OK):
                logger.error(
                    f"Jump host key file {jump_host_key_file} does not exist")
                print(f"ERROR: Jump host key file {jump_host_key_file} "
                      f"does not exist")
                sys.exit(1)
            if not os.access(jump_host_key_file, os.R_OK):
                logger.error(
                    f"Jump host key file {jump_host_key_file} not readable")
                print(f"ERROR: Jump host key file {jump_host_key_file} "
                      f"not readable")
                sys.exit(1)

    for namespace in hostsconf:
        nsname = namespace["namespace"]

        tasks = []
        hostlist = namespace.get("hosts", [])
        if not hostlist:
            logger.error(f'No hosts in namespace {nsname}')
            continue

        for host in hostlist:
            if not isinstance(host, dict):
                logger.error(f'Ignoring invalid host specification: {host}')
                continue
            entry = host.get("url", None)
            if entry:
                words = entry.split()
                result = urlparse(words[0])

                username = result.username
                password = result.password or user_password or "vagrant"
                port = result.port
                host = result.hostname
                devtype = None
                keyfile = None

                try:
                    for i in range(1, len(words[1:]) + 1):
                        if words[i].startswith('keyfile'):
                            keyfile = words[i].split("=")[1]
                        elif words[i].startswith('devtype'):
                            devtype = words[i].split("=")[1]
                        elif words[i].startswith('username'):
                            username = words[i].split("=")[1]
                        elif words[i].startswith('password'):
                            password = words[i].split("=")[1]
                except IndexError:
                    logger.error(f'Invalid key/value {words}, missing "="')
                    logger.error(f'Ignoring node {host}')
                    continue

                newnode = Node()
                tasks += [
                    newnode._init(
                        address=host,
                        username=username,
                        port=port,
                        password=password,
                        passphrase=passphrase,
                        transport=result.scheme,
                        devtype=devtype,
                        ssh_keyfile=keyfile,
                        ssh_config_file=ssh_config_file,
                        jump_host=jump_host,
                        jump_host_key_file=jump_host_key_file,
                        namespace=nsname,
                        ignore_known_hosts=ignore_known_hosts,
                    )
                ]
            else:
                logger.error(f'Ignoring invalid host specification: {entry}')

        if not tasks:
            logger.error("No hosts detected in provided inventory file")
            return []

        for f in asyncio.as_completed(tasks):
            newnode = await f
            if newnode.devtype is None:
                logger.error(
                    "Unable to determine device type for {}:{}".format(
                        newnode.address, newnode.port))
            else:
                logger.info(f"Added node {newnode.hostname}:{newnode.port}")

            nodes.update({"{}.{}".format(nsname, newnode.hostname): newnode})

    return nodes