0

我尝试从网络设备(交换机、路由器、防火墙)获取配置并将其保存到数据库中。为此,我将 Netconf 与 ncclient 库一起使用。配置以 XML 格式接收。这是一个配置示例。

<native xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XE-native\">
    <hostname>R1</hostname>
    <username>
        <name>testuser</name>
        <password>
            <encryption>15</encryption>
            <password>123</password>
        </password>
    </username>
    <username>
        <name>user</name>
        <privilege>15</privilege>
        <secret>
            <encryption>15</encryption>
            <secret>123</secret>
        </secret>
    </username>
    <interface>
        <GigabitEthernet>
            <name>1</name>
            <description>MANAGEMENT INTERFACE</description>
            <ip>
                <address>
                    <primary>
                        <address>10.10.20.48</address>
                        <mask>255.255.255.0</mask>
                    </primary>
                </address>
            </ip>
        </GigabitEthernet>
        <GigabitEthernet>
            <name>2</name>
            <description>Test</description>
            <ip>
                <address>
                    <primary>
                        <address>10.10.30.2</address>
                        <mask>255.255.255.0</mask>
                    </primary>
                </address>
            </ip>
        </GigabitEthernet>
    </interface>
    <ntp>
        <server
            xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XE-ntp\">
            <server-list>
                <ip-address>2.3.4.5</ip-address>
            </server-list>
            <server-list>
                <ip-address>6.6.6.6</ip-address>
            </server-list>
        </server>
    </ntp>
</native>

我使用具有以下模型的 django REST 框架:

class Interface(models.Model):
    SPEED = (('10Base', '10'), ('100Base', '100'), ('1GBase', '1000'), 
            ('2.5GBase', '2500'), ('5GBase', '5000'), ('10GBase', '10000'), 
            ('40GBase', '40000'), ('100GBase', '100000'))

    name = models.CharField(max_length=50, blank=False, null=False)
    description = models.CharField(max_length=200, blank=True, null=True)
    speed = models.CharField(max_length=50, choices=SPEED, blank=False, null=False)
    if_type = models.CharField(max_length=50, blank=True, null=True)
    enabled = models.BooleanField(blank=True, null=True)

class Device(models.Model):
    hostname = models.CharField(max_length=50, blank=True, null=True)
    boot_variable = models.CharField(max_length=50, blank=True, null=True)
    interfaces = models.ManyToManyField(to=Interface, blank=True, related_name='interfaces')

要将配置保存到数据库中,我使用 ElementTree:

from xml.etree import ElementTree as ET

def parse_xml_to_dict(self, xml_data: str) -> dict:
    dom = ET.fromstring(xml_data)
    device_data = {}
    device_data['hostname'] = dom.findall('.//native/hostname')

    return device_data

要更新数据库中的设备,我会:

Device.objects.filter(pk=pk).update(**device_data)

这可行,但这种方法的问题是我必须手动进行所有解析。通常,XML 数据的长度超过 1500 行,并且所有供应商都使用自己的格式。解析所有设备将是一项巨大的工作。

我正在寻找一个更简单的解决方案。我想到了一个这样的翻译表:

translation_table = {'Cisco-IOS-XE-native':
                         {'hostname': 'native/hostname'}}

“Cisco-IOS-XE-native”是设备支持的 yang 模型的名称。所以我可以从设备中获取所有功能并检查它是否有一个用于 yang 模型的转换表。如果是,我将使用内部字典(本机/主机名)中的值进行 xpath 搜索。在这里,我有一个可行的解决方案,但问题是,我该如何做相反的方向。当我更改数据库中的某些内容以更新设备时。我可能需要另一个翻译表,这也是一项巨大的努力。

另一个想法是将 XML 放入转换表中,如下所示:

translation_table = {'Cisco-IOS-XE-native':
                         {'hostname': '<native><hostname></hostname></native>'}}

但在这里我被困住了。是否可以 <native><hostname></hostname></native>在 XML 数据中搜索并获取它的值?使用这种方法,我可以在数据库和 XML 之间双向转换。或者这是完全错误的方法?

如果有人能指出我正确的方向,我会很高兴。

谢谢雷莫

4

0 回答 0