Python呼叫ansible API系列(四)動態生成hosts檔案

昀溪發表於2019-04-09

方法一:透過最原始的操作檔案的方式

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
透過操作檔案形式動態生成ansible的hosts檔案
"""

import sys


class Inventory:

    def __init__(self):

        # ansible的hosts檔案路徑
        self._hostsfile = "./aaa"
        self._data = self._getInventoryInfo()
        if self._genHostsFile():
            print("生成完成。")
        else:
            print("生成失敗。")

    def _getInventoryInfo(self):
        """
        從資料庫中獲取資產資訊
        :return:
        """
        tempdata = [
            {
                "Groupname": "Group1",
                "Items": [
                    {
                        "name": "Srv01",
                        "ansible_ssh_host": "172.16.100.20",
                        "ansible_ssh_port": "22",
                        "ansible_ssh_user": "work",
                        "ansible_python_interpreter": "/usr/bin/python"
                    },
                    {
                        "name": "Srv02",
                        "ansible_ssh_host": "172.16.100.30",
                        "ansible_ssh_port": "22",
                        "ansible_ssh_user": "work",
                        "ansible_python_interpreter": "/usr/bin/python"
                    },
                ]
            },
        ]

        return tempdata

    def _genHostsFile(self):
        """
        生成資產hosts檔案
        :return: 生成成功返回True
        """
        try:
            with open(self._hostsfile, "w") as file1:
                for i in self._data:
                    groupname = i.get("Groupname")
                    file1.write("["+groupname+"]\n")
                    for server in i.get("Items"):
                        name = server.get("name")
                        ansible_ssh_host = server.get("ansible_ssh_host")
                        ansible_ssh_port = server.get("ansible_ssh_port")
                        ansible_ssh_user = server.get("ansible_ssh_user")
                        ansible_python_interpreter = server.get("ansible_python_interpreter")

                        info = "ansible_ssh_host={0} ansible_ssh_port={1} ansible_ssh_user={2} ansible_python_interpreter={3}".\
                            format(ansible_ssh_host, ansible_ssh_port, ansible_ssh_user, ansible_python_interpreter)
                        line = name + " " + info + "\n"
                        file1.write(line)
        except Exception as err:
            print(err)
            return False
        return True


def main():
    Inventory()

if __name__ == "__main__":
    try:
        main()
    finally:
        sys.exit()
View Code

方法二:透過資料庫或者呼叫其他API獲取資料來動態獲得

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
透過ansible API動態生成ansible資產資訊但不產生實際的hosts檔案
主機資訊都可以透過資料庫獲得,然後生成指定格式,最後呼叫這個類來
生成主機資訊。
"""

import sys
# 用於讀取YAML和JSON格式的檔案
from ansible.parsing.dataloader import DataLoader
# 用於儲存各類變數資訊
from ansible.vars.manager import VariableManager
# 用於匯入資產檔案
from ansible.inventory.manager import InventoryManager
# 操作單個主機資訊
from ansible.inventory.host import Host
# 操作單個主機組資訊
from ansible.inventory.group import Group


