一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

ansible结合CMDB动态获取inventory脚本教程

时间:2016-05-05 编辑:简简单单 来源:一聚教程网

在运维工具中,选择了用ansible api来与服务器进行交互,用ansible的目的主要是使用简单,而且客户端不需要安装agent,服务端安装完ansbile后,便可对新机器进行管理。
为了结合资产管理系统(CMDB),所以要使用到动态获取inventory的方法,这样可以省去配置ansible服务端的hosts,所有的客户端IP,帐号,密码,端口都可以从CMDB中获取到。
 
动态inventory脚本必须支如下两个命令行参数:
--host  (用来列出主机的详细信息)
--list    (用来列出群组)
 
脚本输出结果范例:
[root@dywl controller]# python test.py --list
{
    "all": [
        "192.168.1.6",
        "192.168.1.10"
    ]
}
 
[root@dywl controller]# python test.py --host 192.168.1.6
{
    "ansible_ssh_host": "192.168.1.6",
    "ansible_ssh_port": 22,
    "ansible_ssh_portansible_ssh_pass": "xxxx",
    "ansible_ssh_user": "root"
}
 
以上脚本源码(为了测试,所以把内容都写死在test.py中)
#!/usr/bin/env python
#coding:utf8
import json
import sys
def group():
    info_dict = {"all":["192.168.1.6","192.168.1.10"]}
    print json.dumps(info_dict,indent=4)
def host(ip):
    info_dict = {"192.168.1.10":{"ansible_ssh_host":"192.168.1.10","ansible_ssh_port":22,"ansible_ssh_user":"root","ansible_ssh_port""ansible_ssh_pass":"xxxx"},"192.168.1.6":{"ansible_ssh_host":"192.168.1.6","ansible_ssh_port":22,"ansible_ssh_user":"root","ansible_ssh_port""ansible_ssh_pass":"xxxx"}}
    print json.dumps(info_dict[ip],indent=4)
if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
    group()
elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
    host(sys.argv[2])
else:
    print "Usage: %s --list or --host " % sys.argv[0]
    sys.exit(1)
 
要从CMDB中获取,当然就是要从数据库中查询了,所以,我们按以上测试脚本的输出格式,把数据库中取出来的数据,重新整理下,符合动态inventyory规则即可
我写的脚本:
#!/usr/bin/env python
#coding:utf8
__author__ = '戴儒锋'
"""
    从数据库获取所有的服务器的IP、帐号、密码、端口等
"""
import json
import sys
import MySQLdb
import logging
# 配置mysql数据库
db_name = 'osyw'
db_user = 'osyw'
db_pass = 'xxxxxx'
db_ip = '192.168.1.6'
db_port = 3306
def readDb(sql,db_data=()):
    """
    连接mysql数据库(从),并进行数据查询
    """
    try:
        conn = MySQLdb.connect(db=db_name,user=db_user,passwd=db_pass,host=db_ip,port=int(db_port),charset="utf8")
        cursor = conn.cursor()
    except Exception,e:
        print e
        logging.error('数据库连接失败:%s' % e)
        return False
    try:
        cursor.execute(sql,db_data)
        data = [dict((cursor.description[i][0], value) for i, value in enumerate(row)) for row in cursor.fetchall()]
    except Exception,e:
        logging.error('数据执行失败:%s' % e)
        return False
    finally:
        cursor.close()
        conn.close()
    return data
#从数据库中查询数据
sql = "select wip,nip,username,password from yw_device"
result = readDb(sql,)
def groupList():
    """
    整理出群组信息,格式如下:{"all": ["192.168.1.6", "192.168.1.10"]}
    all 对应的hosts文件中的[all],这里只返回[all]下的2个主机组
    192.168.1.6和192.168.1.10是all下面的别名,结合下面hostList(),我是直接用IP做了组名
    [all]
    192.168.1.6
    192.168.1.10
    [192.168.1.6]
    192.168.1.6 ansible_ssh_host=192.168.1.6 ansible_ssh_user=root ansible_ssh_pass='xxxx,ansible_ssh_port=22
    [192.168.1.10]
    192.168.1.10 ansible_ssh_host=192.168.1.10 ansible_ssh_user=root ansible_ssh_pass='xxxx,ansible_ssh_port=22
    (以上有不对的还望指正哈)
    """
    group_list = []
    for host in result:
        group_list.append(host["wip"])
    print json.dumps({"all":group_list},indent=4)
def hostList(key):
    """
    整理主机信息,授受一个KEY后返回该KEY的信息
    我以上的思路就是把服务器IP作为KEY,服务器下面的帐号等信息作为VALUE
    格式大概如下:
    xxx.py --host 192.168.1.6
    返回
    {
        "ansible_ssh_host": "192.168.1.6",
        "ansible_ssh_port": 22,
        "ansible_ssh_portansible_ssh_pass": "xxxx",
        "ansible_ssh_user": "root"
    }
    """
    host_dict = {}
    for host in result:
        host_dict[host["wip"]] = {"ansible_ssh_host":host["wip"],"ansible_ssh_port": 22,"ansible_ssh_user":"root","ansible_ssh_pass":"xxxx"}
    print json.dumps(host_dict[key],indent=4)
#命令行参数简易写法
if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
    groupList()
elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
    hostList(sys.argv[2])
else:
    print "Usage: %s --list or --host " % sys.argv[0]
    sys.exit(1)
 
测试(脚本需要可执行权限,可别忘了,chmod a+x test.py):
[root@dywl controller]# ansible -i test.py 192.168.1.6 -a uptime
192.168.1.6 | success | rc=0 >>
 20:22:43 up 144 days,  2:14,  2 users,  load average: 0.18, 0.20, 0.18
 
 
如果脚本不支持--list和--host的话,是会报错的,错误信息大概如下:
[root@dywl controller]# ansible -i test.py 192.168.1.6 -a uptime -vvv
ERROR: problem running /data/www/yw/controller/gethost.py --list ([Errno 2] No such file or directory)
 
不过就算你写了支持--list和--host,也可能会被其它奇怪的问题搞晕,它还是报以上的错误,--list ([Errno 2] No such file or directory)  ,说下我遇到的问题,我在命令行中运行python test.py --list时,是没有问题的,能正常输出群组信息,但我用ansible -i test.py 192.168.1.6 -a uptime时,还是报--list ([Errno 2] No such file or directory)错误。后来我用直接用./test.py --list,也报错,原因大概找到了,就是不会自动用python来解析这人脚本,所以脚本输出错误,才会报上面的错误,找了许久都没发现问题,后来才发现是脚本第一行:
(#!/usr/bin/env python)导致的,因为我脚本是用pycharm写的,用svn上传到的服务器,这样出的问题,现在我还没明白到底为什么,所以我只好用vim打开该脚本,把第一行删掉,再重新写上
#!/usr/bin/env python,呵呵
不管脚本怎么写,返正你只要符合inventory的规范即可,接下来,我会继续用ansible api来开发运维工具,这套工具,我应该会开源出来提供新手们学习用,请等段时间哈,现在正在开发中,差不多的时候就会放出来了,还是使用python的bottle框架。

热门栏目