Enhance Keenetic model and update templates for improved data handling

- Implemented the `interfaces` and `vlans` methods in the `Keenetic` model to process and decode interface and VLAN data.
- Added a `_decode_utf` method to handle UTF-8 encoded descriptions.
- Updated the Keenetic TTP template to define structured groups for system, interfaces, and VLANs.
- Refactored file paths in the `Mikrotik` model for consistency and clarity.
This commit is contained in:
IluaAir
2026-02-22 00:21:55 +03:00
parent a41cb1f7ec
commit 2394296f5b
5 changed files with 85 additions and 11 deletions

View File

@@ -1,20 +1,54 @@
from ipaddress import ip_interface
from pprint import pprint
from oxi.interfaces import register_parser
from oxi.interfaces.base import BaseDevice
from oxi.interfaces.contract import Interfaces, System, Vlans
@register_parser(["NDMS", "keenetic", "KeeneticOS"])
class Keenetic(BaseDevice):
template = "keenetic.ttp"
def system(self): ...
def system(self):
return System(**self._raw["system"])
def interfaces(self): ...
def _decode_utf(self, text: str):
if "\\x" in text:
desc = text.strip('"')
decoded = (
desc.encode("utf-8")
.decode("unicode_escape")
.encode("latin1")
.decode("utf-8")
)
return decoded
return text
def vlans(self): ...
def interfaces(self):
interfaces: list[dict] = self._raw["interfaces"]
for item in interfaces:
if item.get("ip_address") and item.get("netmask"):
ipaddress = ip_interface(
f"{item.get('ip_address')}/{item.get('netmask')}"
)
item["mask"] = ipaddress.network.prefixlen
item.pop("netmask", "Key not found")
if item.get("description"):
decoded = self._decode_utf(item.get("description", ""))
item["description"] = decoded
return [Interfaces(**item) for item in interfaces]
def vlans(self):
vlans = self._raw["vlans"]
for item in vlans:
if item.get("description"):
decoded = self._decode_utf(item.get("description", ""))
item["description"] = decoded
return [Vlans(**item) for item in vlans]
if __name__ == "__main__":
with open("../../test2.txt") as file:
with open("./test2.txt") as file:
data = file.read()
mikr = Keenetic(data)
print(mikr.parse().json())
print(mikr.parse().model_dump_json())

View File

@@ -1,3 +1,4 @@
import os
from oxi.interfaces import register_parser
from oxi.interfaces.base import BaseDevice
from oxi.interfaces.contract import Interfaces, System, Vlans
@@ -19,7 +20,8 @@ class Mikrotik(BaseDevice):
if __name__ == "__main__":
with open("../../test.txt") as file:
print(os.path.abspath(os.curdir))
with open("./test.txt") as file:
data = file.read()
mikr = Mikrotik(data)
print(mikr.parse().json())

View File

@@ -1,7 +1,16 @@
<doc>
</doc>
<var>
</var>
<vars>
</vars>
<group>
</group>
<group name="system">
...
</group>
<group name="interfaces">
...
</group>
<group name="vlans">
...
</group>

View File

@@ -0,0 +1,29 @@
<doc>
</doc>
<vars>
default_system = {
"model": "",
"serial_number": ""
}
default_interfaces = {}
</vars>
<group name="system" default="default_system">
! release: {{ version }}
! model: {{ model | ORPHRASE }}
! hw_version: {{ serial_number }}
</group>
<group name="interfaces">
interface {{ name | _start_ | exclude("Vlan") }}
rename {{ rename }}
description {{ description | ORPHRASE }}
ip address {{ ip_address }} {{ netmask }}
{{ shutdown | re("up") | replace("up","False") | strip('"') }}
{{ shutdown | re("down") | replace("down","True") | strip('"') }}
</group>
<group name="vlans">
interface {{ ignore }}/Vlan{{ vlan_id }}
description {{ description | ORPHRASE | strip('"') }}
</group>