class MyInventory:
    def __init__(self, hostsresource):
        """
        初始化函式
        :param hostsresource: 主機資源可以有2種形式
        列表形式: [{"ip": "172.16.48.171", "port": "22", "username": "root", "password": "123456"}]
        字典形式: {
                    "Group1": {
                        "hosts": [{"ip": "192.168.200.10", "port": "1314", "username": "root", "password": None}],
                        "vars": {"var1": "ansible"}
                    },
                    "Group2": {}
                }
        """
        self._hostsresource = hostsresource
        self._loader = DataLoader()
        self._hostsfilelist = ["temphosts"]
        """
        sources這個我們知道這裡是設定hosts檔案的地方,它可以是一個列表裡面包含多個檔案路徑且檔案真實存在,在單純的執行ad-hoc的時候這裡的
        檔案裡面必須具有有效的hosts配置,但是當透過動態生成的資產資訊的時候這個檔案必須存在但是它裡面可以是空的,如果這裡配置成None那麼
        它不影響資產資訊動態生成但是會有一個警告,所以還是要配置一個真實檔案。
        """
        self._inventory = InventoryManager(loader=self._loader, sources=self._hostsfilelist)
        self._variable_manager = VariableManager(loader=self._loader, inventory=self._inventory)

        self._dynamic_inventory()

    def _add_dynamic_group(self, hosts_list, groupname, groupvars=None):
        """
        動態新增主機到指定的主機組

        完整的HOSTS檔案格式
        [test1]
        hostname ansible_ssh_host=192.168.1.111 ansible_ssh_user="root" ansible_ssh_pass="123456"

        但通常我們都省略hostname,埠也省略因為預設是22,這個在ansible配置檔案中有,除非有非22埠的才會配置
        [test1]
        192.168.100.10 ansible_ssh_user="root" ansible_ssh_pass="123456" ansible_python_interpreter="/PATH/python3/bin/python3"

        :param hosts_list: 主機列表 [{"ip": "192.168.100.10", "port": "22", "username": "root", "password": None}, {}]
        :param groupname:  組名稱
        :param groupvars:  組變數,格式為字典
        :return:
        """
        # 新增組
        self._inventory.add_group(groupname)
        my_group = Group(name=groupname)

        # 新增組變數
        if groupvars:
            for key, value in groupvars.items():
                my_group.set_variable(key, value)

        # 新增一個主機
        for host in hosts_list:
            hostname = host.get("hostname", None)
            hostip = host.get("ip", None)
            if hostip is None:
                print("IP地址為空,跳過該元素。")
                continue
            hostport = host.get("port", "22")
            username = host.get("username", "root")
            password = host.get("password", None)
            ssh_key = host.get("ssh_key", None)
            python_interpreter = host.get("python_interpreter", None)

            try:
                # hostname可以不寫,如果為空預設就是IP地址
                if hostname is None:
                    hostname = hostip
                # 生成一個host物件
                my_host = Host(name=hostname, port=hostport)
                # 新增主機變數
                self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_host", value=hostip)
                self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_port", value=hostport)
                if password:
                    self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_pass", value=password)
                self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_user", value=username)
                if ssh_key:
                    self._variable_manager.set_host_variable(host=my_host, varname="ansible_ssh_private_key_file", value=ssh_key)
                if python_interpreter:
                    self._variable_manager.set_host_variable(host=my_host, varname="ansible_python_interpreter", value=python_interpreter)

                # 新增其他變數
                for key, value in host.items():
                    if key not in ["ip", "hostname", "port", "username", "password", "ssh_key", "python_interpreter"]:
                        self._variable_manager.set_host_variable(host=my_host, varname=key, value=value)

                # 新增主機到組
                self._inventory.add_host(host=hostname, group=groupname, port=hostport)
            except Exception as err:
                print(err)

    def _dynamic_inventory(self):
        """
        新增 hosts 到inventory
        :return:
        """
        if isinstance(self._hostsresource, list):
            self._add_dynamic_group(self._hostsresource, "default_group")
        elif isinstance(self._hostsresource, dict):
            for groupname, hosts_and_vars in self._hostsresource.items():
                self._add_dynamic_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))

    @property
    def INVENTORY(self):
        """
        返回資產例項
        :return:
        """
        return self._inventory

    @property
    def VARIABLE_MANAGER(self):
        """
        返回變數管理器例項
        :return:
        """
        return self._variable_manager


def main():
    temphosts_list = [{"ip": "192.168.200.10", "port": "22", "username": "root", "password": "123456"}]

    temphosts_dict = {
        "Group1": {
            "hosts": [{"ip": "192.168.200.10", "port": "1314", "username": "root", "password": None}],
            "vars": {"var1": "ansible"}
        },
        # "Group2": {}
    }

    mi = MyInventory(temphosts_dict)
    # print(mi.INVENTORY.get_groups_dict())

    # for group, hosts in mi.INVENTORY.get_groups_dict().items():
    #     print(group, hosts)

    host = mi.INVENTORY.get_host("192.168.200.10")
    print(mi.VARIABLE_MANAGER.get_vars(host=host))

if __name__ == "__main__":
    try:
        main()
    finally:
        sys.exit()
View Code

 

相關文章