我尝试从网络设备(交换机、路由器、防火墙)获取配置并将其保存到数据库中。为此,我将 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 之间双向转换。或者这是完全错误的方法?
如果有人能指出我正确的方向,我会很高兴。
谢谢雷莫