python调用ansible api 秘钥密码设置无效

# -*- conding:utf-8 -*-
import json
import os
import sys
import time

from collections import namedtuple
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.inventory import Inventory
from ansible.inventory.group import Group
from ansible.inventory.host import Host
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars import VariableManager
from ansible.executor.playbook_executor import PlaybookExecutor



class ResultsCollector(CallbackBase):
    def __init__(self, *args, **kwargs):
        super(ResultsCollector, self).__init__(*args, **kwargs)
        self.host_ok = {}
        self.host_unreachable = {}
        self.host_failed = {}
    
    def v2_runner_on_unreachable(self, result):
        self.host_unreachable[result._host.get_name()] = result
    
    def v2_runner_on_ok(self, result, *args, **kwargs):
        self.host_ok[result._host.get_name()] = result
    
    def v2_runner_on_failed(self, result, *args, **kwargs):
        self.host_failed[result._host.get_name()] = result
    
    def v2_runner_on_skipped(self, result):
        self.state = 'skipped'
        self.result = result._result

    def v2_runner_on_no_hosts(self, task):
        print('skipping: no hosts matched')

    def v2_playbook_on_task_start(self, task, is_conditional):
        print("TASK [%s]" % task.get_name().strip())

    def v2_playbook_on_play_start(self, play):
        name = play.get_name().strip()
        if not name:
            msg = "PLAY"
        else:
            msg = "PLAY [%s]" % name
    
        print(msg)

    def v2_playbook_on_stats(self, stats):
        hosts = sorted(stats.processed.keys())
        for h in hosts:
            t = stats.summarize(h)
        
            msg = "PLAY RECAP [%s] : %s %s %s %s %s" % (
                h,
                "ok: %s" % (t['ok']),
                "changed: %s" % (t['changed']),
                "unreachable: %s" % (t['unreachable']),
                "skipped: %s" % (t['skipped']),
                "failed: %s" % (t['failures']),
            )
        print(msg)

class MyInventory(Inventory):
    """
    this is my ansible inventory object.
    """
    
    def __init__(self, resource, loader, variable_manager):
        self.resource = resource
        self.inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=[])
        self.gen_inventory()
    
    def my_add_group(self, hosts, groupname, groupvars=None):
        """
        add hosts to a group
        """
        my_group = Group(name=groupname)
        
        # if group variables exists, add them to group
        if groupvars:
            for key, value in groupvars.iteritems():
                my_group.set_variable(key, value)
                
                # add hosts to group
        for host in hosts:
            # set connection variables
            hostname = host.get("hostname")
            hostip = host.get('ip', hostname)
            hostport = host.get("port")
            username = host.get("username")
            password = host.get("password")
            ssh_key = host.get("ssh_key")
            my_host = Host(name=hostname, port=hostport)
            my_host.set_variable('ansible_ssh_host', hostip)
            my_host.set_variable('ansible_ssh_port', hostport)
            my_host.set_variable('ansible_ssh_user', username)
            my_host.set_variable('ansible_ssh_pass', password)
            my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
            
            # set other variables
            for key, value in host.items():
                if key not in ["hostname", "port", "username", "password"]:
                    my_host.set_variable(key, value)
                    # add to group
            my_group.add_host(my_host)
        
        self.inventory.add_group(my_group)
    
    def gen_inventory(self):
        """
        add hosts to inventory.
        """
        if isinstance(self.resource, list):
            self.my_add_group(self.resource, 'default_group')
        elif isinstance(self.resource, dict):
            for groupname, hosts_and_vars in self.resource.items():
                self.my_add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))


