网络设备自动化测试之逻辑拓扑自动生成

设计说明

网络设备功能测试自动化时,有成千上万个测试案例,幸好拓扑总共只有几十种。但是仍然不能针对每种拓扑都去连好线,这样资源开销太大,又难以维护。实际中我们使用拓扑交换,每台DUT只需要和拓扑交换机相连即可。然后定义好这几十种逻辑拓扑的xml文件,测试用例中指明所使用的拓扑。运行用例时根据逻辑拓扑来划分拓扑交换机上的vlan,从而实现逻辑拓扑的自动生成。同时也会为每个DUT的接口自动配置IP地址。

这种逻辑拓扑生成的方式非常灵活,支持以任意顺序执行全部或者任意部分的测试用例。

扩展性好:增加新拓扑只需要定义新的逻辑拓扑xml文件。如果DUT数目不足,可以在物理拓扑中增加新的DUT。如果拓扑交换机的端口不足,可以轻松扩展为支持多个拓扑交换机。

代码实现

pysical_top.xml:

这里dut1使用了逻辑端口编号,而拓扑交换机使用了实际的接口编号。是因为DUT的端口常会变化,但是拓扑交换机的接口通常不变。这里只列出了三台DUT,实际中DUT比这个多。实际中还有测试仪接口连接在拓扑交换机上。但是因为对测试仪接口的拓扑生成和DUT的一样,所以这里没有额外再列出。这个框架可以轻松扩展为支持多个拓扑交换机,只需要将物理拓扑中的拓扑交换机即dst_dev也提取出来,后续和单机一样水平扩展即可。

<?xml version="1.0" encoding="UTF-8"?>
<Topology>
<Devices name="dut1" type="dut" model="router">
	<Connections src_dev="dut1" src_port="port1" dst_dev="tsw1" dst_port="gigabitethernet 1/0/0"></Connections>
	<Connections src_dev="dut1" src_port="port2" dst_dev="tsw1" dst_port="gigabitethernet 1/0/1"></Connections>
	<Connections src_dev="dut1" src_port="port3" dst_dev="tsw1" dst_port="gigabitethernet 1/0/2"></Connections>
	<Connections src_dev="dut1" src_port="port4" dst_dev="tsw1" dst_port="gigabitethernet 1/0/3"></Connections>
</Devices>
<Devices name="dut2" type="dut" model="router">
	<Connections src_dev="dut2" src_port="port1" dst_dev="tsw1" dst_port="gigabitethernet 1/0/4"></Connections>
	<Connections src_dev="dut2" src_port="port2" dst_dev="tsw1" dst_port="gigabitethernet 1/0/5"></Connections>
	<Connections src_dev="dut2" src_port="port3" dst_dev="tsw1" dst_port="gigabitethernet 1/0/6"></Connections>
	<Connections src_dev="dut2" src_port="port4" dst_dev="tsw1" dst_port="gigabitethernet 1/0/7"></Connections>
</Devices>
<Devices name="dut3" type="dut" model="router">
	<Connections src_dev="dut3" src_port="port1" dst_dev="tsw1" dst_port="gigabitethernet 1/0/8"></Connections>
	<Connections src_dev="dut3" src_port="port2" dst_dev="tsw1" dst_port="gigabitethernet 1/0/9"></Connections>
	<Connections src_dev="dut3" src_port="port3" dst_dev="tsw1" dst_port="gigabitethernet 1/0/10"></Connections>
	<Connections src_dev="dut3" src_port="port4" dst_dev="tsw1" dst_port="gigabitethernet 1/0/11"></Connections>
</Devices>
</Topology>

triangle.xml

本例中定义了三角形的逻辑拓扑xml文件triangle.xml。

<?xml version="1.0" encoding="UTF-8"?>

<Connections src_dev="dut1" src_port="port1" dst_dev="dut2" dst_port="port1"></Connections>
<Connections src_dev="dut1" src_port="port2" dst_dev="dut3" dst_port="port2"></Connections>
<Connections src_dev="dut2" src_port="port2" dst_dev="dut3" dst_port="port1"></Connections>

topology.py

#python3.8
#coding=utf-8
#author=liuyifan

VLAN_START = 4000
IP_ADDRESS_PATTERN = "51.0.{}.{}/24"

from bs4 import BeautifulSoup

