0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Python CLI Package: Protocol scaffolding for Kernel, Device, Direct, Babel and RAdv

This choice comes from my own local setup where I use exactly these protocols.
Other protocols will be added later.
This commit is contained in:
Maria Matejka 2023-05-20 11:51:40 +02:00
parent 7dcfad4085
commit 04f96b6705
8 changed files with 120 additions and 2 deletions

View File

@ -29,3 +29,6 @@ class Code:
Welcome = 1 Welcome = 1
Status = 13 Status = 13
Version = 1000 Version = 1000
ProtocolInfo = 1002
ProtocolDetails = 1006
ProtocolListHeader = 2002

View File

@ -0,0 +1,6 @@
from BIRD.Protocol import Protocol, ProtocolList
class BabelProtocol(Protocol):
match = "Babel"
ProtocolList.register(BabelProtocol)

View File

@ -0,0 +1,4 @@
import asyncio
from BIRD.Basic import Basic
from BIRD.Protocol import Protocol

View File

@ -0,0 +1,16 @@
from BIRD.Protocol import Protocol, ProtocolList
class DeviceProtocol(Protocol):
match = "Device"
ProtocolList.register(DeviceProtocol)
class DirectProtocol(Protocol):
match = "Direct"
ProtocolList.register(DirectProtocol)
class KernelProtocol(Protocol):
match = "Kernel"
ProtocolList.register(KernelProtocol)

View File

@ -0,0 +1,6 @@
from BIRD.Protocol import Protocol, ProtocolList
class RAdvProtocol(Protocol):
match = "RAdv"
ProtocolList.register(RAdvProtocol)

View File

@ -0,0 +1,78 @@
import asyncio
from BIRD.Basic import Basic, BIRDException, Code
class ProtocolException(Exception):
def __init__(self, msg):
Exception.__init__(self, f"Failed to parse protocol {self.protocol_name}: {msg}")
class ProtocolListException(Exception):
def __init__(self, msg):
Exception.__init__(self, f"Failed to parse protocol list: {msg}")
class ProtocolList(Basic):
match = {}
# def __init__(self, **kwargs):
# super().__init__(**kwargs)
def register(sub):
if sub.match in ProtocolList.match:
raise BIRDException(f"Protocol match {sub.match} already registered for {ProtocolList.match[sub.match]}")
ProtocolList.match[sub.match] = sub
async def update(self):
self.data = {}
await self.bird.cli.open()
data = await self.bird.cli.socket.command("show protocols all")
# Get header
if data[0]["code"] != Code.ProtocolListHeader:
raise ProtocolListException(f"First line is not protocol list header, got {data[0]}")
if data[0]["data"].split() != ['Name', 'Proto', 'Table', 'State', 'Since', 'Info']:
raise ProtocolListException(f"Strange protocol list header: {data[0]['data']}")
data.pop(0)
for line in data:
if line["code"] == Code.ProtocolInfo:
kwargs = Protocol.parse_info(line["data"])
if (name := kwargs["name"]) in self.data:
raise ProtocolListException(f"Duplicate protocol {name}")
if (m := kwargs["match"]) in self.match:
del kwargs["match"]
kwargs["bird"] = self.bird
self.data[name] = self.match[m](**kwargs)
else:
raise ProtocolListException(f"Unknown protocol kind {m}")
class Protocol(Basic):
def __init__(self, name, state, last_change, info, **kwargs):
super().__init__(**kwargs)
self.name = name
self.state = state
self.last_change = last_change
self.info = info
def parse_info(data):
s = data.split(maxsplit=5) + [None]
assert(len(s) <= 7)
if len(s) < 6:
raise ProtocolListException(f"Strange protocol info: {data}")
s.append(None)
s.pop(2) # drop the default table name, it's a BIRD 1 anachronism
return dict(zip(
["name", "match", "state", "last_change", "info"],
s
))
import BIRD.Protocol.Kernel
import BIRD.Protocol.Babel
import BIRD.Protocol.RAdv

View File

@ -5,6 +5,7 @@ from datetime import datetime
from BIRD.Basic import BIRDException from BIRD.Basic import BIRDException
from BIRD.Socket import Socket from BIRD.Socket import Socket
from BIRD.Status import Status, Version from BIRD.Status import Status, Version
from BIRD.Protocol import ProtocolList
from BIRD.Config import Timestamp, ProtocolConfig, DeviceProtocolConfig from BIRD.Config import Timestamp, ProtocolConfig, DeviceProtocolConfig
@ -111,8 +112,9 @@ class CLI:
class BIRD: class BIRD:
def __init__(self, socket=Path("bird.ctl")): def __init__(self, socket=Path("bird.ctl")):
self.cli = CLI(socket) self.cli = CLI(socket)
self.version = Version(self) self.version = Version(bird=self)
self.status = Status(self) self.status = Status(bird=self)
self.protocols = ProtocolList(bird=self)
self.within = False self.within = False

View File

@ -9,4 +9,7 @@ async def main():
await b.status.update() await b.status.update()
print(b.status) print(b.status)
await b.protocols.update()
print(b.protocols)
asyncio.run(main()) asyncio.run(main())