main.py 12.6 KB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    :  2020/9/16 18:28
# @Author  :  Young Lee
# @Email   :  young_lee2017@163.com

import configparser
import chardet
import re
import logging
import sys
import os
import socket
import fcntl
import struct
from multiprocessing import Process
from create_hosts import Inventory

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logging.disable(logging.INFO)

class Configure_FX():
    """ 配置繁星的类 """

    def __init__(self):
        self.config_file = 'modify.ini'
        self.logger = logging.getLogger(__name__)
        self.self_ip = self.get_self_ip('eth0')
        # self.self_ip = '192.168.8.104'
        self.reset_config()

    # 获取所在主节点IP
    def get_self_ip(self, ifname):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        return socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15].encode()))[20:24])
    
    # 初始化配置参数
    def reset_config(self):
        self.options = {}
        self.master_info = {}
        self.slave_info = {}
        configfile = configparser.ConfigParser()
        with open(self.config_file, 'rb') as f:
            str = f.read()
            coding = chardet.detect(str)['encoding']
        configfile.read(self.config_file, encoding=coding)
        for item in configfile.options('options'):
            self.options[item] = configfile.get('options', item)
        for item in configfile.options('master_info'):
            self.master_info[item] = configfile.get('master_info', item)
        for item in configfile.options('slave_info'):
            self.slave_info[item] = configfile.get('slave_info', item)
        self.logger.info(self.options)
        self.logger.info(self.master_info)
        self.logger.info(self.slave_info)

    # 检测是否安装ansible/ansible版本是否为2.8
    def check_ansible_version(self):
        try:
            import ansible
            ansible_version = re.search('\d+.\d+', ansible.__version__).group()
            if ansible_version != '2.8':
                print("\033[0;36m>>>>>>>>>>即将开始安装ansible2.8.6<<<<<<<<<<\n\033[0m")
                time.sleep(3)
                result = os.system('tar zxf ansible_offline.tar.gz;chmod +x ansible_offline/install.sh;./ansible_offline/install.sh')
                if result == 0:
                    print("\033[0;36m>>>>>>>>>>完成安装ansible2.8.6!<<<<<<<<<<\n\033[0m")
        except:
            print("\033[0;36m>>>>>>>>>>即将开始安装ansible2.8.6<<<<<<<<<<\n\033[0m")
            time.sleep(3)
            result = os.system('pwd;tar zxf ansible_offline.tar.gz;chmod +x ansible_offline/install.sh;./ansible_offline/install.sh')
            if result == 0:
                print("\033[0;36m>>>>>>>>>>完成安装ansible2.8.6!<<<<<<<<<<\n\033[0m")
        finally:
            from Ansible_API import MyAnsiable
            global MyAnsiable

    # 对操作过滤,程序的入口
    def filter_operation(self):
        if self.options['modify_ip_slave'] == '1' or self.options['update_config_slave'] == '1':
            self.check_ansible_version()
            self.make_slave_info()
            if self.options['update_config_slave'] == '1':
                self.make_master_info('slave_use')
                self.configure_slave()
            if self.options['modify_ip_slave'] == '1':
                self.modify_slave_ip()

        if self.options['modify_ip_master'] == '1' or self.options['update_config_master'] == '1':
            self.make_master_info()
            if self.options['update_config_master'] == '1':
                self.configure_master()
            if self.options['modify_ip_master'] == '1':
                self.modify_master_ip()

    # 将配置的IP转成列表
    def get_each_ip(self, infos):
        ip_list = []
        ip_infos = re.findall('\d+.\d+.\d+.\d+-?\d*', infos)
        for info in ip_infos:
            if re.search('-', info):
                ip_block = re.search('(\d+.\d+.\d+.)(\d+)-(\d+)', info)
                if ip_block:
                    ip_pre = ip_block.group(1)
                    ip_min = ip_block.group(2)
                    ip_max = ip_block.group(3)
                    if ip_min > ip_max:
                        print('\033[0;31m起始IP大于结束IP(%s),请检查modify.ini!\033[0m' % info)
                        sys.exit()
                    ip_list = ip_list + ["%s%d" % (ip_pre, num) for num in range(int(ip_min), int(ip_max)+1)]
                else:
                    print('\033[0;31m子节点IP配置存在空值(%s),请检查modify.ini!\033[0m' % info)
                    sys.exit()

            else:
                dest_ip = re.search('\d+.\d+.\d+.\d+', info).group()
                if dest_ip:
                    ip_list.append(info)
        return ip_list

    # 删除旧hosts文件
    def check_hosts_file(self):
        self.hosts_file = 'tmp_hosts'
        if os.path.exists(self.hosts_file):
            os.remove(self.hosts_file)

    # 再封装一层调用ansible
    def use_ansible_api(self, ansible_worker, ip, module, command):
        ansible_worker.run(hosts=ip, module=module, args=command)

    # 整理子节点信息
    def make_slave_info(self):
        self.check_hosts_file()
        if self.slave_info['slave_ip']:
            # 生成子节点IP列表,跳过主节点IP
            self.slave_ips = self.get_each_ip(self.slave_info['slave_ip'])
            self_ip_index = self.slave_ips.index(self.self_ip)
            del self.slave_ips[self_ip_index]
            self.logger.info(self.slave_ips)

            # 生成新子节点IP列表,跳过主节点新IP
            if self.options['modify_ip_slave'] == '1':
                if self.slave_info['slave_whether_reboot'] == '1':
                    self.slave_whether_reboot = 'reboot'
                else:
                    self.whether_reboot = 'noreboot'
                self.slave_new_mask = self.slave_info['slave_new_mask']
                if self.slave_info['slave_new_ip'] and self.slave_new_mask:
                    self.slave_ips_new = self.get_each_ip(self.slave_info['slave_new_ip'])
                    if len(self.slave_ips) != len(self.slave_ips_new) - 1:
                        print('\033[0;31m新旧IP数目不一致,请检查modify.ini!\033[0m')
                        sys.exit()
                    del self.slave_ips_new[self_ip_index]
                    self.logger.info(self.slave_ips_new)
                    Inventory(self.hosts_file, 'old', self.slave_ips, 'ubuntu', 'ubuntu')
                    Inventory(self.hosts_file, 'tx2', self.slave_ips_new, 'ubuntu', 'ubuntu')
                else:
                    print("\033[0;31m缺少子节点更改后的IP或掩码,请检查modify.ini!\033[0m")
                    sys.exit()
            else:
                Inventory(self.hosts_file, 'tx2', self.slave_ips, 'ubuntu', 'ubuntu')
        else:
            print('\033[0;31m没有填写子节点IP信息,请检查modify.ini!\033[0m')
            sys.exit()

    # 整理主节点信息
    def make_master_info(self, type='master_use'):
        if self.master_info['auto_get'] == '1' and self.options['modify_ip_master'] == '0':
            self.master_int_ip = self.self_ip
            # 获取子节点需要的主节点内网IP后不再进行其他操作
            if type == 'slave_use':
                return
            self.master_ext_ip = self.get_self_ip('eth1')
        else:
            re_int = re.search('\d+.\d+.\d+.\d+', self.master_info['master_int_ip'])
            if self.master_info['master_int_ip'] and re_int:
                self.master_int_ip = re_int.group()
            else:
                print('\033[0;31mmaster_int_ip(%s)无效,请检查modify.ini!\033[0m' % self.master_info['master_int_ip'])
                sys.exit()
            # 获取子节点需要的主节点内网IP后不再进行其他操作
            if type == 'slave_use':
                return

            re_ext = re.search('\d+.\d+.\d+.\d+', self.master_info['master_ext_ip'])
            if self.master_info['master_ext_ip'] and re_ext:
                self.master_ext_ip = re_ext.group()
            else:
                print('\033[0;31mmaster_ext_ip(%s)无效,请检查modify.ini!\033[0m' % self.master_info['master_ext_ip'])
                sys.exit()

        # 修改主节点IP时获取如下信息
        if self.options['modify_ip_master'] == '1':
            if self.master_info['master_whether_reboot'] == '1':
                self.master_whether_reboot = 'reboot'
            else:
                self.master_whether_reboot = 'noreboot'
            self.master_ext_mask = self.master_info['master_ext_mask']
            self.master_int_mask = self.master_info['master_int_mask']
            self.master_gateway = self.master_info['master_gateway']

        # 更新主节点配置时获取如下信息
        if self.options['update_config_master'] == '1':
            self.plat_ip = self.master_info['plat_ip']

    # 修改子节点IP
    def modify_slave_ip(self):
        print("\033[0;36m>>>>>>>>>>开始修改子节点IP<<<<<<<<<<\n\033[0m")
        ansible_worker = MyAnsiable(inventory='tmp_hosts', connection='smart')
        # 进程池Pool不能在类中使用,此处调用Process模拟进程池
        process_list = []
        for i in range(len(self.slave_ips)):
            command = 'modify.sh %s %s %s' % (self.slave_ips_new[i], self.slave_new_mask, self.slave_whether_reboot)
            p = Process(target=self.use_ansible_api,
                        args=(ansible_worker, self.slave_ips[i], 'script', command,))
            process_list.append(p)
            p.start()
            while len(process_list) > 9:
                for process in process_list:
                    if not process.is_alive():
                        process_list.remove(process)
        for p in process_list:
            p.join()
        print("\033[0;36m>>>>>>>>>>完成修改子节点IP!<<<<<<<<<<\n\033[0m")

    # 修改主节点IP
    def modify_master_ip(self):
        print("\033[0;36m>>>>>>>>>>开始修改主节点IP!<<<<<<<<<<\n\033[0m")
        os.system('chmod +x modify.sh;./modify.sh %s %s %s' % (self.master_int_ip, self.master_int_mask, 'noreboot'))
        os.system('chmod +x modify.sh;./modify.sh %s %s %s %s' % (self.master_ext_ip, self.master_ext_mask,
                                                                  self.master_gateway, self.master_whether_reboot))
        print("\033[0;36m>>>>>>>>>>完成修改主节点IP!<<<<<<<<<<\n\033[0m")

    # 修改子节点配置,思路同modify_slave_ip
    def configure_slave(self):
        print("\033[0;36m>>>>>>>>>>开始修改子节点配置<<<<<<<<<<\n\033[0m")
        ansible_worker = MyAnsiable(inventory='tmp_hosts', connection='smart')
        if self.options['modify_ip_slave'] == '1':
            process_list = []
            for i in range(len(self.slave_ips)):
                command = 'update_fx_config.sh %s %s' % (self.slave_ips_new[i], self.master_int_ip)
                p = Process(target=self.use_ansible_api,
                            args=(ansible_worker, self.slave_ips[i], 'script', command,))
                process_list.append(p)
                p.start()
                while len(process_list) > 9: 
                    for process in process_list:
                        if not process.is_alive():
                            process_list.remove(process)
            for p in process_list:
                p.join()
        else:
            slave_group = 'tx2'
            self.use_ansible_api(ansible_worker, slave_group, 'script', 'update_fx_config.sh %s %s' %
                                 ('{{inventory_hostname}}', self.master_int_ip))
        print("\033[0;36m>>>>>>>>>>完成修改子节点配置!<<<<<<<<<<\n\033[0m")

    # 修改主节点配置
    def configure_master(self):
        print("\033[0;36m>>>>>>>>>>开始修改主节点配置<<<<<<<<<<\n\033[0m")
        os.system('chmod +x update_fx_config.sh && ./update_fx_config.sh %s %s %s' %
                  (self.master_ext_ip, self.master_int_ip, self.plat_ip))
        print("\033[0;36m>>>>>>>>>>完成修改主节点配置!<<<<<<<<<<\n\033[0m")

    # def thread_pool_callback(self, worker):
    #    self.logger.info("called thread pool executor callback function")
    #    worker_exception = worker.exception()
    #    if worker_exception:
    #        self.logger.exception("Worker return exception: {}".format(worker_exception))



if __name__ == "__main__":
    rootPath = os.path.dirname(__file__)
    os.chdir(rootPath)
    configure_fx = Configure_FX()
    # configure_fx.get_each_ip(configure_fx.slave_info['slave_ip'])
    configure_fx.filter_operation()