Python-day3作業-haproxy配置文件管理腳本

#!/usr/bin/env python

import os,sys,time,re,prettytable,json

from collections import defaultdict,OrderedDict

conf='haproxy.cfg'  ###指定haproxy配置文件###

jgf=''

######################1.input輸入字符類型轉化函數#######################

def input_handle(s):

    if str.isdigit(s):                                                     ###對輸入是否是數字進行判斷###

        s = int(s)                                                         ###如果輸出的是個數字,則轉化爲整數類型###

    return s                                                              ###返回輸入字符###


###########################2.backend列表展示函數############################

def backend_read(conf):

    backend_list = []                                                       ###初始化backend的列表###

    show_dict = {}                                                          ###初始化要返回的顯示字典###

    backend_name_dict = defaultdict(list)                                   ###定義一個value爲列表的字典,用來存放server###

    server_flag = False                                                     ###初始化server判斷標誌位###

    with open(conf,'r') as ha:                                             ###打開haproxy配置文件###

        for line in ha:

            server_dict = OrderedDict()                                      ###定義一個有序字典###

            line = line.strip('\n')

            #情況1

            if re.match('backend',line):                                    ###匹配配置文件以backend開頭的行###

                backend_name = re.split('\s+',line)[1]

                backend_list.append(backend_name)                            ###將配置到的backend的名稱插入到列表###

                server_flag = True                                           ###賦值標誌位爲真,用來與server關聯###

            #情況2

            elif server_flag and re.match('\s+server',line):               ###匹配配置文件以server開頭的行###

                server_info = re.split('\s+',line)                          ###對server進行分隔###

                server_dict['name'] = server_info[2]                        ###對server的具體信息進行字典賦值###

                server_dict['address'] = server_info[3]

                server_dict['weight'] = server_info[5]

                server_dict['maxconn'] = server_info[7]

                backend_name_dict[backend_name].append(server_dict)          ###將server字典與backend的名稱進行關聯###

            else:

                server_flag = False                                          ###當server沒匹配到,賦值標誌位爲假,結束關聯###

    for k,v in enumerate(backend_list,1):

        show_dict[k] = v                                                     ###對backend名稱進行新字典賦值,方便查詢和展示###

        print('%d . %s' % (k,v))                                             ###輸出backend列表###

    return(show_dict,backend_name_dict)                                     ###返回顯示的字典和backend-server字典###


########################3.顯示server服務器函數#############################

def backend_server_show(backend_show_value,server_show_dict):

    ############對backend名稱進行遍歷並加上數字編號###########################

    print(jgf.center(70,'='))

    print('\033[1m後端服務器(%s)信息如下:\033[0m'%backend_show_value)

    print('%-20s %-20s %-20s %-20s'%('name','address','weight','maxconn'))

    server_list = server_show_dict[backend_show_value]

    for v in server_list:                                     ###用enumerate進行server展示###

        n=list(v.values())

        print('\033[32;40m%-5s%20s%15s%25s\033[1m'%(n[0],n[1],n[2],n[3]))

    print(jgf.center(60, '='))


#####################4.名稱輸入判斷函數#############################

def name_decide():

    (name,name_flag) = ('',True)                                           ###初始化返回的名稱和判斷標誌位###

    while name_flag:

        name_input = input('\033[32m請輸入新服務名(退出輸入q):\033[0m')

        if len(name_input) == 0:                                           ###如果輸入爲空則直接下一次循環###

            continue

        elif name_input == 'q':                                           ###輸入q,退出本次輸入###

            name_flag = False

            sys.exit('\033[32;1m腳本已退出!\033[1m')

        elif re.match('[0-9a-zA-Z\_]+',name_input):                       ###匹配輸入是否以字符、數字或下劃線開頭###

            name = name_input

            name_flag = False                                              ###輸入成功後退出循環###

        else:

            print('\033[31m名稱輸入錯誤,請重新輸入!!!\033[0m')

        break

    return(name)                                                          ###返回輸入的結果###

#####################5.IP地址及端口輸入判斷函數#############################

def ipaddress_decide():

    (address,address_flag) = ('',True)                                     ###初始化返回的IP地址和判斷標誌位###

    while address_flag:

        address_input = input('\033[32m請輸入新地址(IP哦)(退出輸入q):\033[0m')

        if len(address_input) == 0:                                        ###如果輸入爲空則直接下一次循環###

            continue

        elif address_input == 'q':                                        ###輸入q,退出本次輸入###

            address_flag = False

            sys.exit('\033[32;1m腳本已退出!\033[1m')

        ##################匹配輸入是否是ip:port的格式######################

        elif re.match('(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}(\:\d{1,5})?$',address_input):

            address = address_input

            address_flag = False                                           ###輸入成功後退出循環###

        else:

            print('\033[31m地址輸入錯誤,請重新輸入!!!\033[0m')

    return(address)                                                       ###返回輸入的結果###


####################6.數字輸入判斷函數######################################

def number_decide(name):

    (number,number_flag) = ('',True)                                      ###初始化返回的數字和判斷標誌位###

    while number_flag:

        number_input =input('\033[32m請輸入%s(數字哦)(退出輸入q):\033[0m' % name)

        if len(number_input) == 0:                                        ###如果輸入爲空則直接下一次循環###

            continue

        elif number_input == 'q':                                        ###輸入q,退出本次輸入###

            number_flag = False

            sys.exit('\033[32;1m腳本已退出!\033[32;1m')

        else:

            try:

                int(number_input)                                         ###匹配輸入是否是數字###

            except:

                print('\033[31;1m%s輸入類型錯誤,請重新輸入!!!\033[0m'%name)

            else:

                number = number_input

                number_flag = False                                       ###輸入成功後退出循環###

    return(number)                                                       ###返回輸入的結果###


#############################7.節點輸入判斷函數##########################

def backend_input_if(input_index,input_dict):

    (input_name,input_flag) = ('',True)                                   ###初始化返回的名稱和判斷標誌位###

    ###############如果輸入非空,對輸入進行判斷並轉化類型#################

    if len(input_index) != 0:

        input_index = input_handle(input_index)

    if input_index == 'b':                                                ###如果輸入爲b,則退出程序###

        input_flag = False

    elif input_index in input_dict.keys():                                ###如果輸入爲數字編號,則從字典中獲取具體backend名稱###

        input_name = input_dict[input_index]

    elif input_index in input_dict.values():                              ###如果輸入爲backend名稱,則直接獲取###

        input_name = input_index

    else:

        input_name = ''                                                    ###輸入其他字符,賦值變量爲空###

    return(input_name,input_flag)                                         ###返回輸入的結果和循環標誌位###


########################8.配置文件操作函數#################

def backend_server_handle(conf,handle_dict):

    newfile = '%s.new'%conf                                                ###定義回寫的新文件###

    server_flag = False

    with open(conf,'r') as read_file,open(newfile,'w') as write_file:       ###同時打開二文件,一個讀,一個寫###

        for line in read_file:

            if re.match('backend',line):                                     ###匹配到backend行時進行server信息插入###

                write_file.write(line)

                backend_name = re.split('\s+',line)[1]

                for server_dict in handle_dict[backend_name]:                ###對backend-server字典進行遍歷###

                    server_line = '\tserver {name} {address} weight {weight} maxconn {maxconn}\n'

                    write_file.write(server_line.format(**server_dict))       ###將指定的backend下的server條目插入文件###


                server_flag = True                                           ###指定標誌位爲真,方便server判斷###

            elif server_flag and re.match('\s+server',line):                 ###匹配server開頭的行,跳過不做任何操作###

                pass

            else:

                write_file.write(line)                                        ###其他的行,直接插入新文件###

                server_flag = False

    print('\033[33;1m server更新成功\033[0m')

    os.system('mv %s %s.bak'%(conf,conf))                                  ###對源配置文件進行備份###

    os.system('mv %s %s'%(newfile,conf))                                   ###對新生成的配置文件進行改名###


##################################主程序開始##################################

if __name__ == '__main__':

    flag = True

    backend_name = ''

    haproxy_name_show_dict = {}                                                ###初始化backend顯示字典###

    haproxy_server_show_dict = {}                                              ###初始化server顯示字典###

    while flag:

        print(jgf.center(60,'='))

        hy='\033[36m歡迎訪問haproxy配置文件管理腳本\033[0m'

        print(hy.center(60,'*'))

        print('\033[1mbackend列表信息如下:')

        (haproxy_name_show_dict,haproxy_server_show_dict) = backend_read(conf)

        print(jgf.center(50,'='))

        time.sleep(1)

        print('''

        \033[35;1m1.查詢後端服務\033[0m

        \033[35;1m 2.添加後端服務\033[0m

        \033[35;1m 3.修改後端服務\033[0m

        \033[31;1m 4.刪除後端服務\033[0m

        \033[32;1m 5.退出\033[0m ''')

        print(jgf.center(60,'='))

        select_num = input('\033[35;1m請選擇操作條目:\033[0m')


        #######################1. 查詢後端服務################################

        if select_num == '1':

            query_flag = True                                                 ###初始化查詢循環標誌###

            while query_flag:

                backend_index =input('\033[31;1m請輸入需要查詢的backend編號或名稱(返回上級菜單輸入b,退出輸入q):\033[0m')


                ##############################對輸入值進行判斷################

                (backend_name,query_flag) = backend_input_if(backend_index,haproxy_name_show_dict)

                if backend_name:                                              ###顯示對應backend下的server列表###

                    backend_server_show(backend_name,haproxy_server_show_dict)

                elif backend_index=='b':

                    break

                elif backend_index=='q':

                    sys.exit('\033[35;1m腳本退出!\033[0m')

                else:

                    query_flag=False

                    print('\033[31;1m您輸入的節點不存在!請重新輸入!')

                    time.sleep(1)


        #######################2. 添加後端服務################################

        if select_num == '2':

            add_flag = True                                                   ###初始化添加循環標誌###

            while add_flag:

                backend_index =input('\033[32;1m請輸入添加的backend的編號或名稱(返回上級菜單,請輸入b):\033[0m')

                ##############################對輸入值進行判斷################

                (backend_name,add_flag) = backend_input_if(backend_index,haproxy_name_show_dict)

                if backend_name:                                              ###顯示對應backend下的server列表###

                    backend_server_show(backend_name,haproxy_server_show_dict)

                    add_server_dict = OrderedDict()                           ###設置實例默認爲有序字典

                    print('\033[34;1m請依次輸入後端服務信息(name,address,weight,maxconn):\033[0m')

                    add_server_dict['name'] = name_decide()                  ###對輸入的name有效性進行判斷###

                    add_server_dict['address'] = ipaddress_decide()          ###對輸入的IP有效性進行判斷###

                    add_server_dict['weight'] = number_decide('權重值')      ###對輸入的權重有效性進行判斷###

                    add_server_dict['maxconn'] = number_decide('最大連接數') ###對輸入的連接數有效性進行判斷###


                    print(add_server_dict['name'],add_server_dict['address'],add_server_dict['weight'],add_server_dict['maxconn'])


                    #############對輸入的四個服務信息是否成功判斷#############

                    if add_server_dict['name'] and add_server_dict['address'] and add_server_dict['weight'] and add_server_dict['maxconn']:

                        add_commit = input('\033[31;1m請確認是否添加此條目(y | n):\033[0m')

                        if add_commit == 'y':                                 ###確認添加服務條目,並回寫配置文件###

                            haproxy_server_show_dict[backend_name].append(add_server_dict)

                            backend_server_handle(conf,haproxy_server_show_dict)

                        else:

                            add_flag = False                                  ###否則退出本次循環###

                    else:

                        print('\033[1;31m server信息輸入有誤,請重新輸入!!!\033[0m')

                        time.sleep(2)


        #######################3. 修改後端服務#################################

        if select_num == '3':

            backend_modify_flag = True                                         ###初始化修改循環標誌###

            while backend_modify_flag:

                backend_index =input('\033[32;1m請輸入修改的backend的編號或名稱(返回上級菜單,請輸入b):\033[0m')

                ##############################對輸入值進行判斷################

                (backend_name,backend_modify_flag) = backend_input_if(backend_index,haproxy_name_show_dict)


                if backend_name:                                               ###顯示對應backend下的server列表###

                    backend_server_show(backend_name,haproxy_server_show_dict)


                    server_modify_flag = True                                  ###初始化server條目修改標誌位###

                    while server_modify_flag:


                        server_index =input('\033[32;1m請輸入修改的server的編號(返回上級菜單,請輸入b):\033[0m')

                        if len(server_index) != 0:

                            server_index = input_handle(server_index)

                        if server_index == 'b':                               ###輸入b,返還上一層###

                            server_modify_flag = False

                        #####################指定具體的server編號進行判斷#####

                        elif server_index >= 1 and server_index <= len(haproxy_server_show_dict[backend_name]):

                            modify_server_dict = OrderedDict()

                            print('\033[34;1m請依次輸入後端服務信息(name,address,weight,maxconn):\033[0m')

                            modify_server_dict['name'] = name_decide()        ###對輸入的四個信息有效性進行判斷###

                            modify_server_dict['address'] = ipaddress_decide()

                            modify_server_dict['weight'] = number_decide('權重值')

                            modify_server_dict['maxconn'] = number_decide('最大連接數')


                            print(modify_server_dict['name'],modify_server_dict['address'],modify_server_dict['weight'],modify_server_dict['maxconn'])


                            ######對輸入的四個服務信息是否成功判斷#############

                            if modify_server_dict['name'] and modify_server_dict['address'] and modify_server_dict['weight'] and modify_server_dict['maxconn']:

                                modify_commit =input('\033[32;1m請確認是否修改此條目(y|n):\033[1m')

                                if modify_commit == 'y':                      ###確認修改服務條目,並回寫配置文件###

                                    haproxy_server_show_dict[backend_name][server_index - 1] = modify_server_dict

                                    backend_server_handle(conf,haproxy_server_show_dict)

                                    modify_server_flag = False


                                else:                                         ###否則退出本次循環###

                                    modify_server_flag = False

                            else:

                                print('\033[31m server輸入信息有誤,請重新輸入!!!\033[0m')

                        else:

                            print('\033[31m server編號輸入錯誤,請重新輸入!!!\033[0m')


        #######################4. 刪除後端服務################################

        if select_num == '4':

            backend_delete_flag = True                                        ###初始化刪除循環標誌###

            while backend_delete_flag:

                backend_index =input('\033[32;1m請輸入刪除的backend下條目編號或名稱(返回上層菜單,請輸入b):\033[0m')

                ##############################對輸入值進行判斷################

                (backend_name,backend_delete_flag) = backend_input_if(backend_index,haproxy_name_show_dict)


                if backend_name:                                              ###顯示對應backend下的server列表###

                    backend_server_show(backend_name,haproxy_server_show_dict)


                    server_delete_flag = True                                 ###初始化server條目刪除標誌位###

                    while server_delete_flag:


                        server_index =input('\033[32;1m請輸入要刪除的server編號(返回上層菜單,請輸入b):\033[0m')

                        if len(server_index) != 0:

                            server_index = input_handle(server_index)

                        if server_index == 'b':                               ###輸入b,返還上一層###

                            server_delete_flag = False

                        #####################指定具體的server編號進行判斷#####

                        elif server_index >= 1 and server_index <= len(haproxy_server_show_dict[backend_name]):


                            print(haproxy_server_show_dict[backend_name][server_index - 1])

                            delete_commit =input('請確認是否刪除此條目(y|n):')

                            if delete_commit == 'y':                          ###確認刪除服務條目,並回寫配置文件###

                                del haproxy_server_show_dict[backend_name][server_index - 1]

                                backend_server_handle(conf,haproxy_server_show_dict)

                                delete_server_flag = False


                            else:                                             ###否則退出本次循環###

                                delete_server_flag = False

                        else:

                            print('\033[31m server編號輸入錯誤,請重新輸入!!!\033[0m')


        #######################5. 退出程序######################

        if select_num == '5':

           print('\033[31;1m程序將在兩秒後退出,歡迎再次使用,謝謝!\033[0m')

           time.sleep(1)

           print('\033[32;1m1s\033[0m')

           time.sleep(1)

           print('\033[32;1m2s\033[0m')

           print('\033[31;1m程序退出')

           sys.exit()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章