ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Ansible API 2.0 研究

Ansible API 2.0 研究

原创 Linux操作系统 作者:bestpaydata 时间:2016-03-25 18:24:23 0 删除 编辑
编者:Matlon    
      Ansible 作为新出现的运维工具,是基于Python开发的,糅合了众多老牌运维工具的优点,实现了批量操作系统配置、批量程序的部署、批量运行命令等功能。在几个月前发布了2.0版本,变化比较大,大部分被重写,所以许多地方需要重新研究。

      如下,我们先看一下之前API的部分代码:

  1. import ansible.runner
  2. runner = ansible.runner.Runner(
  3.     module_name='ping',
  4.     module_args='',
  5.     pattern='web*',
  6.     forks=10)datastructure = runner.run()

使用runner 模块就可以调用ansible,执行一系列任务,但在2.0,这就变得比较困难了,首先看如下2.0的API的目录结构:

在2.0中,仍然使用和之前相同的run()方法,但其不在runner模块中了,而在executor模块,它的基本类名是PlaybookExecutor,部分代码如下:

点击(此处)折叠或打开

  1. def __init__(self, playbooks, inventory, variable_manager, loader, options, passwords):

  2.         self._playbooks = playbooks #获取playbook的地址

  3.         self._inventory = inventory #获取主机列表

  4.         self._variable_manager = variable_manager #获取额外的变量

  5.         self._loader = loader

  6.         self._options = options

  7.         self.passwords = passwords

  8.         self._unreachable_hosts = dict()

  9.         if options.listhosts or options.listtasks or options.listtags or options.syntax

  10.            self._tqm = None

  11.         else:

  12.            self._tqm = TaskQueueManager(inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=self.passwords #通过调用任务管理器来执行playbook

所有的调度逻辑由run()来实现,playbook中的task由TaskQueueManager与taskExecutor来管理执行,暂时不需要理解,我们现在只需要去了解inventory和playbook如何获取,就可以简单执行,进到inventory目录,找到它的主要模块,

点击(此处)折叠或打开

  1. def __init__(self, loader,variable_manager,host_list=C.DEFAULT_HOST_LIST):

inventory 可以传参,参数的格式和类型需要考虑,解析如下:

#如果是str,根据逗号来区分并且去除空格,放到list里面

  1. if isinstance(host_list, string_types):
  2.             if "," in host_list:
  3.                 host_list = host_list.split(",")
  4.                 host_list = [ h for h in host_list if h and h.strip() ]

#host_list没有传入参数时,默认是去找/etc/ansible/hosts文件的

  1. if host_list is None:
  2.             pass

#如果是list类型,直接解析

  1. elif isinstance(host_list, list):
  2.             for h in host_list:
  3.                 (host, port) = parse_address(h, allow_ranges=False)
  4.                 all.add_host(Host(host, port))

#如果你指定host位置,它会从你的指定文件读入的,如果是hosts脚本,需返回一个json格式的对象。

  1. elif self._loader.path_exists(host_list):
  2.             if self.is_directory(host_list):
  3.                 # Ensure basedir is inside the directory
  4.                 host_list = os.path.join(self.host_list, "")
  5.                 self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list) #group一般设为all、ungrouped
  6.             else:
  7.                 self.parser = get_file_parser(host_list, self.groups, self._loader)
  8.                 vars_loader.add_directory(self.basedir(), with_subdir=True)

综上:我们只要给inventory传入特定格式的参数,就可以处理host_list

之后,再看playbook如何传入,进入playbook 目录,找到playbook的初始化模块,有一个load()函数,就是获取playbook的文件路径,来加载playbook,如下:

  1. def load(file_name, variable_manager=None, loader=None):
  2.         pb = Playbook(loader=loader)
  3.         pb._load_playbook_data(file_name=file_name, variable_manager=variable_manager)
  4.         return pb

当然,也可以运行单个play,在playbook目录可以看到有一个play的模块,同样是load方法,只不过它获取的是一个dict类型对象,如下:

  1. play_data = dict(
  2.         name = "Ansible play",
  3.         hosts = "localhost",
  4.         tasks = [
  5.                   dict(action=dict(module='shell',args='ls'),register='shell_out')
  6.                   ]
  7.       )

  8. play = Play.load(play_data,variable_manager=variable_manager,loader=loader)

最终,可以得到如下API脚本:

点击(此处)折叠或打开

  1. #!/bin/env python
  2. import os
  3. import sys
  4. import json
  5. from collections import namedtuple
  6. from ansible.parsing.dataloader import DataLoader
  7. from ansible.vars import VariableManager
  8. from ansible.inventory import Inventory
  9. from ansible.executor.playbook_executor import PlaybookExecutor
  10. def install(request):
  11.         if 'ip' in request.GET:
  12.                 ip = request.GET['ip']
  13.                 host = []
  14.                 host.append(ip) #传入一个host列表
  15.                 variable_manager = VariableManager()
  16.                 loader = DataLoader()
  17.                 inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host)
  18.                 playbook_path = '/etc/ansible/main.yml #传入一个playbook路径
  19.                 Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file','ssh_common_args','ssh_extra_args','sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])
  20.                 options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote_user='root, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=None, become_user='root', verbosity=None, check=False)
                    passwords = {}
                    pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords)
                    results =  pbex.run()  #返回的结果是数字,不同的结果对应不同的数字  
                    return 1   
           
            else:
                    return  0


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30109892/viewspace-2063898/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-01-19

  • 博文量
    126
  • 访问量
    1055720