mirror of
				https://github.com/checktheroads/hyperglass
				synced 2024-05-11 05:55:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			119 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			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
 |