从cmdb获取原始主机信息生成ansible的hosts文件,cmdbansible


#!/usr/bin/env python
#-*- coding: utf-8 -*-
#Description:应用场景,从cmdb中直接获取主机信息,然后生成ansible支持的ini格式inventory文件;并且划分了原子组、业务组(高级分组)、应用组(高级分组),其中,原子组是业务组和应用组的交集名称,业务组和应用组的成员都是原子组;

import shutil
import os
from datetime import datetime
import logging
import ConfigParser
import re
import requests
import json
import sys
reload(sys)
sys.setdefaultencoding('utf8')

#变量、配置初始化
#backuptime = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
backuptime = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
logging.basicConfig(filename="inventory.log", level = logging.DEBUG,
                    format='levelname: %(levelname)s, process-id: %(process)d, filename: %(filename)s, messages: %(message)s')
hosts_all = []
atomic_groups = []
advanced_groups_app = []
advanced_groups_business = []

#从数据库获取主机信息数据,看实际情况返回的数据结构类型,最终所有的主机要构造成一个列表,备用;
#comment: 备注
#service: 运行的服务
#idc: 机房名称
#project:所属项目,主机组
#eth1: 公网IP
#eth2: 内网IP
def get_hosts_all():
    token = 'yyyyyyyyyyyyyyyyyyyyyy'
    headers = {'token': token}
    url = 'http://xxxxxxxx:xxxx/yyyyyy/get_hosts/'
    res = requests.get(url=url, headers=headers)
    for i in res.json():
        re1 = r'^[a-z]+'
        comment = i['comment']
        lcomment = comment.split(';')
        if re.match(re1, comment) and re.search('lt;', comment):
            #过滤掉lt-test、lt-gray组的机器,构造一个完全lt组的主机名列表
            if 'lt-' not in comment:
                sighost = lcomment[0]
                hosts_all.append(sighost)
    return hosts_all

#备份ansible原来的inventory文件
def backup_ansible_inventory():
    bakFile = 'hosts_' + backuptime
    if os.path.isfile('hosts'):
        if not os.path.isfile(bakFile):
            shutil.move('hosts', bakFile)

#构造初始的原子组列表
def build_atomic_groups():
    with open('init_atomic_groups_name.txt', 'r') as iagn:
        iagn_lines = iagn.readlines()
    for iagn_line in iagn_lines:
        iagn_line = iagn_line.strip()
        atomic_groups.append(iagn_line)
    return atomic_groups

#构造初始的高级分组列表,基于应用名称
def build_advanced_groups_app():
    with open('init_advanced_groups_app.txt', 'r') as iaga:
        iaga_lines = iaga.readlines()
    for iaga_line in iaga_lines:
        iaga_line = iaga_line.strip()
        advanced_groups_app.append(iaga_line)
    # print 'advanced_groups_app: ', advanced_groups_app
    return advanced_groups_app

#构造初始的高级分组列表,基于业务模块
def build_advanced_groups_business():
    with open('init_advanced_groups_business.txt', 'r') as iagb:
        iagb_lines = iagb.readlines()
    for iagb_line in iagb_lines:
        iagb_line = iagb_line.strip()
        advanced_groups_business.append(iagb_line)
    # print 'advanced_groups_business: ', advanced_groups_business
    return advanced_groups_business

#构造ConfigParser对象,并初始化section对象,包括初始化的原子组和高级分组
def build_sections():
    conf = ConfigParser.ConfigParser(allow_no_value = True)
    for agroup in atomic_groups:
        conf.add_section(agroup)
    return conf

#构造一个原子组名的正则表达式列表,用于匹配hosts主机名,然后放到对应的原子组中;
def gen_groups_re(atomic_groups):
    global groups_re
    groups_re = []
    for group_re in atomic_groups:
        group_re = group_re.split('_')
        group_re[0] = group_re[0] + '[0-9]*'
        group_re = '.'.join(group_re)
        groups_re.append(group_re)
    return groups_re

