示例#1
0
def log_yaml_inventory(label, inventory):
    """Log yaml inventory but mask passwords

    :param inventory: A dictionary of the ansible inventory
    """
    alpha = inventory.get('alpha')
    hosts_dict = alpha.get('hosts')
    vars_dict = alpha.get('vars')
    redact_key_list = ['ansible_become_pass', 'ansible_ssh_pass']

    # pylint: disable=unused-variable
    for host, host_dict in iteritems(hosts_dict):
        host_dict = redact_dict(redact_key_list, host_dict)

    vars_dict = redact_dict(redact_key_list, vars_dict)

    log.debug('%s:\n%s', label, yaml.dump(inventory))
    return inventory
示例#2
0
def process_ping_output(out_lines):
    """Find successful hosts from the output of a ping command.

    Use this function by using ansible to run echo "Hello" on remote
    hosts, then sending the output to this function.

    :param out_lines: an iterator returning lines of Ansible output.
    :returns: the hosts that pinged successfully, as a set and those that
        failed, as a set.
    """

    success_hosts = set()
    failed_hosts = set()

    # Ansible output has the format
    # host | UNREACHABLE! => {
    #     "changed": false,
    #     "msg": "Failed to connect to the host via ssh ...",
    #     "unreachable": true
    #    }
    #   hostname | SUCCESS | rc=0 >>
    #   Hello
    # with the above two lines repeated for each host
    for line in out_lines:
        ansi_escape = re.compile(r'\x1b[^m]*m')
        line = ansi_escape.sub('', line)
        pieces = line.split('|')
        if len(pieces) == 3 and pieces[1].strip() == 'SUCCESS':
            success_hosts.add(pieces[0].strip())
        elif len(pieces) == 3 and pieces[1].strip() == 'FAILED':
            failed_hosts.add(pieces[0].strip())
        elif len(pieces) == 2 and pieces[1].strip().startswith('UNREACHABLE'):
            failed_hosts.add(pieces[0].strip())

    log.debug('Ping log reached hosts: %s', success_hosts)
    log.debug('Ping log did not reached hosts: %s', failed_hosts)

    return success_hosts, failed_hosts
示例#3
0
def run_ansible_with_vault(cmd_string, vault_pass, env=None, log_path=None,
                           log_to_stdout=True, ansible_verbosity=0):
    """ Runs ansible command allowing for password to be provided after
    process triggered.

    Returns after the process completes.

    :param cmd_string: the command to run.
    :param vault_pass: the password to the user's Ansible Vault.
    :param env: the environment to run the subprocess in.
    :param log_path: a path to write the process's log to. Defaults to
        'XDG_DATA_HOME/rho/ansible_log'.
    :param log_to_stdout: if True, write Ansible's log to stdout. Defaults to
        True.
    :param ansible_verbosity: the number of v's of Ansible verbosity.
    :returns: the popen.spawn object for the process.
    """

    # pexpect provides the ability to send the process's output to a
    # single Python file object. We want to send it to a file and
    # maybe also stdout. The solution is to have pexpect log to the
    # file and then use 'tail -f' to copy that to stdout.

    if not log_path:
        log_path = ANSIBLE_LOG_PATH

    if ansible_verbosity:
        cmd_string = cmd_string + ' -' + 'v' * ansible_verbosity

    result = None
    try:
        utilities.ensure_data_dir_exists()
        with open(log_path, 'wb') as logfile:
            pass
        with open(log_path, 'r+b') as logfile:
            log.debug('Running Ansible: %s', cmd_string)
            child = pexpect.spawn(cmd_string, timeout=None,
                                  env=env)

            if log_to_stdout:
                utilities.threaded_tailing(log_path, ansible_verbosity)

            result = child.expect('Vault password:'******'s Vault
            # password to Ansible, so we don't log the password.
            child.logfile = logfile
            last_pos = logfile.tell()

            i = child.expect([pexpect.EOF, 'Enter passphrase for key .*:',
                              'you want to continue connecting (yes/no)?'])
            while i:
                new_pos = logfile.tell()
                logfile.seek(last_pos)
                logfile_lines = logfile.readlines()
                log.info(logfile_lines)
                print(logfile_lines[-1].replace('\r\n', ''))
                logfile.seek(new_pos)
                last_pos = new_pos
                child.logfile = None
                # Ansible has already printed a prompt; it would be
                # confusing if getpass printed another one.
                child.sendline(getpass(''))
                child.logfile = logfile
                i = child.expect([pexpect.EOF, 'Enter passphrase for key .*:',
                                  'you want to continue connecting (yes/no)?'])

            if child.isalive():
                child.wait()
            if log_to_stdout:
                time.sleep(2)

        return child
    except pexpect.EOF:
        print(str(result))
        print('pexpect unexpected EOF')
    except pexpect.TIMEOUT:
        print(str(result))
        print('pexpect timed out')