mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +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:
parent
7dcfad4085
commit
04f96b6705
@ -29,3 +29,6 @@ class Code:
|
||||
Welcome = 1
|
||||
Status = 13
|
||||
Version = 1000
|
||||
ProtocolInfo = 1002
|
||||
ProtocolDetails = 1006
|
||||
ProtocolListHeader = 2002
|
||||
|
6
python/BIRD/Protocol/Babel.py
Normal file
6
python/BIRD/Protocol/Babel.py
Normal file
@ -0,0 +1,6 @@
|
||||
from BIRD.Protocol import Protocol, ProtocolList
|
||||
|
||||
class BabelProtocol(Protocol):
|
||||
match = "Babel"
|
||||
|
||||
ProtocolList.register(BabelProtocol)
|
4
python/BIRD/Protocol/Device.py
Normal file
4
python/BIRD/Protocol/Device.py
Normal file
@ -0,0 +1,4 @@
|
||||
import asyncio
|
||||
|
||||
from BIRD.Basic import Basic
|
||||
from BIRD.Protocol import Protocol
|
16
python/BIRD/Protocol/Kernel.py
Normal file
16
python/BIRD/Protocol/Kernel.py
Normal 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)
|
6
python/BIRD/Protocol/RAdv.py
Normal file
6
python/BIRD/Protocol/RAdv.py
Normal file
@ -0,0 +1,6 @@
|
||||
from BIRD.Protocol import Protocol, ProtocolList
|
||||
|
||||
class RAdvProtocol(Protocol):
|
||||
match = "RAdv"
|
||||
|
||||
ProtocolList.register(RAdvProtocol)
|
78
python/BIRD/Protocol/__init__.py
Normal file
78
python/BIRD/Protocol/__init__.py
Normal 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
|
@ -5,6 +5,7 @@ from datetime import datetime
|
||||
from BIRD.Basic import BIRDException
|
||||
from BIRD.Socket import Socket
|
||||
from BIRD.Status import Status, Version
|
||||
from BIRD.Protocol import ProtocolList
|
||||
|
||||
from BIRD.Config import Timestamp, ProtocolConfig, DeviceProtocolConfig
|
||||
|
||||
@ -111,8 +112,9 @@ class CLI:
|
||||
class BIRD:
|
||||
def __init__(self, socket=Path("bird.ctl")):
|
||||
self.cli = CLI(socket)
|
||||
self.version = Version(self)
|
||||
self.status = Status(self)
|
||||
self.version = Version(bird=self)
|
||||
self.status = Status(bird=self)
|
||||
self.protocols = ProtocolList(bird=self)
|
||||
|
||||
self.within = False
|
||||
|
||||
|
@ -9,4 +9,7 @@ async def main():
|
||||
await b.status.update()
|
||||
print(b.status)
|
||||
|
||||
await b.protocols.update()
|
||||
print(b.protocols)
|
||||
|
||||
asyncio.run(main())
|
||||
|
Loading…
Reference in New Issue
Block a user