1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00
2020-12-13 01:48:35 -07:00

119 lines
3.1 KiB
Python

"""Data Models for Parsing FRRouting JSON Response."""
# Standard Library
from typing import List
from datetime import datetime
# Third Party
from pydantic import StrictInt, StrictStr, StrictBool, constr, root_validator
# Project
from hyperglass.log import log
# Local
from ..main import HyperglassModel
from .serialized import ParsedRoutes
FRRPeerType = constr(regex=r"(internal|external)")
def _alias_generator(field):
components = field.split("_")
return components[0] + "".join(x.title() for x in components[1:])
class _FRRBase(HyperglassModel):
class Config:
alias_generator = _alias_generator
extra = "ignore"
class FRRNextHop(_FRRBase):
"""FRR Next Hop Model."""
ip: StrictStr
afi: StrictStr
metric: StrictInt
accessible: StrictBool
used: StrictBool
class FRRPeer(_FRRBase):
"""FRR Peer Model."""
peer_id: StrictStr
router_id: StrictStr
type: FRRPeerType
class FRRPath(_FRRBase):
"""FRR Path Model."""
aspath: List[StrictInt]
aggregator_as: StrictInt
aggregator_id: StrictStr
med: StrictInt = 0
localpref: StrictInt
weight: StrictInt
valid: StrictBool
last_update: StrictInt
bestpath: StrictBool
community: List[StrictStr]
nexthops: List[FRRNextHop]
peer: FRRPeer
@root_validator(pre=True)
def validate_path(cls, values):
"""Extract meaningful data from FRR response."""
new = values.copy()
new["aspath"] = values["aspath"]["segments"][0]["list"]
new["community"] = values["community"]["list"]
new["lastUpdate"] = values["lastUpdate"]["epoch"]
bestpath = values.get("bestpath", {})
new["bestpath"] = bestpath.get("overall", False)
return new
class FRRRoute(_FRRBase):
"""FRR Route Model."""
prefix: StrictStr
paths: List[FRRPath] = []
def serialize(self):
"""Convert the FRR-specific fields to standard parsed data model."""
# TODO: somehow, get the actual VRF
vrf = "default"
routes = []
for route in self.paths:
now = datetime.utcnow().timestamp()
then = datetime.utcfromtimestamp(route.last_update).timestamp()
age = int(now - then)
routes.append(
{
"prefix": self.prefix,
"active": route.bestpath,
"age": age,
"weight": route.weight,
"med": route.med,
"local_preference": route.localpref,
"as_path": route.aspath,
"communities": route.community,
"next_hop": route.nexthops[0].ip,
"source_as": route.aggregator_as,
"source_rid": route.aggregator_id,
"peer_rid": route.peer.peer_id,
# TODO: somehow, get the actual RPKI state
"rpki_state": 3,
}
)
serialized = ParsedRoutes(
vrf=vrf, count=len(routes), routes=routes, winning_weight="high",
)
log.info("Serialized FRR response: {}", serialized)
return serialized