Python库,用于解析网络拓扑数据(例如:动态路由协议、NetJSON、CNML)并检测变更。
项目描述
Netdiff是一个简单的抽象层,用于解析开源动态路由协议或任何其他具有网络拓扑知识网络软件的网络拓扑数据。
它的目标是允许像openwisp-network-topology这样的应用程序收集、可视化和监控网络拓扑数据,而无需处理检索数据每个网络软件的详细信息。
特性:
底层使用流行的networkx库
从PyPI安装稳定版本
从PyPI安装
pip install netdiff
安装开发版本
安装tar包
pip install https://github.com/openwisp/netdiff/tarball/master
或者您也可以通过pip使用git进行安装
pip install -e git+git://github.com/openwisp/netdiff#egg=netdiff
如果您想贡献,请安装您克隆的分支
git clone git@github.com:<your_fork>/netdiff.git
cd netdiff
python setup.py develop
基本用法示例
计算OLSR 0.6.x拓扑的diff
from netdiff import OlsrParser
from netdiff import diff
old = OlsrParser(file="./stored-olsr.json")
new = OlsrParser(url="http://127.0.0.1:9090")
diff(old, new)
或者,您也可以使用减法运算符
from netdiff import OlsrParser
from netdiff import diff
old = OlsrParser(file="./stored-olsr.json")
new = OlsrParser(url="http://127.0.0.1:9090")
old - new
输出将是一个包含三个键的有序字典
添加
删除
更改
每个键将包含一个与NetJSON NetworkGraph格式兼容的dict,分别表示
已添加到拓扑中的节点和链接
从拓扑中删除的节点和链接
在两个拓扑中都存在,但它们的属性已更改的节点和链接
如果没有更改,键将包含None。
因此,如果在旧版和新版之间没有更改,结果将是
{"added": None, "removed": None, "changed": None}
而如果有更改,结果将如下所示
{
"added": {
"type": "NetworkGraph",
"protocol": "OLSR",
"version": "0.6.6",
"revision": "5031a799fcbe17f61d57e387bc3806de",
"metric": "ETX",
"nodes": [
{
"id": "10.150.0.7",
"label": "Node A",
"local_addresses": [],
"properties": {},
},
{
"id": "10.150.0.6",
"label": "Node B",
"local_addresses": ["10.56.2.1"],
"properties": {"hostname": "nodeb.lan"},
},
],
"links": [
{
"source": "10.150.0.3",
"target": "10.150.0.7",
"cost": 1.50390625,
"cost_text": "",
"properties": {},
},
{
"source": "10.150.0.3",
"target": "10.150.0.6",
"cost": 1.0,
"cost_text": "",
"properties": {},
},
],
},
"removed": {
"type": "NetworkGraph",
"protocol": "OLSR",
"version": "0.6.6",
"revision": "5031a799fcbe17f61d57e387bc3806de",
"metric": "ETX",
"nodes": [
{
"id": "10.150.0.8",
"label": "Node C",
"local_addresses": [],
"properties": {},
}
],
"links": [
{
"source": "10.150.0.7",
"target": "10.150.0.8",
"cost": 1.0,
"cost_text": "",
"properties": {},
}
],
},
"changed": {
"type": "NetworkGraph",
"protocol": "OLSR",
"version": "0.6.6",
"revision": "5031a799fcbe17f61d57e387bc3806de",
"metric": "ETX",
"nodes": [],
"links": [
{
"source": "10.150.0.3",
"target": "10.150.0.2",
"cost": 1.0,
"cost_text": "",
"properties": {},
}
],
},
}
解析器
解析器是扩展netdiff.base.BaseParser的类,并实现了一个parse方法,该方法负责将Python数据结构转换为networkx.Graph对象并返回结果。
解析器还有一个json方法,该方法返回有效的NetJSON输出。
可用的解析器有
netdiff.OlsrParser:用于解析olsrd jsoninfo插件或较老的txtinfo插件
netdiff.BatmanParser:用于解析batman-advanced alfred工具(也支持从olsrd继承的旧版txtinfo格式)
netdiff.Bmx6Parser:用于解析BMX6 b6m工具
netdiff.CnmlParser:用于解析CNML 0.1
netdiff.NetJsonParser:用于解析NetJSON NetworkGraph格式
netdiff.OpenvpnParser:用于解析OpenVPN状态文件
netdiff.WireguardParser:用于解析Wireguard VPN(要使用的命令是wg show all dump)
netdiff.ZeroTierParser:用于解析ZeroTier VPN(要使用的命令是zerotier-cli peers -j 或通过ZeroTier服务API访问对等体信息)
初始化参数
数据可以通过以下3种方式提供,按优先级顺序
data:表示拓扑/图的字典或字符串
url:从URL获取数据的URL
file:检索数据的文件路径
其他可用参数
timeout:表示HTTP或telnet请求超时的秒数的整数,默认为None
verify:布尔值,表示请求库是否进行SSL证书验证[链接]
directed:布尔值,启用使用有向图(networkx.DiGraph),默认为False
初始化示例
本地文件示例
from netdiff import BatmanParser
BatmanParser(file="./my-stored-topology.json")
HTTP示例
from netdiff import NetJsonParser
url = "https://raw.githubusercontent.com/interop-dev/netjson/master/examples/network-graph.json"
NetJsonParser(url=url)
带有timeout的Telnet示例
from netdiff import OlsrParser
OlsrParser(url="telnet://127.0.1", timeout=5)
带有自签名SSL证书的HTTPS示例,使用verify=False
from netdiff import NetJsonParser
OlsrParser(
url="https://myserver.mydomain.com/topology.json", verify=False
)
NetJSON输出
Netdiff解析器可以返回有效的NetJSON NetworkGraph对象
from netdiff import OlsrParser
olsr = OlsrParser(url="telnet://127.0.0.1:9090")
# will return a dict
olsr.json(dict=True)
# will return a JSON formatted string
print(olsr.json(indent=4))
输出
{
"type": "NetworkGraph",
"protocol": "OLSR",
"version": "0.6.6",
"revision": "5031a799fcbe17f61d57e387bc3806de",
"metric": "ETX",
"nodes": [
{
"id": "10.150.0.3"
},
{
"id": "10.150.0.2"
},
{
"id": "10.150.0.4"
}
],
"links": [
{
"source": "10.150.0.3",
"target": "10.150.0.2",
"cost": 2.4
},
{
"source": "10.150.0.3",
"target": "10.150.0.4",
"cost": 1.0
}
]
}
异常
所有异常都是netdiff.exceptions.NetdiffException的子类。
ConversionException
netdiff.exceptions.ConversionException
当netdiff无法识别传递给解析器的格式时抛出。
不一定是错误,应该捕获并管理以支持更多格式。
可以从“data”属性访问从网络/存储检索的数据,例如
def to_python(self, data):
try:
return super().to_python(data)
except ConversionException as e:
return self._txtinfo_to_jsoninfo(e.data)
ParserError
netdiff.exceptions.ParserError
当格式被识别但数据无效时抛出。
NetJsonError
netdiff.exceptions.NetJsonError
当netdiff.parsers.BaseParser的json方法没有足够的数据符合NetJSON NetworkGraph规范时抛出。
TopologyRetrievalError
netdiff.exceptions.TopologyRetrievalError
当无法检索拓扑数据时抛出(例如:URL可能暂时不可达)。
特殊功能
OpenVPN
默认情况下,OpenVPN解析器使用通用名称来识别客户端,这是因为它如果使用公共IP地址,相同的客户端如果在不同的IP地址下连接,将不会被识别(由于许多ISP使用动态公共IP地址,这种情况非常可能)。
当VPN服务器配置允许不同客户端使用相同的通用名称时(通常不推荐这样做),这不起作用。
如果您需要支持配置了OpenVPN duplicate-cn功能的旧系统,您可以在初始化OpenvpnParser时传递duplicate_cn=True。这将更改解析器的行为,使每个客户端都通过它们的通用名称和IP地址(如果有多个具有相同通用名称和IP的客户端,则还包括使用的端口号)来识别。
已知问题
ConnectionError: BadStatusLine
如果您在向olsrd的jsoninfo插件(版本0.6到0.9)发出请求时遇到类似的错误,那么很可能是HTTP头被禁用了。
要修复它,请打开olsrd配置文件中的HTTP头,例如
LoadPlugin "olsrd_jsoninfo.so.0.0" { PlParam "httpheaders" "yes" # add this line PlParam "Port" "9090" PlParam "accept" "0.0.0.0" }
运行测试
安装您的分叉仓库
git clone git://github.com/<your_fork>/netdiff
cd netdiff/
python setup.py develop
安装测试需求
pip install -r requirements-test.txt
使用以下命令运行测试
./runtests.py
./run-qa-checks
或者,您可以使用nose2命令(它有大量可用选项)
nose2
nose2 tests.test_olsr # run only olsr related tests
nose2 tests/test_olsr.py # variant form of the previous command
nose2 tests.test_olsr:TestOlsrParser # variant form of the previous command
nose2 tests.test_olsr:TestOlsrParser.test_parse # run specific test
使用以下命令查看测试覆盖率
coverage run --source=netdiff runtests.py && coverage report
贡献
请参阅OpenWISP贡献指南。
支持
参阅OpenWISP支持渠道。
变更日志
参阅CHANGES。
许可证
参阅LICENSE。
项目详情
下载文件
下载适用于您平台上的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。