class MyRunner(object):
    """
    This is a General object for parallel execute modules.
    """
    
    def __init__(self, resource, *args, **kwargs):
        self.resource = resource
        self.inventory = None
        self.variable_manager = None
        self.loader = None
        self.options = None
        self.passwords = None
        self.callback = None
        self.__initializeData()
        self.results_raw = {}
    
    def __initializeData(self):
        """
        初始化ansible
        """
        Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'timeout', 'remote_user',
                                         'ask_pass', 'private_key_file', 'ssh_common_args', 'ssh_extra_args',
                                         'sftp_extra_args',
                                         'scp_extra_args', 'become', 'become_method', 'become_user', 'ask_value_pass',
                                         'verbosity',
                                         'check', 'listhosts', 'listtasks', 'listtags', 'syntax'])
        
        # initialize needed objects
        self.variable_manager = VariableManager()
        self.loader = DataLoader()
        self.options = Options(connection='smart', module_path='/usr/local/python36/lib/python3.6/site-packages/ansible/modules', forks=100, timeout=10,
                               remote_user='root', ask_pass=False, private_key_file=None, ssh_common_args=None,
                               ssh_extra_args=None,
                               sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None,
                               become_user='root', ask_value_pass=False, verbosity=None, check=False, listhosts=False,
                               listtasks=False, listtags=False, syntax=False)
        
        self.passwords = dict(sshpass=None, becomepass=None)
        self.inventory = MyInventory(self.resource, self.loader, self.variable_manager).inventory
        self.variable_manager.set_inventory(self.inventory)
    
    def run(self, host_list, module_name, module_args):
        """
        run module from andible ad-hoc.
        module_name: ansible module_name
        module_args: ansible module args
        """
        # create play with tasks
        print(host_list, module_name, module_args)
        play_source = dict(
            name="Ansible Play",
            hosts=host_list,
            gather_facts='no',
            tasks=[dict(action=dict(module=module_name, args=module_args))]
        )
        play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader)
        
        tqm = None
        self.callback = ResultsCollector()
        try:
            tqm = TaskQueueManager(
                inventory=self.inventory,
                variable_manager=self.variable_manager,
                loader=self.loader,
                options=self.options,
                passwords=self.passwords,
            )
            tqm._stdout_callback = self.callback
            result = tqm.run(play)
            time.sleep(10)
        finally:
            if tqm is not None:
                tqm.cleanup()

   # def run_playbook(self, host_list, role_name, role_uuid, temp_param):
    def run_playbook(self, hosts, playbookfile, playbookvars):
        """
        run ansible palybook
        """
        try:
            self.callback = ResultsCollector()
            filenames = [playbookfile]  # playbook的路径
            print('ymal file path:%s' % filenames)

            extra_vars = playbookvars  # 额外的参数 sudoers.yml以及模板中的参数,它对应ansible-playbook test.yml --extra-vars "host='aa' name='cc' "
            self.variable_manager.extra_vars = extra_vars
            print('playbook 额外参数:%s' % self.variable_manager.extra_vars)

            executor = PlaybookExecutor(
                playbooks=filenames, inventory=self.inventory, variable_manager=self.variable_manager,
                loader=self.loader,
                options=self.options, passwords=self.passwords,
            )
            executor._tqm._stdout_callback = self.callback
            executor.run()
        except Exception as e:
            print("run_playbook:%s" % e) 
    
#    def run_rule(self, hosts, playbookfile, playbooktag):
#        """
#        run ansible palybook
#        """
#        try:
#            self.callback = ResultsCollector()
#            filenames = [playbookfile]  # playbook的路径
#            print('ymal file path:%s' % filenames)
#
#            extra_vars = {}  # 额外的参数 sudoers.yml以及模板中的参数,它对应ansible-playbook test.yml --extra-vars "host='aa' name='cc' "
#            extra_vars['host'] = hosts
#            self.variable_manager.extra_vars = extra_vars
#            print('playbook 额外参数:%s' % self.variable_manager.extra_vars)
#        
#            self.options = self.options._replace(tags=playbooktag)
##            executor = PlaybookExecutor(
#                playbooks=filenames, inventory=self.inventory, variable_manager=self.variable_manager,
##                loader=self.loader,
#                options=self.options, passwords=self.passwords,
#            )
#            executor._tqm._stdout_callback = self.callback
#            executor.run()
#        except Exception as e:
#            print("run_playbook:%s" % e) 

    def get_result(self):
        self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}}
        for host, result in self.callback.host_ok.items():
            self.results_raw['success'][host] = result._result
        
        for host, result in self.callback.host_failed.items():
            self.results_raw['failed'][host] = result._result['msg']
        
        for host, result in self.callback.host_unreachable.items():
            self.results_raw['unreachable'][host] = result._result['msg']
        
        print("Ansible执行结果集:%s" % json.dumps(self.results_raw, indent=4))
        return json.dumps(self.results_raw, indent=4) 

if __name__ == '__main__':
    res ={
        "app": {
            "hosts": [
                {
                    'hostname': '192.168.176.112'
                }
            ]
        },
        "one": {
            "hosts": [
                {
                    'username': 'root',
                    'hostname': '192.168.1.1',
                    'ip': '192.168.1.1',
                    'ssh_key': '/usr/local/python36/django/key/local', 
                    'password': '12345678', #password 不能认证
                    'port': 22
                }
            ]
       }
    }
    rapi = MyRunner(res)
    rapi.run('one', 'shell', 'ss -tnl')
    rapi.get_result()

python调用ansibleapi ,api版本是2.3的,这段配置的是秘钥的密码:('password': '12345678', #password 不能认证)执行时没有效果,一直卡住不动, 把这段去掉,也就是my_host.set_variable('ansible_ssh_pass', password)的password为None的时候在执行会出现交互模式输入密钥密码,哪里写的有问题吗,或者该怎么写?? 0-0

注:是生成密钥时设置的密码,不是账户的密码

阅读 8.1k
4 个回答

好主意是全用SSH keys进行远程登录.

如果你执意想用username/password方式, 可以通过建立inventory文件的方式存储.默认放到/etc/ansible/hosts下面, 也可以用参数的方式指定-i <path>.

版本 Ansible <2.0:

[all:vars]
ansible_connection=ssh
ansible_ssh_user=用户名 
ansible_ssh_pass=密码

版本 Ansible >=2.0:

[all:vars]
ansible_connection=ssh 
ansible_user=用户名 
ansible_pass=密码

参考:
https://serverfault.com/quest...

新手上路,请多包涵

from ansible import constants as C
C.HOST_KEY_CHECKING = False
加上这段代码,关闭HOST_KEY检查

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题