python 解析网络设备配置文件

适用于华为华三交换机防火墙配置文件格式

增加解析汇总 ACL ,方便查看 ACL应用在哪些接口及ACL规则信息

用于定时备份设备配置文件后,对配置文件的变化做出分析。

对运行状态配置和保存配置进行对比,发现差异配置。

支持

文本文件配置文件:vrpcfg.cfg

压缩包配置文件:vrpcfg.zip(自动下载交换机/防火墙配置文件可参考其他文章)

dis cu 命令查询结果配置(自动登录并执行命令,保存回显结果可参考其他文章)

#!/usr/local/python3/bin/python3
# -*- coding: utf8 -*-
import sys, time, os, zipfile

## 终端显示颜色
if os.name == 'nt':       # Windows
    import ctypes,sys
    STD_OUTPUT_HANDLE = -11
    
    # Windows CMD命令行 字体颜色定义 text colors
    黑字 = 0x00 # black.
    FOREGROUND_DARKBLUE = 0x01 # dark blue.
    FOREGROUND_DARKGREEN = 0x02 # dark green.
    FOREGROUND_DARKSKYBLUE = 0x03 # dark skyblue.
    FOREGROUND_DARKRED = 0x04 # dark red.
    FOREGROUND_DARKPINK = 0x05 # dark pink.
    FOREGROUND_DARKYELLOW = 0x06 # dark yellow.
    FOREGROUND_DARKWHITE = 0x07 # dark white.
    FOREGROUND_DARKGRAY = 0x08 # dark gray.
    FOREGROUND_BLUE = 0x09 # blue.
    FOREGROUND_GREEN = 0x0a # green.
    FOREGROUND_SKYBLUE = 0x0b # skyblue.
    FOREGROUND_RED = 0x0c # red.
    FOREGROUND_PINK = 0x0d # pink.
    FOREGROUND_YELLOW = 0x0e # yellow.
    FOREGROUND_WHITE = 0x0f # white.
    
    std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
    
    def set_cmd_text_color(color, handle=std_out_handle):
        Bool = ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
        return Bool
    
    def resetColor():
        set_cmd_text_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
    
    def 打印_黑(TEXT, SHOW=1):
        if SHOW == 1:
            set_cmd_text_color(黑字)
            sys.stdout.write(TEXT+'\n')
            resetColor()
    def 打印_红(TEXT, SHOW=1):
        if SHOW == 1:
            set_cmd_text_color(FOREGROUND_RED)
            sys.stdout.write(TEXT+'\n')
            resetColor()
    def 打印_绿(TEXT, SHOW=1):
        if SHOW == 1:
            set_cmd_text_color(FOREGROUND_GREEN)
            sys.stdout.write(TEXT+'\n')
            resetColor()
    def 打印_黄(TEXT, SHOW=1):
        if SHOW == 1:
            set_cmd_text_color(FOREGROUND_YELLOW)
            sys.stdout.write(TEXT+'\n')
            resetColor()
    def 打印_蓝(TEXT, SHOW=1):
        if SHOW == 1:
            set_cmd_text_color(FOREGROUND_BLUE)
            sys.stdout.write(TEXT+'\n')
            resetColor()
    def 打印_紫(TEXT, SHOW=1):
        if SHOW == 1:
            set_cmd_text_color(FOREGROUND_PINK)
            sys.stdout.write(TEXT+'\n')
            resetColor()
    
    def 打印_青(TEXT, SHOW=1):
        if SHOW == 1:
            set_cmd_text_color(FOREGROUND_SKYBLUE)
            sys.stdout.write(TEXT+'\n')
            resetColor()