#打开hosts配置文件,准备写入
def main():
    with open('hosts', 'wb+') as host_file:
        groups_re = gen_groups_re(atomic_groups)
        groups_re_num = len(groups_re)
        groups_app_num = len(advanced_groups_app)
        groups_business_num = len(advanced_groups_business)
        print 'init_groups_business_num: ', groups_business_num
        print 'init_groups_app_num: ', groups_app_num
        # print "groups_re_num: ", groups_re_num
        #遍历所有主机名
        for h in hosts_all:
            #遍历所有正则表达式,将主机名与正则表达式列表进行匹配,如果没有匹配的,则创建新的原子组名称,并把该主机添加到新增的原子组内,此时数据都还是在内存中的ConfigParser对象中;
            h_i = 0
            for r in groups_re:#[1,2,3]
                match = re.search(r, h)
                if match:
                    #从正则表达式构造对应的原子组名称
                    group_tmp = r.split('.')
                    group_tmp[0] = group_tmp[0].split('[')[0]
                    group_tmp = '_'.join(group_tmp)
                    conf.set(group_tmp, h)
                    break
                else:
                    h_i += 1
            #如果循环次数与已有原子组个数相等,则说明该主机没有属于的原子组,需要增加原子组并把该主机添加到该原子组中;
            if h_i == groups_re_num:
                new_group = h.split('.')
                new_group[0] = re.sub(r'[0-9]+', '', new_group[0])
                new_group = '_'.join(new_group[0:3])
                print 'new_group: ', new_group
                #更新原子组名称列表
                atomic_groups.append(new_group)
                #更新正则表达式列表
                groups_re = gen_groups_re(atomic_groups)
                groups_re_num = len(groups_re)
                #更新原子组初始化文件
                with open('init_atomic_groups_name.txt', 'a') as iagn:
                    iagn.write('\n' + new_group)
                conf.add_section(new_group)
                conf.set(new_group, h)
                print 'host: {0}, h_i: {1}'.format(h,h_i)

        #此时ConfigParser对象还在内存中,没有消失,后面再add_sections,则是在写入到文件那一刻时的内容后面再次追加了;文件的追加和ConfigParser对象内容的追加是两个概念;
        #构造基于应用名称的高级分组
        for appgroup in advanced_groups_app:
            conf.add_section(appgroup)
        for g in atomic_groups:
            j = 0
            for k in advanced_groups_app:
                kre = k + '_'
                kmatch = re.match(kre, g)
                if kmatch:
                    conf.set(k, g)
                    break
                else:
                    j += 1
            if j == groups_app_num:
                new_group_app = g.split('_')[0]
                print 'new_group_app: ', new_group_app
                #更新advanced_groups_app列表,下一次循环开始使用最新的列表;
                advanced_groups_app.append(new_group_app)
                #更新groups_app_num的值;
                groups_app_num = len(advanced_groups_app)
                with open('init_advanced_groups_app.txt', 'a') as iaga:
                    iaga.write('\n' + new_group_app)
                conf.add_section(new_group_app)
                conf.set(new_group_app, g)
                print 'advanced_groups_app new: ', advanced_groups_app
        #
        #
        #构造基于业务模块的高级分组
        for busgroup in advanced_groups_business:
            conf.add_section(busgroup)
        for g in atomic_groups:
            j = 0
            # print 'business_g: ', g
            for k in advanced_groups_business:
                kre = '_' + k
                kmatch = re.search(kre, g)
                if kmatch:
                    conf.set(k, g)
                    break
                else:
                    j += 1
            # print 'bussiness_j: ', j
            if j == groups_business_num:
                new_group_business = g.split('_')
                new_group_business = '_'.join(new_group_business[1:])
                # print 'new_group_business: ', new_group_business
                #更新advanced_groups_app列表,下一次循环开始使用最新的列表;
                advanced_groups_business.append(new_group_business)
                #更新groups_business_num的值,下一次循环开始使用;
                groups_business_num = len(advanced_groups_business)
                with open('init_advanced_groups_business.txt', 'a') as iagb:
                    iagb.write('\n' + new_group_business)
                conf.add_section(new_group_business)
                conf.set(new_group_business, g)
        conf.write(host_file)

if __name__ == '__main__':
    backup_ansible_inventory()
    hosts_all = get_hosts_all()
    atomic_groups = build_atomic_groups()
    advanced_groups_app = build_advanced_groups_app()
    advanced_groups_business = build_advanced_groups_business()
    conf = build_sections()
    main()

 

相关内容

    暂无相关文章