class Topology():
    # 解析物理拓扑文件,将所有connections存储到字典中,(src_dev,src_port)是key,拓扑交换机的接口即dst_port是value
    def parse_pysical_top(self,xml_top_file):
        d = {}
        soup = BeautifulSoup(open(xml_top_file), 'html.parser')
        for c in soup.find_all("connections"):
            d[c.get("src_dev"),c.get("src_port")]=c.get("dst_port")
        return d

    # 解析逻辑拓扑文件,将所有connections存储到列表中,这是一个两层列表,第一层每一个元素代表一个connection,
    # 对于每一个connection列表第一个元素是(src_dev,src_port),第二个元素是(dst_dev,dst_port)
    def parse_logical_top(self,xml_top_file):
        lst, inner_lst = [], []
        soup = BeautifulSoup(open(xml_top_file), 'html.parser')
        for c in soup.find_all("connections"):
            inner_lst.append((c.get("src_dev"),c.get("src_port")))
            inner_lst.append((c.get("dst_dev"),c.get("dst_port")))
            lst.append(inner_lst)
            inner_lst = []
        return lst

    # 输入为parse_logical_top()的返回值,为每一个接口分配一个ip地址
    # 所有connections存储到列表中,这个一个三层列表,第一层每一个元素代表一个connection,
    # 对于一个connection列表第一个元素是[src_dev,src_port,ip_address],第二个元素是[dst_dev,dst_port,ip_address]。
    def generate_ip_address(self,logic):
        lst, inner_lst, inner_inner_lst = [], [], []
        for i in range(len(logic)):
            for j in range(len(logic[i])):
                inner_inner_lst.append(logic[i][j][0])
                inner_inner_lst.append(logic[i][j][1])
                inner_inner_lst.append(IP_ADDRESS_PATTERN.format(i+1,j+1))
                inner_lst.append(inner_inner_lst)
                inner_inner_lst = []
            lst.append(inner_lst)
            inner_lst = []
        return lst


    # 综合物理拓扑和逻辑拓扑的解析结果,得出拓扑交换机物理接口vlan划分关系。
    # 返回一个2维列表,一级列表中每个元素是一个列表。内层列表的内容为两个拓扑交换机的接口和它们所属的vlan。
    def partition_tsw_vlan(self,pysical,logic):
        lst, inner_lst = [], []
        vlan_offset = 0
        for connection in logic:
            for intf in connection:
                # 找到dut该接口所连的拓扑交换机的物理接口
                inner_lst.append(pysical[intf])
            inner_lst.append(VLAN_START + vlan_offset)
            vlan_offset += 1
            lst.append(inner_lst)
            inner_lst = []
        return lst

if __name__ == '__main__':
    top = Topology()
    pysical = top.parse_pysical_top("pysical_top.xml")
    print("物理拓扑解析结果:")
    pprint.pprint(pysical)
    logic = top.parse_logical_top("triangle.xml")
    print("逻辑拓扑解析结果:")
    pprint.pprint(logic)
    vlans = top.partition_tsw_vlan(pysical,logic)
    print("拓扑交换机VLAN划分方案:")
    pprint.pprint(vlans)
    addresses = top.generate_ip_address(logic)
    print("DUT接口IP地址分配方案:")
    pprint.pprint(addresses)
    #最后根据vlans中指定的vlan关系,使用拓扑交换机实际的命令来划分出vlan,就完成了逻辑拓扑的生成。
    #根据配置文件找出实际的DUT登录方式和对应的实际接口,配置相应的IP地址。

运行输出:

物理拓扑解析结果:
{('dut1', 'port1'): 'gigabitethernet 1/0/0',
 ('dut1', 'port2'): 'gigabitethernet 1/0/1',
 ('dut1', 'port3'): 'gigabitethernet 1/0/2',
 ('dut1', 'port4'): 'gigabitethernet 1/0/3',
 ('dut2', 'port1'): 'gigabitethernet 1/0/4',
 ('dut2', 'port2'): 'gigabitethernet 1/0/5',
 ('dut2', 'port3'): 'gigabitethernet 1/0/6',
 ('dut2', 'port4'): 'gigabitethernet 1/0/7',
 ('dut3', 'port1'): 'gigabitethernet 1/0/8',
 ('dut3', 'port2'): 'gigabitethernet 1/0/9',
 ('dut3', 'port3'): 'gigabitethernet 1/0/10',
 ('dut3', 'port4'): 'gigabitethernet 1/0/11'}
逻辑拓扑解析结果:
[[('dut1', 'port1'), ('dut2', 'port1')],
 [('dut1', 'port2'), ('dut3', 'port2')],
 [('dut2', 'port2'), ('dut3', 'port1')]]
拓扑交换机VLAN划分方案:
[['gigabitethernet 1/0/0', 'gigabitethernet 1/0/4', 4000],
 ['gigabitethernet 1/0/1', 'gigabitethernet 1/0/9', 4001],
 ['gigabitethernet 1/0/5', 'gigabitethernet 1/0/8', 4002]]
DUT接口IP地址分配方案:
[[['dut1', 'port1', '51.0.1.1/24'], ['dut2', 'port1', '51.0.1.2/24']],
 [['dut1', 'port2', '51.0.2.1/24'], ['dut3', 'port2', '51.0.2.2/24']],
 [['dut2', 'port2', '51.0.3.1/24'], ['dut3', 'port1', '51.0.3.2/24']]]

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值