1
0
Fork 1
mirror of https://github.com/thatmattlove/hyperglass.git synced 2026-04-17 21:38:27 +00:00

Merge pull request #2 from WilhelmZA/structured

Structured
This commit is contained in:
Carlos Santos 2025-09-26 12:10:37 -03:00 committed by GitHub
commit d1e42f554e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 80 additions and 86 deletions

2
.gitignore vendored
View file

@ -2,6 +2,8 @@
hyperglass/hyperglass/static hyperglass/hyperglass/static
TODO* TODO*
.env .env
dev-build.sh
dev-docker/
test.py test.py
.DS_Store .DS_Store

View file

@ -4,11 +4,12 @@
from typing import Union from typing import Union
# Local # Local
from .bgp_route import BGPRouteTable from .bgp_route import BGPRoute, BGPRouteTable
OutputDataModel = Union[BGPRouteTable] OutputDataModel = Union[BGPRouteTable]
__all__ = ( __all__ = (
"BGPRoute",
"BGPRouteTable", "BGPRouteTable",
"OutputDataModel", "OutputDataModel",
) )

View file

@ -9,7 +9,7 @@ from pydantic import ConfigDict
# Project # Project
from hyperglass.log import log from hyperglass.log import log
from hyperglass.models.data import BGPRouteTable from hyperglass.models.data import BGPRoute, BGPRouteTable
# Local # Local
from ..main import HyperglassModel from ..main import HyperglassModel
@ -138,23 +138,22 @@ class AristaBGPTable(_AristaBase):
if len(as_path) != 0: if len(as_path) != 0:
source_as = as_path[0] source_as = as_path[0]
routes.append( route_data = {
{ "prefix": prefix,
"prefix": prefix, "active": route.route_type.active,
"active": route.route_type.active, "age": self._get_route_age(route.timestamp),
"age": self._get_route_age(route.timestamp), "weight": route.weight,
"weight": route.weight, "med": route.med,
"med": route.med, "local_preference": route.local_preference,
"local_preference": route.local_preference, "as_path": as_path,
"as_path": as_path, "communities": communities,
"communities": communities, "next_hop": route.next_hop,
"next_hop": route.next_hop, "source_as": source_as,
"source_as": source_as, "source_rid": route.peer_entry.peer_router_id,
"source_rid": route.peer_entry.peer_router_id, "peer_rid": route.peer_entry.peer_router_id,
"peer_rid": route.peer_entry.peer_router_id, "rpki_state": rpki_state,
"rpki_state": rpki_state, }
} routes.append(BGPRoute(**route_data))
)
serialized = BGPRouteTable( serialized = BGPRouteTable(
vrf=self.vrf, vrf=self.vrf,

View file

@ -9,7 +9,7 @@ from pydantic import ConfigDict, model_validator
# Project # Project
from hyperglass.log import log from hyperglass.log import log
from hyperglass.models.data import BGPRouteTable from hyperglass.models.data import BGPRoute, BGPRouteTable
# Local # Local
from ..main import HyperglassModel from ..main import HyperglassModel
@ -91,25 +91,24 @@ class FRRBGPTable(_FRRBase):
now = datetime.utcnow().timestamp() now = datetime.utcnow().timestamp()
then = datetime.utcfromtimestamp(route.last_update).timestamp() then = datetime.utcfromtimestamp(route.last_update).timestamp()
age = int(now - then) age = int(now - then)
routes.append( route_data = {
{ "prefix": self.prefix,
"prefix": self.prefix, "active": route.bestpath,
"active": route.bestpath, "age": age,
"age": age, "weight": route.weight,
"weight": route.weight, "med": route.med,
"med": route.med, "local_preference": route.loc_prf,
"local_preference": route.loc_prf, "as_path": route.aspath,
"as_path": route.aspath, "communities": route.community,
"communities": route.community, "next_hop": route.nexthops[0].ip,
"next_hop": route.nexthops[0].ip, "source_as": route.aggregator_as,
"source_as": route.aggregator_as, "source_rid": route.aggregator_id,
"source_rid": route.aggregator_id, "peer_rid": route.peer.peer_id,
"peer_rid": route.peer.peer_id, # TODO: somehow, get the actual RPKI state
# TODO: somehow, get the actual RPKI state # This depends on whether or not the RPKI module is enabled in FRR
# This depends on whether or not the RPKI module is enabled in FRR "rpki_state": 3,
"rpki_state": 3, }
} routes.append(BGPRoute(**route_data))
)
serialized = BGPRouteTable( serialized = BGPRouteTable(
vrf=vrf, vrf=vrf,

View file

@ -9,7 +9,7 @@ from pydantic import ConfigDict, field_validator, model_validator
# Project # Project
from hyperglass.log import log from hyperglass.log import log
from hyperglass.models.data.bgp_route import BGPRouteTable from hyperglass.models.data.bgp_route import BGPRoute, BGPRouteTable
# Local # Local
from ..main import HyperglassModel from ..main import HyperglassModel
@ -318,15 +318,9 @@ def _extract_route_entries(lines: t.List[str]) -> t.List[HuaweiRouteEntry]:
class HuaweiBGPRouteTable(BGPRouteTable): class HuaweiBGPRouteTable(BGPRouteTable):
"""Custom BGP Route Table for Huawei that bypasses validation.""" """Canonical Huawei BGP Route Table."""
def __init__(self, **kwargs): # No custom __init__ needed; inherit from BGPRouteTable (which should be a Pydantic model)
"""Initialize without calling parent validation."""
# Set attributes directly without validation using object.__setattr__
object.__setattr__(self, "vrf", kwargs.get("vrf", "default"))
object.__setattr__(self, "count", kwargs.get("count", 0))
object.__setattr__(self, "routes", kwargs.get("routes", []))
object.__setattr__(self, "winning_weight", kwargs.get("winning_weight", "low"))
class HuaweiBGPTable(HuaweiBase): class HuaweiBGPTable(HuaweiBase):
@ -388,7 +382,7 @@ class HuaweiBGPTable(HuaweiBase):
RPKI_STATE_MAP.get("unknown") if route.is_valid else RPKI_STATE_MAP.get("valid") RPKI_STATE_MAP.get("unknown") if route.is_valid else RPKI_STATE_MAP.get("valid")
), ),
} }
routes.append(route_data) routes.append(BGPRoute(**route_data))
return HuaweiBGPRouteTable( return HuaweiBGPRouteTable(
vrf="default", vrf="default",

View file

@ -9,7 +9,7 @@ from pydantic import ConfigDict, field_validator, model_validator
# Project # Project
from hyperglass.log import log from hyperglass.log import log
from hyperglass.util import deep_convert_keys from hyperglass.util import deep_convert_keys
from hyperglass.models.data.bgp_route import BGPRouteTable from hyperglass.models.data.bgp_route import BGPRoute, BGPRouteTable
# Local # Local
from ..main import HyperglassModel from ..main import HyperglassModel
@ -176,23 +176,22 @@ class JuniperBGPTable(JuniperBase):
count += table.rt_entry_count count += table.rt_entry_count
prefix = "/".join(str(i) for i in (table.rt_destination, table.rt_prefix_length)) prefix = "/".join(str(i) for i in (table.rt_destination, table.rt_prefix_length))
for route in table.rt_entry: for route in table.rt_entry:
routes.append( route_data = {
{ "prefix": prefix,
"prefix": prefix, "active": route.active_tag,
"active": route.active_tag, "age": route.age,
"age": route.age, "weight": route.preference,
"weight": route.preference, "med": route.metric,
"med": route.metric, "local_preference": route.local_preference,
"local_preference": route.local_preference, "as_path": route.as_path,
"as_path": route.as_path, "communities": route.communities,
"communities": route.communities, "next_hop": route.next_hop,
"next_hop": route.next_hop, "source_as": route.source_as,
"source_as": route.source_as, "source_rid": route.source_rid,
"source_rid": route.source_rid, "peer_rid": route.peer_rid,
"peer_rid": route.peer_rid, "rpki_state": route.validation_state,
"rpki_state": route.validation_state, }
} routes.append(BGPRoute(**route_data))
)
serialized = BGPRouteTable(vrf=vrf, count=count, routes=routes, winning_weight="low") serialized = BGPRouteTable(vrf=vrf, count=count, routes=routes, winning_weight="low")
log.bind(platform="juniper", response=repr(serialized)).debug("Serialized response") log.bind(platform="juniper", response=repr(serialized)).debug("Serialized response")

View file

@ -282,28 +282,28 @@ class MikrotikBGPTable(MikrotikBase):
return inst return inst
def bgp_table(self) -> BGPRouteTable: def bgp_table(self) -> BGPRouteTable:
out = [] routes = []
for r in self.routes: for route in self.routes:
route_dict = { route_data = {
"prefix": r.prefix, "prefix": route.prefix,
"active": r.active, "active": route.active,
"age": r.age, "age": route.age,
"weight": r.weight, "weight": route.weight,
"med": r.med, "med": route.med,
"local_preference": r.local_preference, "local_preference": route.local_preference,
"as_path": r.as_path, "as_path": route.as_path,
"communities": r.all_communities, "communities": route.all_communities,
"next_hop": r.next_hop, "next_hop": route.next_hop,
"source_as": r.source_as, "source_as": route.source_as,
"source_rid": r.source_rid, "source_rid": route.source_rid,
"peer_rid": r.peer_rid, "peer_rid": route.peer_rid,
"rpki_state": r.rpki_state, "rpki_state": route.rpki_state,
} }
# Instantiate BGPRoute to trigger validation (including external RPKI) # Instantiate BGPRoute to trigger validation (including external RPKI)
out.append(BGPRoute(**route_dict)) routes.append(BGPRoute(**route_data))
return MikrotikBGPRouteTable( return MikrotikBGPRouteTable(
vrf="default", vrf="default",
count=len(out), count=len(routes),
routes=out, routes=routes,
winning_weight="low", winning_weight="low",
) )