A-A+

运维开发:ansible结合CMDB动态获取inventory脚本

2016年01月20日 Python, 自动化运维 评论 3 条 阅读 17,639 views 次

在运维工具中,选择了用ansible api来与服务器进行交互,用ansible的目的主要是使用简单,而且客户端不需要安装agent,服务端安装完ansbile后,便可对新机器进行管理。

为了结合资产管理系统(CMDB),所以要使用到动态获取inventory的方法,这样可以省去配置ansible服务端的hosts,所有的客户端IP,帐号,密码,端口都可以从CMDB中获取到。

 

动态inventory脚本必须支如下两个命令行参数:

--host  (用来列出主机的详细信息)

--list    (用来列出群组)

 

脚本输出结果范例:

  1. [root@dywl controller]# python test.py --list
  2. {
  3.     "all": [
  4.         "192.168.1.6",
  5.         "192.168.1.10"
  6.     ]
  7. }

 

  1. [root@dywl controller]# python test.py --host 192.168.1.6
  2. {
  3.     "ansible_ssh_host": "192.168.1.6",
  4.     "ansible_ssh_port": 22,
  5.     "ansible_ssh_portansible_ssh_pass": "xxxx",
  6.     "ansible_ssh_user": "root"
  7. }

 

以上脚本源码(为了测试,所以把内容都写死在test.py中)

  1. #!/usr/bin/env python
  2. #coding:utf8
  3. import json
  4. import sys
  5. def group():
  6.     info_dict = {"all":["192.168.1.6","192.168.1.10"]}
  7.     print json.dumps(info_dict,indent=4)
  8. def host(ip):
  9.     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"}}
  10.     print json.dumps(info_dict[ip],indent=4)
  11. if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
  12.     group()
  13. elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
  14.     host(sys.argv[2])
  15. else:
  16.     print "Usage: %s --list or --host <hostname>" % sys.argv[0]
  17.     sys.exit(1)

 

要从CMDB中获取,当然就是要从数据库中查询了,所以,我们按以上测试脚本的输出格式,把数据库中取出来的数据,重新整理下,符合动态inventyory规则即可

我写的脚本:

  1. #!/usr/bin/env python
  2. #coding:utf8
  3. __author__ = '戴儒锋'
  4. """
  5.     从数据库获取所有的服务器的IP、帐号、密码、端口等
  6. """
  7. import json
  8. import sys
  9. import MySQLdb
  10. import logging
  11. # 配置mysql数据库
  12. db_name = 'osyw'
  13. db_user = 'osyw'
  14. db_pass = 'xxxxxx'
  15. db_ip = '192.168.1.6'
  16. db_port = 3306
  17. def readDb(sql,db_data=()):
  18.     """
  19.     连接mysql数据库(从),并进行数据查询
  20.     """
  21.     try:
  22.         conn = MySQLdb.connect(db=db_name,user=db_user,passwd=db_pass,host=db_ip,port=int(db_port),charset="utf8")
  23.         cursor = conn.cursor()
  24.     except Exception,e:
  25.         print e
  26.         logging.error('数据库连接失败:%s' % e)
  27.         return False
  28.     try:
  29.         cursor.execute(sql,db_data)
  30.         data = [dict((cursor.description[i][0], value) for i, value in enumerate(row)) for row in cursor.fetchall()]
  31.     except Exception,e:
  32.         logging.error('数据执行失败:%s' % e)
  33.         return False
  34.     finally:
  35.         cursor.close()
  36.         conn.close()
  37.     return data
  38. #从数据库中查询数据
  39. sql = "select wip,nip,username,password from yw_device"
  40. result = readDb(sql,)
  41. def groupList():
  42.     """
  43.     整理出群组信息,格式如下:{"all": ["192.168.1.6", "192.168.1.10"]}
  44.     all 对应的hosts文件中的[all],这里只返回[all]下的2个主机组
  45.     192.168.1.6和192.168.1.10是all下面的别名,结合下面hostList(),我是直接用IP做了组名
  46.     [all]
  47.     192.168.1.6
  48.     192.168.1.10
  49.     [192.168.1.6]
  50.     192.168.1.6 ansible_ssh_host=192.168.1.6 ansible_ssh_user=root ansible_ssh_pass='xxxx,ansible_ssh_port=22
  51.     [192.168.1.10]
  52.     192.168.1.10 ansible_ssh_host=192.168.1.10 ansible_ssh_user=root ansible_ssh_pass='xxxx,ansible_ssh_port=22
  53.     (以上有不对的还望指正哈)
  54.     """
  55.     group_list = []
  56.     for host in result:
  57.         group_list.append(host["wip"])
  58.     print json.dumps({"all":group_list},indent=4)
  59. def hostList(key):
  60.     """
  61.     整理主机信息,授受一个KEY后返回该KEY的信息
  62.     我以上的思路就是把服务器IP作为KEY,服务器下面的帐号等信息作为VALUE
  63.     格式大概如下:
  64.     xxx.py --host 192.168.1.6
  65.     返回
  66.     {
  67.         "ansible_ssh_host": "192.168.1.6",
  68.         "ansible_ssh_port": 22,
  69.         "ansible_ssh_portansible_ssh_pass": "xxxx",
  70.         "ansible_ssh_user": "root"
  71.     }
  72.     """
  73.     host_dict = {}
  74.     for host in result:
  75.         host_dict[host["wip"]] = {"ansible_ssh_host":host["wip"],"ansible_ssh_port": 22,"ansible_ssh_user":"root","ansible_ssh_pass":"xxxx"}
  76.     print json.dumps(host_dict[key],indent=4)
  77. #命令行参数简易写法
  78. if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
  79.     groupList()
  80. elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
  81.     hostList(sys.argv[2])
  82. else:
  83.     print "Usage: %s --list or --host <hostname>" % sys.argv[0]
  84.     sys.exit(1)

 

测试(脚本需要可执行权限,可别忘了,chmod a+x test.py):

  1. [root@dywl controller]# ansible -i test.py 192.168.1.6 -a uptime
  2. 192.168.1.6 | success | rc=0 >>
  3.  20:22:43 up 144 days,  2:14,  2 users,  load average: 0.18, 0.20, 0.18

 

 

如果脚本不支持--list和--host的话,是会报错的,错误信息大概如下:

  1. [root@dywl controller]# ansible -i test.py 192.168.1.6 -a uptime -vvv
  2. 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框架。

关键词:

3 条留言  访客:2 条  博主:1 条

  1. avatar 花花工资

    动态inventory 会用–host遍历每个ip,这个怎么避免,我整个–list 有2000台机器,但是有时我只需要在web 这个组执行命令,但是ansible会用–host 遍历2000台机器之后才在web组执行我要执行的命令,造成的问题就是每次执行ansible 卡住的时间比较长

  2. avatar sunshadow

    你好,为什么我按照你的写法,能正常输出信息。但是用ansible -i 执行的时候始终会遍历所选组前面所有的ip?

    • avatar 江江

      这个写出来是给程序用的,不是给自己用的,只要程序能正常获取到IP信息,能远程操作就行了

给我留言

Copyright © linux系统运维 保留所有权利.   Theme  Ality 粤ICP备13023035号-1

用户登录

分享到: