Python-修改配置文件

配置文件的修改


功能:
主要用來作爲功能菜單選擇及相關模塊的選擇、處理功能,包括:
        1 查看所有 backend 的配置信息
        2 添加配置信息
        3 刪除配置信息


設計思路:
查看功能: 打開配置文件,一行一行的進行讀取,當發現有 backend開頭行時,再判斷後面的 域名是否等於要查找的名稱,如果是則做一個標記,判斷標記
           爲True時開始寫到變量中,直到找到下一個backend時將標誌位置False
添加配置信息:新建一個臨時文件,同查找功能一樣一行一行讀取寫入臨時文件,同時判斷當找到指定backend的記錄後,置標誌位,到下一個backend記錄時
            將新增加的記錄寫入文件,再將剩下的配置信息寫入到文件中。最後進行重命名操作替換到以前的配置文件
刪除配置信息: 同添加類似,一行一行讀取。當找到與要刪除的配置一樣時,就把那一行跳過不寫入文件

2 haconfig.py       haproxy 自定義類

功能:
此文件主要是將要操作的配置文件進行一個類的封裝。
用戶的添加、刪除、查找等操作都在類實現了具體的方法。並增加了 IP 地址合法性的判斷。將用戶輸入的配置參數中的: IP地址、weight值、maxconn值
作爲類的一個屬性進行處理,在類內部通過字符串的拼接生成配置串
包括方法:
1 獲取所有backend下的配置信息 : show_show_backend()
2 添加配置信息: add_backend()
3 刪除配置信息: del_backend()
4 檢查ip合法性:check_ip_available
5 字符串拼接:union_str

6 獲取backend的所有節點名; get_backend_name




流程圖:



源碼;

haconfig.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import shutil
import re


_default_path = os.path.dirname(os.path.abspath("__file__"))
class haproxy(object):

    _default_path = os.path.dirname(os.path.abspath("__file__"))
    _default_file = os.path.join(_default_path, "config.ini")
    _tmp_file = os.path.join(_default_path, "tmp.ini")

    def __init__(self, ip='', weight=20, max_conn=100, file=_default_file):
        self.config_file = file
        self.ip_address = ip
        self.weight = weight
        self.max_conn = max_conn
        self.backend_contant = ''
        self.backend_name = list()

    # 檢查ip是否合法,變爲一個屬性
    @property
    def check_ip_available(self):
        rule = "((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"
        #         (200-240   | 250- 255|0-199|). 重複3次       IP
        r = re.compile(rule)
        if r.match(self.ip_address):
            return True
        else:
            return False

    # 拼接字符串
    def union_str(self):
        """
        添加或修改backend的內容時,調用此類方法,將輸入的參數值拼接成一行完成配置信息
        :return: 更新到self.backend_value屬性中,
        """
        _default_str = 'server {ip} {ip} weight {weight} maxconn {maxconn}'
        self.backend_contant = _default_str.format(ip=self.ip_address,
                                                   weight=self.weight,
                                                   maxconn=self.max_conn)

    def get_backend_name(self):
        """
        獲取配置文件中的所有 backend 節點信息
        :return: 無返回值,保存在 self.backend_name 中
        """
        with open(self.config_file, 'r') as fr:
            for line in fr:
                if line.startswith("backend"):
                    self.backend_name.append(line.split()[1])

    # 查找指定 backend 節點下的配置信息
    def show_backend(self, backend):
        """
        根據用戶輸入的 backend 節點值獲取對應的配置文件
        :param backend: 查找的鍵值,如: test.oldboy.org
        :return: 返回一個列表  list
        """
        result = list()
        # 定位到查找的行標識
        line_locked_flag = False

        with open(self.config_file, 'r', encoding='utf-8') as f:
            for line in f:
                # 如果找到 backend 配置節
                if line.startswith('backend'):
                    # 獲取backend的內容,test.oldboy.com
                    url_addr = line.split()[1]
                    # 如果內容和搜索的內容一樣,則將定位標識置爲True
                    if url_addr == backend:
                        line_locked_flag = True
                        continue
                    else:
                        line_locked_flag = False

                # 如果定位到內容則將配置寫入到結果列表中
                if line_locked_flag:
                    result.append(line)
        return result

    # 增加backend內容
    def add_backend(self, backend):
        """
        根據輸入的backend查找文件:
        如果存在 backend,則在配置末尾增加一條記錄
        如果不存在 backend,則在最後新增加一個
        :param backend: 要增加的backend,如:test.oldboy.com
        :return:
        """
        # 是否存在指定的backend標識,如果存在就在指定下面添加配置,沒有就新建一個backend,再添加配置
        backend_is_exists_flag = False
        # 定位到查找的行標識
        line_locked_flag = False

        try:
            with open(self.config_file, 'r') as fr,open(self._tmp_file, 'a+') as fw:
                for line in fr:
                    if line.startswith('backend'):
                        url_addr = line.split()[1]
                        if url_addr == backend:
                            backend_is_exists_flag = True
                            line_locked_flag = True
                        else:
                            # 找到"backend"字符標識,且定位標識爲True,說明到了定位的下一個backend,這時需要先追加一條配置
                            if line_locked_flag:
                                fw.write("        {content}\n".format(content=self.backend_contant))
                                line_locked_flag = False
                    fw.write(line)

                # 文件中沒有要添加的 backend 節點,那在最後新增加一個節點
                if not backend_is_exists_flag:
                    fw.write("backend {url}\n".format(url=backend))
                    fw.write("        {content}\n".format(content=self.backend_contant))

            # 將臨時文件重命名,替換原來的配置文件
            shutil.move(self._tmp_file, self.config_file)

            return True
        except Exception as e:
            return e

    # 刪除指定 backend 的配置
    def del_backend(self, backend):
        is_locked_flag = False
        # 是否找到指定的 IP 配置信息
        is_delete_flag = False
        try:
            with open(self.config_file, 'r') as fr, open(self._tmp_file, 'a+') as fw:
                for line in fr:
                    # 找到backend行
                    if line.startswith("backend"):
                        url_addr = line.split()[1]
                        # 找到指定的backend節點
                        if url_addr == backend:
                            is_locked_flag = True
                        else:
                            # 找到指定 backend 節點的下一個backend, 定位標識別改爲False
                            if is_locked_flag:
                                is_locked_flag = False
                    else:
                        if is_locked_flag:
                            # 在定位的 backend 節點下找到符合的 IP ,則把這一行跳過,不寫到tmp文件中
                            if line.count(self.ip_address) > 0:
                                is_delete_flag = True
                                continue

                    fw.write(line)
            shutil.move(self._tmp_file, self.config_file)
            if not is_delete_flag:
                return False
            else:
                return True
        except Exception as e:
            return e
