added automatic chrony management
This commit is contained in:
parent
9480339b89
commit
90745b069c
4 changed files with 45 additions and 36 deletions
|
@ -25,3 +25,7 @@ class PeerEvent(base.BaseEvent):
|
|||
# make sure we trust the peers trusted by this peer
|
||||
for public_key_hash in peer.allowed_public_key_hashes:
|
||||
self.manager.communication.trust_peer_hash(public_key_hash)
|
||||
|
||||
# add the peer as a time source and allow it to use us as a time source
|
||||
self.manager.clock.add_source(address[0])
|
||||
self.manager.clock.allow_client(address[0])
|
|
@ -1,57 +1,59 @@
|
|||
import subprocess
|
||||
import typing
|
||||
|
||||
from source import managers
|
||||
|
||||
|
||||
class BatmanController:
|
||||
# TODO: need to be able to get ping in the network if possible, otherwise no other uses
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
class ChronyController:
|
||||
class ChronyManager:
|
||||
"""
|
||||
Wrapper to control chrony to manipulate time synchronisation
|
||||
Manager for chrony to manipulate time synchronisation
|
||||
NOTE: the ideal method would be to use `chronyd.sock` to communicate, but it seems to only work with raw binary data
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, manager: "managers.Manager"):
|
||||
self.manager = manager
|
||||
|
||||
self.clear_sources()
|
||||
self.deny_client("all")
|
||||
|
||||
@staticmethod
|
||||
def run_command(*args: str) -> str:
|
||||
# run the command through the chrony command line tool
|
||||
# NOTE(Faraphel): do not check the errors because some codes like 511 can happen
|
||||
# if we add a source that already exist
|
||||
process = subprocess.run(
|
||||
["chronyc", *args],
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
# raise an error if the command did not ended up successfully
|
||||
process.check_returncode()
|
||||
|
||||
# return the stdout of the command
|
||||
return process.stdout.decode()
|
||||
|
||||
def get_sources(self) -> list[...]:
|
||||
def get_sources(self) -> typing.Iterator[str]:
|
||||
"""
|
||||
Get the list of NTP sources
|
||||
:return: the list of NTP sources
|
||||
"""
|
||||
|
||||
...
|
||||
table: str = self.run_command("sources")
|
||||
sources_info = table.strip().split("\n")[2:]
|
||||
print(sources_info)
|
||||
for source_info in sources_info:
|
||||
yield source_info.split(" ")[1]
|
||||
|
||||
def add_source(self, kind: str, source: ...) -> None:
|
||||
def add_source(self, address: str) -> None:
|
||||
"""
|
||||
Add a source to chrony
|
||||
"""
|
||||
|
||||
self.run_command("add", "server", host, "iburst")
|
||||
self.run_command("add", "server", address, "iburst")
|
||||
|
||||
def remove_source(self, source: ...) -> None:
|
||||
def remove_source(self, address: str) -> None:
|
||||
"""
|
||||
Remove a source from chrony
|
||||
"""
|
||||
|
||||
...
|
||||
self.run_command("delete", address)
|
||||
|
||||
def clear_sources(self) -> None:
|
||||
"""
|
||||
|
@ -61,34 +63,39 @@ class ChronyController:
|
|||
for source in self.get_sources():
|
||||
self.remove_source(source)
|
||||
|
||||
def get_clients(self) -> list[...]:
|
||||
def get_clients(self) -> typing.Iterator[str]:
|
||||
"""
|
||||
Get the list of clients using us as a server
|
||||
:return: the list of clients
|
||||
"""
|
||||
|
||||
...
|
||||
table: str = self.run_command("clients")
|
||||
clients_info = table.strip().split("\n")[2:]
|
||||
for client_info in clients_info:
|
||||
yield client_info.split(" ")[0]
|
||||
|
||||
def allow_client(self, client: ...) -> None:
|
||||
def allow_client(self, address: str) -> None:
|
||||
"""
|
||||
Allow a client to use us as a server
|
||||
:param client: the client information
|
||||
:param address: the client address
|
||||
"""
|
||||
|
||||
...
|
||||
self.run_command("allow", address)
|
||||
|
||||
def allow_all_clients(self) -> None:
|
||||
"""
|
||||
Allow all clients to use us as a time-server
|
||||
"""
|
||||
|
||||
def deny_client(self, client: ...) -> None:
|
||||
self.allow_client("all")
|
||||
|
||||
def deny_client(self, address: str) -> None:
|
||||
"""
|
||||
Deny a client to use us as a server
|
||||
:param client: the client information
|
||||
:param address: the client address
|
||||
"""
|
||||
|
||||
...
|
||||
self.run_command("deny", address)
|
||||
|
||||
def deny_all_clients(self) -> None:
|
||||
"""
|
||||
|
@ -96,11 +103,3 @@ class ChronyController:
|
|||
"""
|
||||
|
||||
self.deny_client("all")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
chrony = ChronyController()
|
||||
|
||||
while True:
|
||||
command = input("chronyc >>> ")
|
||||
print(chrony.run_command(command))
|
|
@ -3,7 +3,6 @@ from pathlib import Path
|
|||
|
||||
from source import packets
|
||||
from source.behaviors import events
|
||||
from source.managers.ApiManager import ApiManager
|
||||
|
||||
|
||||
class Manager:
|
||||
|
@ -12,11 +11,17 @@ class Manager:
|
|||
"""
|
||||
|
||||
def __init__(self, interface: str):
|
||||
from . import CommunicationManager, EventManager, RoleManager, AudioManager, PeerManager, DriveManager
|
||||
from . import (
|
||||
CommunicationManager, EventManager, RoleManager, AudioManager, PeerManager,
|
||||
DriveManager, ChronyManager, ApiManager
|
||||
)
|
||||
|
||||
self.storage = Path("./storage/")
|
||||
self.storage.mkdir(exist_ok=True)
|
||||
|
||||
# clock manager
|
||||
self.clock = ChronyManager(self)
|
||||
|
||||
# communication manager
|
||||
self.communication = CommunicationManager(self, interface)
|
||||
self.communication.register_packet_type(b"DISC", packets.DiscoveryPacket)
|
||||
|
|
|
@ -5,5 +5,6 @@ from .AudioManager import AudioManager
|
|||
from .PeerManager import PeerManager
|
||||
from .DriveManager import DriveManager
|
||||
from .ApiManager import ApiManager
|
||||
from .ChronyManager import ChronyManager
|
||||
|
||||
from .Manager import Manager
|
||||
|
|
Loading…
Reference in a new issue