elif os.name == 'posix':  # Linux
    
    def 打印_黑(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;30;1m{TEXT}\033[0m")
    
    def 打印_红(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;31;1m{TEXT}\033[0m")
    
    def 打印_绿(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;32;1m{TEXT}\033[0m")
    
    def 打印_黄(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;33;1m{TEXT}\033[0m")
    
    def 打印_蓝(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;34;1m{TEXT}\033[0m")
    
    def 打印_紫(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;35;1m{TEXT}\033[0m")
    
    def 打印_青(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;36;1m{TEXT}\033[0m")
    
    def 打印_白(TEXT, SHOW=1):
        if SHOW == 1:
            print(f"\033[0;37;1m{TEXT}\033[0m")

## 读取网络设备上下载的 startup.cfg 配置文件(文本文件)
## 读取 dis cu 查询配置保存下来的文本文件
def 读取文本文件内容(FILE_PATH):
    L_编码 = ['UTF8', 'GB2312', 'GBK', 'BIG5']
    TEXT = None
    if os.path.isfile(FILE_PATH):
        for 编码 in L_编码:
            try:
                #print(f"尝试 {编码}")
                f = open(FILE_PATH, 'r', encoding=编码)
                TEXT = f.read()
            except Exception as e:
                f.close()
                #打印_红(f"{编码}编码读取{FILE_PATH}失败{e}")
            else:
                f.close()
                #print(f"成功 TEXT={TEXT}")
                return(TEXT)
    else:
        打印_红(f"ERROR 文件 {FILE_PATH} 不存在")
        return(TEXT)
    打印_红(f"ERROR 文件 {FILE_PATH} 字符编码解码失败,超出{L_编码}范围")
    return(TEXT)

## 网络设备上下载的配置文件有压缩包类型,如:vrpcfg.zip 里面就一个配置文本文件 vrpcfg.cfg
def 读取ZIP中第一个文件(FILE_PATH):
    TEXT = None
    if os.path.isfile(FILE_PATH):
        if zipfile.is_zipfile(FILE_PATH):
            try:
                f = zipfile.ZipFile(FILE_PATH)
            except Exception as e:
                ERROR = f'ERROR zipfile 打开 {FILE_PATH} 失败 {e}'
                打印_红(ERROR)
                return()
            else:
                for i in f.namelist():
                    #print("ZIP内文件", i)
                    文件名, 扩展名 = os.path.splitext(i)
                    #print(文件名, 扩展名)
                    if i.endswith('/'):
                        #print(f"目录 {i}")
                        pass
                    else:
                        #print(f"文件 {i}")
                        try:
                            DATA = f.open(i)
                        except Exception as e:
                            ERROR = f'ERROR 打开 {i} 失败 {e}'
                            print(ERROR)
                        else:
                            TEXT = DATA.read().decode('GB2312')     # 一般是 GB2312
                            #print("TEXT", TEXT)
                            break
        else:
            打印_红(f"ERROR {FILE_PATH} 不是ZIP格式文件")
    else:
        打印_红(f"ERROR {FILE_PATH} 不存在或不是文件")
    return(TEXT)

def 前置空格数(TEXT):
    N = 0
    for i in TEXT:
        if i == ' ':
            N += 1
        else:
            break
    return(N)

def 配置文本分段分行(TEXT_CONF, SHOW=0):
    LL_CONF = []
    LL_配置行 = [[j for j in i.split('\r')] for i in TEXT_CONF.split('\n')] # 以换行符分段
    #打印_蓝(f"换行符分段 LL_配置行={LL_配置行}", SHOW)
    L_配置段 = []
    for L_配置行 in LL_配置行:
        #打印_红(f"{L_配置行}", SHOW)
        for 配置行 in L_配置行:
            if 配置行.strip() != '':   # 忽略空配置行
                if 配置行 == '#':      # 遇到分段符号'#'进行分段保存
                    if L_配置段 != []:
                        LL_CONF.append(L_配置段)
                        L_配置段 = []  # 重置为空列表
                else:
                    L_配置段.append(配置行)
    #打印_绿(f"{LL_CONF}", SHOW)
    #for i in LL_CONF:
    #    打印_蓝(f"{i}\n", SHOW)
    return(LL_CONF)

def 配置行转配置信息字典(LL_CONF, SHOW=0):
    打印_红("[配置行转配置信息字典]", SHOW)
    D_NET_CONF = {'GLOBAL':[]}
    for L_配置段 in LL_CONF:
        打印_红(f"L_配置段={L_配置段}", SHOW)
        KEY = 'GLOBAL'
        for TEXT_配置行 in L_配置段:
            配置行前置空格数 = 前置空格数(TEXT_配置行)
            打印_蓝(f"  前置空格数={配置行前置空格数} TEXT_配置行={TEXT_配置行}", SHOW)
            if 配置行前置空格数 == 0:
                KEY = TEXT_配置行           # 更新KEY
                if KEY not in D_NET_CONF:
                    D_NET_CONF[KEY] = []
                打印_绿(f"    KEY={KEY}", SHOW)
            else:
                D_NET_CONF[KEY].append(TEXT_配置行)
                打印_绿(f"    D_NET_CONF[{KEY}].append({TEXT_配置行})", SHOW)
    return(D_NET_CONF)

def 转换网络TXT配置文件(FILE_CONF_PATH, SHOW=0):
    D_NET_CONF = {}
    TEXT_CONF = 读取文本文件内容(FILE_CONF_PATH)
    打印_黄(f"TEXT_CONF={TEXT_CONF}", SHOW)
    if TEXT_CONF != None:
        LL_CONF = 配置文本分段分行(TEXT_CONF, SHOW)
        D_NET_CONF = 配置行转配置信息字典(LL_CONF, SHOW)
    return(D_NET_CONF)

def 转换网络ZIP配置文件(FILE_CONF_PATH, SHOW=0):
    D_NET_CONF = {}
    TEXT_CONF = 读取ZIP中第一个文件(FILE_CONF_PATH)
    打印_黄(f"TEXT_CONF={TEXT_CONF}", SHOW)
    if TEXT_CONF != None:
        LL_CONF = 配置文本分段分行(TEXT_CONF, SHOW)
        D_NET_CONF = 配置行转配置信息字典(LL_CONF, SHOW)
    return(D_NET_CONF)

def 网络配置文件转配置字典(FILE_CONF_PATH, SHOW=0):
    FILE_NAME = os.path.basename(FILE_CONF_PATH)
    SP = FILE_NAME.split('.')
    if SP != [] and SP[-1].lower() == 'zip':
        D_NET_CONF = 转换网络ZIP配置文件(FILE_CONF_PATH, SHOW)
    else:
        D_NET_CONF = 转换网络TXT配置文件(FILE_CONF_PATH, SHOW)
    配置字典再加工(D_NET_CONF, SHOW)
    return(D_NET_CONF)

def SAVE_TEXT(TEXT, SAVE_PATH, SHOW=1):
    try:
        f = open(SAVE_PATH, 'w')
        BYTES = f.write(TEXT)
        f.close()
    except Exception as e:
        打印_红(f"{SAVE_PATH} X", SHOW)
    else:
        打印_绿(f"{SAVE_PATH} V {BYTES}", SHOW)

def 对比配置字典(D_OLD, D_NEW, SHOW=1):
    TEXT_对比结果 = ''
    if D_OLD != {} and D_NEW != {}:
        ## 对比新旧配置项是否有新增或删除
        P_KEY_D_OLD = set([K for K in D_OLD])   # 旧配置项
        P_KEY_D_NEW = set([K for K in D_NEW])   # 新配置项
        #print(f"P_KEY_D_OLD={P_KEY_D_OLD}")
        #print(f"P_KEY_D_NEW={P_KEY_D_NEW}")
        P_KEY_OLD_独有 = P_KEY_D_OLD - P_KEY_D_NEW
        P_KEY_NEW_独有 = P_KEY_D_NEW - P_KEY_D_OLD
        if P_KEY_OLD_独有 == P_KEY_NEW_独有 == set():
            P_KEY_共有 = P_KEY_D_OLD
            INFO = f"    [新旧配置项] 一致"
            TEXT_对比结果 += INFO+'\n'
            打印_绿(INFO, SHOW)
        else:
            P_KEY_共有 = P_KEY_D_OLD & P_KEY_D_NEW
            INFO = f"    [新旧配置项] 不同\n      P_KEY_OLD_独有 {P_KEY_OLD_独有}\n      P_KEY_NEW_独有 {P_KEY_NEW_独有}"
            打印_黄(INFO, SHOW)
            TEXT_对比结果 += INFO+'\n'
            for KEY in P_KEY_OLD_独有:
                INFO = f"      [删除配置项] {KEY} 【配置项内容】 {D_OLD[KEY]}"
                TEXT_对比结果 += INFO+'\n'
                打印_蓝(INFO, SHOW)
            for KEY in P_KEY_NEW_独有:
                INFO = f"      [新增配置项] {KEY} 【配置项内容】 {D_NEW[KEY]}"
                TEXT_对比结果 += INFO+'\n'
                打印_青(INFO, SHOW)
        ## 相同配置项对比配置内容是否有变化
        for KEY in P_KEY_共有:
            if D_OLD[KEY] != D_NEW[KEY]:
                P_OLD_配置行 = set(D_OLD[KEY])
                P_NEW_配置行 = set(D_NEW[KEY])
                if P_OLD_配置行 == P_NEW_配置行:
                    INFO = f"      [配置项] {KEY} 配置行内容有重复"
                    TEXT_对比结果 += INFO+'\n'
                    打印_红(INFO, SHOW)
                else:
                    INFO = f"      [变化配置项] {KEY}"
                    TEXT_对比结果 += INFO+'\n'
                    打印_红(INFO, SHOW)
                    for i in P_OLD_配置行-P_NEW_配置行:
                        INFO = f"        [DEL] {i}"
                        TEXT_对比结果 += INFO+'\n'
                        打印_蓝(INFO, SHOW)
                    for i in P_NEW_配置行-P_OLD_配置行:
                        INFO = f"        [ADD] {i}"
                        TEXT_对比结果 += INFO+'\n'
                        打印_青(INFO, SHOW)
    else:
        if D_OLD == {}:
            INFO = "    D_OLD 无有效内容"
            TEXT_对比结果 += INFO+'\n'
            打印_红(INFO)
        if D_NEW == {}:
            INFO = "    D_NEW 无有效内容"
            TEXT_对比结果 += INFO+'\n'
            打印_红(INFO)
    return(TEXT_对比结果)

def 载入字典形式文本文件(FILE_PATH):
    D = {}
    if os.path.isfile(FILE_PATH):
        try:
            f = open(FILE_PATH, 'r')
            TEXT = f.read()
            f.close()
        except Exception as e:
            打印_红(f"读取文件 {FILE_PATH} 失败 {e}")
        else:
            D = eval(TEXT)
    else:
        打印_红(f"    ERROR 文件{FILE_PATH}不存在")
    return(D)

def 防火墙安全规则转字典(LL_CONF, SHOW=0):
    打印_红("[防火墙安全规则转字典]", SHOW)
    D_security_policy = {'security-policy':[]}
    KEY = 'security-policy'
    for TEXT_配置行 in LL_CONF:
        配置行前置空格数 = 前置空格数(TEXT_配置行)
        打印_蓝(f"  前置空格数={配置行前置空格数} TEXT_配置行={TEXT_配置行}", SHOW)
        if 配置行前置空格数 == 1:
            KEY = ('security-policy', TEXT_配置行)           # 更新KEY
            if KEY not in D_security_policy:
                D_security_policy[KEY] = []
            打印_绿(f"    KEY={KEY}", SHOW)
        else:
            D_security_policy[KEY].append(TEXT_配置行)
            打印_绿(f"    D_security_policy[{KEY}].append({TEXT_配置行})", SHOW)
    return(D_security_policy)

def AAA用户信息转字典(LL_CONF, SHOW=0):
    打印_红("[AAA用户信息转字典]", SHOW)
    D_AAA = {'aaa':[]}
    KEY = 'aaa'
    for TEXT_配置行 in LL_CONF:
        配置行前置空格数 = 前置空格数(TEXT_配置行)
        打印_蓝(f"  前置空格数={配置行前置空格数} TEXT_配置行={TEXT_配置行}", SHOW)
        if 配置行前置空格数 == 1:
            KEY = ('aaa', TEXT_配置行)           # 更新KEY
            if KEY not in D_AAA:
                D_AAA[KEY] = []
            打印_绿(f"    KEY={KEY}", SHOW)
        else:
            D_AAA[KEY].append(TEXT_配置行)
            打印_绿(f"    D_AAA[{KEY}].append({TEXT_配置行})", SHOW)
    return(D_AAA)

def 配置字典再加工(D_NET_CONF, SHOW=0):
    # 删除一些无用信息(注释、查询命令等)
    for K in [i for i in D_NET_CONF]:
        if K == 'dis cu' or K[0] in ('*', '<', '[', '\x00'):
            del D_NET_CONF[K]
            打印_黄(f"  删除 {K}", SHOW)
        #else:
        #    打印_绿(f"  保留 {K}", SHOW)
    
    # 删除空全局配置
    if 'GLOBAL' in D_NET_CONF and D_NET_CONF['GLOBAL'] == []:
        del D_NET_CONF['GLOBAL']
        打印_黄(f"  删除 空 D_NET_CONF['GLOBAL']", SHOW)
    
    # 进一步细分,整理防火墙安全策略信息,方便对比策略变化
    if 'security-policy' in D_NET_CONF:
        #print(D_NET_CONF['security-policy'])
        LL_CONF = D_NET_CONF['security-policy']
        D_security_policy = 防火墙安全规则转字典(LL_CONF, SHOW)
        del D_NET_CONF['security-policy']
        for K in D_security_policy:
            D_NET_CONF[K] = D_security_policy[K]
    
    # 进一步细分,整理aaa用户信息,方便对比用户信息变化
    if 'aaa' in D_NET_CONF:
        LL_CONF = D_NET_CONF['aaa']
        D_AAA = AAA用户信息转字典(LL_CONF, SHOW)
        del D_NET_CONF['aaa']
        for K in D_AAA:
            D_NET_CONF[K] = D_AAA[K]

def TEST_换行符分段():
    TEXT = 'aa\r\nbb\ncc\rdd\n\ne\r\rf\n g g \n'
    print(TEXT)
    print("\\r  ", TEXT.split('\r'))
    print("\\n  ", TEXT.split('\n'))
    print("\\r\\n", TEXT.split('\r\n'))
    
    print("分段 先\\r 再\\n")
    Lr = [i for i in TEXT.split('\r')]
    print("Lr", Lr)
    LL = [[j for j in i.split('\n')] for i in TEXT.split('\r')]
    print("LL", LL)
    
    print()
    
    print("分段 先\\n 再\\r")
    Ln = [i for i in TEXT.split('\n')]
    print("Ln", Ln)
    LL = [[j for j in i.split('\r')] for i in TEXT.split('\n')]
    print("LL", LL)
    
    for i in LL:
        for j in i:
            print(j)
    
    for i in LL:
        for j in i:
            if j != '':
                print(j)


## ACL 解析
def 配置字典转ACL信息字典(D_NET_CONF, SHOW=0):
    D_ACL_INFO = {}
    #{
    #   (ACL_ID, ACL_NAME):{
    #       'RULE':['RULE 明细', ],
    #       '规则应用信息:[{
    #           'TYPE': '接口或其他'
    #           'CONF': '规则应用配置,进出方向等'
    #           'DESC': '备注',
    #           }, {}]
    #      },
    #   (ACL_ID, ACL_NAME):{},
    #   },
    #}
    
    for KEY in D_NET_CONF:
        if type(KEY) == str:
            SP_KEY = KEY.split()
            if SP_KEY != [] and SP_KEY[0] == 'acl':
                打印_紫(f"ACL : {KEY}", SHOW)
                if 'number' in SP_KEY:
                    ACL_ID = SP_KEY[SP_KEY.index('number')+1]
                else:
                    ACL_ID = ''
                if 'name' in SP_KEY:
                    ACL_NAME = SP_KEY[SP_KEY.index('name')+1]
                else:
                    ACL_NAME = ''
                D_ACL_INFO[(ACL_ID,ACL_NAME)] = {'RULE':D_NET_CONF[KEY], '规则应用信息':[]}
            
    #打印_红(f"D_ACL_INFO={D_ACL_INFO}")
    
    ## 解析ACL在接口上的应用信息
    for KEY in D_NET_CONF:
        打印_紫(f"KEY={KEY}", SHOW)
        if type(KEY) == str:
            SP_KEY = KEY.split()
            if SP_KEY != [] and SP_KEY[0] == 'interface':
                打印_蓝(f"interface : {KEY}", SHOW)
                for 接口配置行 in D_NET_CONF[KEY]:
                    L_SP_接口配置 = 接口配置行.split()
                    if 'packet-filter' in L_SP_接口配置 or 'traffic-filter' in L_SP_接口配置:
                        for ACL_ID,ACL_NAME in D_ACL_INFO:
                            if ACL_ID in L_SP_接口配置 or ACL_NAME in L_SP_接口配置:
                                打印_蓝(f"{(ACL_ID,ACL_NAME)}", SHOW)
                                
                                L_接口备注 = [i for i in D_NET_CONF[KEY] if 'description' in i.split()]
                                if L_接口备注 != []:
                                    接口备注 = L_接口备注[0].strip()
                                else:
                                    接口备注 = '无'
                                打印_绿(f"        {KEY:22s} {接口配置行:33s} | {接口备注}", SHOW)
                                D_ACL_INFO[(ACL_ID,ACL_NAME)]['规则应用信息'].append({'TYPE':KEY, 'CONF':接口配置行.strip(), 'DESC':接口备注})
                        
                                for RULE_TEXT in D_ACL_INFO[(ACL_ID,ACL_NAME)]['RULE']:
                                    打印_青(f"           {RULE_TEXT}", SHOW)
            elif SP_KEY != [] and SP_KEY[0] == 'acl':
                打印_红(f"ACL : {KEY} PASS", SHOW)
            else:
                ## ACL 应用在顶级配置上
                打印_黄(f"Other : {KEY}", SHOW)
                for ACL_ID,ACL_NAME in D_ACL_INFO:
                    if ACL_ID in SP_KEY or ACL_NAME in SP_KEY:
                        if D_NET_CONF[KEY] == []:
                            CONF = ''
                        else:
                            CONF = str(D_NET_CONF[KEY])
                        DESC = ''
                        打印_蓝(f"{(ACL_ID,ACL_NAME)}", SHOW)
                        打印_绿(f"        {KEY:22s} {CONF:33s} |", SHOW)
                        D_ACL_INFO[(ACL_ID,ACL_NAME)]['规则应用信息'].append({'TYPE':KEY, 'CONF':CONF, 'DESC':DESC})
                    else:
                        for 配置行 in D_NET_CONF[KEY]:
                            L_SP_配置行 = 配置行.split()
                            if ACL_ID in L_SP_配置行 or ACL_NAME in L_SP_配置行:
                                CONF = 配置行.strip()
                                DESC = ''
                                打印_蓝(f"{(ACL_ID,ACL_NAME)}", SHOW)
                                打印_绿(f"        {KEY:22s} {CONF:33s} |", SHOW)
                                D_ACL_INFO[(ACL_ID,ACL_NAME)]['规则应用信息'].append({'TYPE':KEY, 'CONF':CONF, 'DESC':DESC})
                    
    return(D_ACL_INFO)

def 配置文件转ACL信息字典(FILE_CONF_PATH, SHOW=0):
    D_NET_CONF = 网络配置文件转配置字典(FILE_CONF_PATH, SHOW)
    D_ACL_INFO = 配置字典转ACL信息字典(D_NET_CONF, SHOW)
    return(D_ACL_INFO)

def ACL信息字典转文本(D_ACL_INFO):
    换行符 = '\n'
    TEXT = ''
    for K in D_ACL_INFO:
        TEXT += f"  ACL={K}{换行符}"
        TEXT += f"    规则应用信息{换行符}"
        for 规则应用信息 in D_ACL_INFO[K]['规则应用信息']:
            TEXT += f"      {规则应用信息}{换行符}"
        TEXT += f"    ACL规则{换行符}"
        for RULE in D_ACL_INFO[K]['RULE']:
            TEXT += f"      {RULE}{换行符}"
        TEXT += 换行符
    return(TEXT)



## 测试
if __name__ == '__main__':
    
    def 测试_文本配置文件(FILE_CONF_PATH):
        D_NET_CONF = 转换网络TXT配置文件(FILE_CONF_PATH, SHOW=1)
        for K in D_NET_CONF:
            打印_红(f"{K}")
            打印_蓝(f"    {D_NET_CONF[K]}")
    #FILE_CONF_PATH = 'E:\\TEST\\A.down_run_txt'
    #测试_文本配置文件(FILE_CONF_PATH)
    
    def 测试_压缩包配置文件(FILE_CONF_PATH):
        D_NET_CONF = 转换网络ZIP配置文件(FILE_CONF_PATH, SHOW=1)
        for K in D_NET_CONF:
            打印_红(f"{K}")
            打印_蓝(f"    {D_NET_CONF[K]}")
    #FILE_CONF_PATH = 'E:\\TEST\\A_vrpcfg.zip'
    #测试_压缩包配置文件(FILE_CONF_PATH)
    
    def 测试_对比两个配置文件差异(FILE_CONF_OLD_PATH, FILE_CONF_NEW_PATH):
        D_NET_CONF_OLD = 网络配置文件转配置字典(FILE_CONF_OLD_PATH, SHOW=0)
        D_NET_CONF_NEW = 网络配置文件转配置字典(FILE_CONF_NEW_PATH, SHOW=0)
        打印_蓝(f"OLD {FILE_CONF_OLD_PATH}")
        打印_青(f"NEW {FILE_CONF_NEW_PATH}")
        TEXT_对比结果 = 对比配置字典(D_NET_CONF_OLD, D_NET_CONF_NEW, SHOW=1)
        打印_紫(TEXT_对比结果)
    #FILE_CONF_OLD_PATH = 'E:\\TEST\\A_vrpcfg.zip'
    #FILE_CONF_NEW_PATH = 'E:\\TEST\\A.down_run_txt'
    #测试_对比两个配置文件差异(FILE_CONF_OLD_PATH, FILE_CONF_NEW_PATH)
    
    def 测试_解析配置后保存为字典类型文本文件(FILE_CONF_PATH, SAVE_PATH):
        D_NET_CONF = 网络配置文件转配置字典(FILE_CONF_PATH, SHOW=1)
        SAVE_TEXT(f"{D_NET_CONF}", SAVE_PATH, SHOW=1)
    #FILE_CONF_PATH = 'E:\\TEST\\A_vrpcfg.zip'
    #SAVE_PATH = 'E:\\TEST\\A_vrpcfg.zip.cfg_dict_txt'
    #测试_解析配置后保存为字典类型文本文件(FILE_CONF_PATH, SAVE_PATH)
    
    def 测试_读取字典形式保存的配置文件(FILE_PATH):
        D_NET_CONF = 载入字典形式文本文件(FILE_PATH)
        for K in D_NET_CONF:
            打印_红(f"{K}")
            打印_蓝(f"    {D_NET_CONF[K]}")
    #FILE_PATH = 'E:\\TEST\\A_vrpcfg.zip.cfg_dict_txt'
    #测试_读取字典形式保存的配置文件(FILE_PATH)
    
    ## 交换机 ACL 信息整理
    #FILE_CONF_PATH = f'E:\\TEST\\A_vrpcfg.zip'
    #D_ACL_INFO = 配置文件转ACL信息字典(FILE_CONF_PATH, SHOW=0)
    #TEXT = ACL信息字典转文本(D_ACL_INFO)
    #打印_黄(TEXT)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值