Modify_ini.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from haconfig import haproxy

welcome_title_str = "%s\n#%s#\n#%s#\n#%s#\n%s" % ("".ljust(50, '#'),
                                                  ''.ljust(48, ' '),
                                                  'HAProxy 配置管理程序'.center(43, ' '),
                                                  ''.ljust(48, ' '),
                                                  ''.ljust(50, '#')
                                                  )
menu_str = "\n1.查找配置\n2.添加配置\n3.刪除配置\n4.退出程序\n"


# 返回一個非空的輸入
def input_string(show_message, is_int=False):
    """
    對input函數進行重新改造,增加判斷不能爲空,
    :param show_message: input()中的提示信息
    :param is_int: 是否要求輸入必須爲數字,默認爲False,如果爲True就要檢查是否爲數字
    :return: 返回用戶輸入的值
    """
    not_null_flag = False
    while not not_null_flag:
        # 獲得用戶的輸入信息
        input_value = input("{message}".format(message=show_message)).strip().lower()
        if not input_value:
            continue
        else:
            # 如果要求輸入必須爲數字,則做以下驗證
            if is_int:
                if not input_value.isdigit():
                    print("\n\033[1;30m非法輸入,請輸入一個數字!\033[0m")
                    continue
            not_null_flag = True
    return input_value


if __name__ == "__main__":
    print(welcome_title_str)

    # 退出系統標識
    exit_flag = False
    while not exit_flag:
        print(menu_str)
        choose = input("請選擇功能模塊:").strip().lower()

        # 退出系統
        if choose == '4':
            exit_flag = True
            continue

        if choose not in ('1', '2', '3'):
            print("\n\033[1;31m輸入錯誤!請輸入正確的功能編號.\033[0m")
        else:
            # 實例化配置文件對象
            proxyobj = haproxy()

            # 1. 查找節點配置信息
            if choose == "1":
                # 獲取所有 backend 的節點名稱
                proxyobj.get_backend_name()
                print("\n當前配置文件所有 backend 節點名稱:")
                for name in proxyobj.backend_name:
                    print(name)

                search_backend = input_string("\n請輸入要查找的 backend 域名:")
                # 調用類方法獲取配置信息列表
                search_result = proxyobj.show_backend(search_backend)
                if not search_result:
                    print("\n\033[1;30m沒有找到要查找的記錄!\033[1m\n ")
                else:
                    for record in search_result:
                        print(record.strip())

            # 2. 添加配置
            if choose == "2":
                search_backend = input_string("請輸入要添加的 backend 域名:")
                # 對配置文件對象進行賦值
                proxyobj.ip_address = input_string("請輸入添加的 IP 地址:")
                # 判斷IP是否合法
                while not proxyobj.check_ip_available:
                    proxyobj.ip_address = input_string("\nIP地址不合法! 請重新輸入 IP 地址:")
                proxyobj.weight = input_string("請輸入添加的 weight 值:", is_int=True)
                proxyobj.max_conn = input_string("請輸入添加的 max conn 值:", is_int=True)

                # 根據用戶輸入的信息,調用類的格式化字符串方法生成配置文件串
                proxyobj.union_str()

                # 調用添加方法進行添加配置操作
                if proxyobj.add_backend(search_backend):
                    print("\n添加成功! 節點當前配置更新爲:")

                # 將添加成功的信息打印出來,直接調用類的查看方法
                search_result = proxyobj.show_backend(search_backend)
                for line in search_result:
                    print(line.strip())

            # 3. 刪除配置
            if choose == "3":
                # 重新獲取一下當前配置文件中的節點名稱列表
                proxyobj.get_backend_name()

                # 要刪除的 backend 節點是否存在標識
                is_exist_flag = False
                while not is_exist_flag:
                    search_backend = input_string("請指定要刪除配置的 backend 節點名稱: ")
                    if search_backend not in proxyobj.backend_name:
                        print("\n當前配置文件中未找到 %s 的 backend 節點!" %search_backend)
                        continue
                    else:
                        is_exist_flag = True

                proxyobj.ip_address = input_string("請輸入要刪除的 IP 地址:")
                # 判斷IP是否合法
                while not proxyobj.check_ip_available:
                    proxyobj.ip_address = input_string("\nIP地址不合法! 請重新輸入 IP 地址:")

                # 調用類的刪除方法進行刪除操作
                if proxyobj.del_backend(search_backend):
                    print("\n刪除成功!當前節點配置更新爲: ")
                else:
                    print("\n刪除失敗!請檢查 IP 地址是否存在!\n")

                # 將修改後的信息打印出來,直接調用類的查看方法
                search_result = proxyobj.show_backend(search_backend)
                for line in search_result:
                    print(line.strip())


發佈了35 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章