Ansible基於服務樹進行分組全量接口調用

Ansible APi
說明
品茶:代碼是基於我們的服務樹結構進行構建,如果需要自己構建相應服務樹則可以根據group host inventory進行自行構建。我們中帶有中文,所以命令行模式需要2.0纔可以調中文,1.9需要改代碼。直接調模塊不受影響。

Info
ansible2.0更貼近於ansible cli的常用命令執行方式,不同於上一版本只能發送單個命令或playbook;而更推薦用戶在調用ansibleAPI的時候,將playbook的每個task拆分出來,獲取每個task的結果。能夠跟靈活處理在執行批量作業過程中的各種反饋。

Info 2
將執行操作的隊列模型,包含各類環境參數設置,歸結到“ansible.executor.task_queue_manager”類中
將執行過程中的各個task的設置,或者說playbook中的編排內容,歸結到“ansible.playbook.play”中

Import Packge
from collections import namedtuple #有命元組
from ansible.parsing.dataloader import DataLoader #數據解析
from ansible.vars import VariableManager # 變量管旦
from ansible.inventory import Inventory # 主機配置信息
from ansible.playbook.play import Play # 劇本
from ansible.executor.task_queue_manager import TaskQueueManager # 任務消息隊列
from ansible.plugins.callback import CallbackBase #回調
Info
inventory --> 由ansible.inventory模塊創建,用於導入inventory文件
variable_manager --> 由ansible.vars模塊創建,用於存儲各類變量信息
loader --> 由ansible.parsing.dataloader模塊創建,用於數據解析
options --> 存放各類配置信息的數據字典
passwords --> 登錄密碼,可設置加密信息
stdout_callback --> 回調函數
Example Code:

coding:utf8

import json
import sys

from ansible.runner import Runner
from ansible.inventory.group import Group
from ansible.inventory.host import Host
from ansible.inventory import Inventory
from ansible import playbook
from ansible import callbacks
from ansible import utils

from cmdb import groups

class CmdbInventory(object):
'''
Get ansible.inventory for cmdb parse tree
'''

def __init__(self):

    self.cmdbs = groups()
    self.inventory = self.init_inventory()

def init_inventory(self, inventory=Inventory(host_list=[])):
    '''

    :param inventory: default param, init cmdb Tree info.
    :return: ansible.inventory type
    '''

    for name in self.cmdbs:
        if name == "_meta": # 主機變量,暫不處理
            pass
        g = Group(name=name)

        # 設置組環境變量
        if self.cmdbs[name].get("vars", None):
            vars = self.cmdbs[name]["vars"]
            for k,v in vars.iteritems():
                g.set_variable(k, v)

        # 添加主機進主機組
        if self.cmdbs[name].get("hosts", None):
            hosts = self.cmdbs[name]["hosts"]
            for host in hosts:
                h = Host(name=host)
                g.add_host(h)

        inventory.add_group(g)

    # 處理子組
    for name in self.cmdbs:
        if self.cmdbs[name].get("children", None):
            children = self.cmdbs[name]["children"]
            for child in children:
                g = inventory.get_group(name)
                child = inventory.get_group(child)
                g.add_child_group(child)

    # 處理主機的環境變量
    hostvars = self.cmdbs.get("_meta",{}).get("hostvars", {})
    if hostvars:
       for host in hostvars:
           inve_host = inventory.get_host(host)
           for k, v in hostvars[host].iteritems():
               inve_host.set_variable(k, v)

    return inventory

class Ansible(object):
def init(self, transport="paramiko", module_name="ping",
module_args="", pattern="", remote_user="",
remote_pass="", play_book=False, yml_path=""):
'''
Run a ansible task
:param transport: paramiko, ssh, smart
:param module_name: ansible module name
:param module_args: ansible module args
:param pattern: ansible pattern
:param remote_user: transport user
:param remote_pass: transport password
:return: ansible task result
'''

    if not remote_user or not remote_pass:
        raise ValueError("Ansible class need params remote_user, remote_pass")

    if play_book:
        if not yml_path:
            raise ValueError("playbook need params yml_path")
    else:
        if not module_name or not pattern:
            raise ValueError("Ad-hoc need params module_name, pattern")

    if transport not in ("paramiko", "ssh", "smart"):
        raise ValueError("params transport not in paramiko, ssh, smart.")

    self.transport = transport
    self.module_name = module_name
    self.module_args = module_args
    self.pattern = pattern.decode("utf-8")  # 這是因爲中文問題
    self.remote_user = remote_user
    self.remote_pass = remote_pass
    self.play_book = play_book
    self.yml_path = yml_path

    # A 通過解析方式(這是一種單獨的方式)
    # ci = CmdbInventory()
    # inventory = ci.inventory

    # B 通過腳本方式(這是一種全量的方式,可通過修改文件名)
    self.inventory = Inventory(host_list="cmdb.py")

def task(self):
    '''Ansible Ad-Hoc'''

    try:
        runner = Runner(
            transport=self.transport,
            module_name=self.module_name,
            module_args=self.module_args,
            pattern=self.pattern,
            forks=10,
            inventory=self.inventory,
            remote_user=self.remote_user,
            remote_pass=self.remote_pass
        )
        result =  runner.run()
        return True, result
    except Exception as e:
        return False, str(e)

def playbook(self):
    stats = callbacks.AggregateStats()
    playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
    runner_cb = callbacks.PlaybookRunnerCallbacks(stats=stats, verbose=utils.VERBOSITY)

    # B 通過腳本方式(這是一種全量的方式,可通過修改文件名)
    inventory = Inventory(host_list="cmdb.py")

    pb = playbook.PlayBook(
        inventory=self.inventory,
        playbook=self.yml_path,
        stats=stats,
        callbacks=playbook_cb,
        runner_callbacks=runner_cb,
        check=True,
        transport=self.transport,
        remote_user=self.remote_user,
        remote_pass=self.remote_pass
    )

    result = pb.run()
    return True, result

if name == "main":
ansible = Ansible(remote_user="",
remote_pass="",
play_book=True,
yml_path="playbooks/ping.yml")

result = ansible.task()

result = ansible.playbook()
print json.dumps(result, indent=4)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章