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
|
# make sure we trust the peers trusted by this peer
|
||||||
for public_key_hash in peer.allowed_public_key_hashes:
|
for public_key_hash in peer.allowed_public_key_hashes:
|
||||||
self.manager.communication.trust_peer_hash(public_key_hash)
|
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 subprocess
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from source import managers
|
||||||
|
|
||||||
|
|
||||||
class BatmanController:
|
class ChronyManager:
|
||||||
# TODO: need to be able to get ping in the network if possible, otherwise no other uses
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ChronyController:
|
|
||||||
"""
|
"""
|
||||||
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
|
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.clear_sources()
|
||||||
self.deny_client("all")
|
self.deny_client("all")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run_command(*args: str) -> str:
|
def run_command(*args: str) -> str:
|
||||||
# run the command through the chrony command line tool
|
# 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(
|
process = subprocess.run(
|
||||||
["chronyc", *args],
|
["chronyc", *args],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
)
|
)
|
||||||
# raise an error if the command did not ended up successfully
|
|
||||||
process.check_returncode()
|
|
||||||
|
|
||||||
# return the stdout of the command
|
# return the stdout of the command
|
||||||
return process.stdout.decode()
|
return process.stdout.decode()
|
||||||
|
|
||||||
def get_sources(self) -> list[...]:
|
def get_sources(self) -> typing.Iterator[str]:
|
||||||
"""
|
"""
|
||||||
Get the list of NTP sources
|
Get the list of NTP sources
|
||||||
:return: 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
|
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
|
Remove a source from chrony
|
||||||
"""
|
"""
|
||||||
|
|
||||||
...
|
self.run_command("delete", address)
|
||||||
|
|
||||||
def clear_sources(self) -> None:
|
def clear_sources(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -61,34 +63,39 @@ class ChronyController:
|
||||||
for source in self.get_sources():
|
for source in self.get_sources():
|
||||||
self.remove_source(source)
|
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
|
Get the list of clients using us as a server
|
||||||
:return: the list of clients
|
: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
|
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:
|
def allow_all_clients(self) -> None:
|
||||||
"""
|
"""
|
||||||
Allow all clients to use us as a time-server
|
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
|
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:
|
def deny_all_clients(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -96,11 +103,3 @@ class ChronyController:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.deny_client("all")
|
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 import packets
|
||||||
from source.behaviors import events
|
from source.behaviors import events
|
||||||
from source.managers.ApiManager import ApiManager
|
|
||||||
|
|
||||||
|
|
||||||
class Manager:
|
class Manager:
|
||||||
|
@ -12,11 +11,17 @@ class Manager:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interface: str):
|
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 = Path("./storage/")
|
||||||
self.storage.mkdir(exist_ok=True)
|
self.storage.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# clock manager
|
||||||
|
self.clock = ChronyManager(self)
|
||||||
|
|
||||||
# communication manager
|
# communication manager
|
||||||
self.communication = CommunicationManager(self, interface)
|
self.communication = CommunicationManager(self, interface)
|
||||||
self.communication.register_packet_type(b"DISC", packets.DiscoveryPacket)
|
self.communication.register_packet_type(b"DISC", packets.DiscoveryPacket)
|
||||||
|
|
|
@ -5,5 +5,6 @@ from .AudioManager import AudioManager
|
||||||
from .PeerManager import PeerManager
|
from .PeerManager import PeerManager
|
||||||
from .DriveManager import DriveManager
|
from .DriveManager import DriveManager
|
||||||
from .ApiManager import ApiManager
|
from .ApiManager import ApiManager
|
||||||
|
from .ChronyManager import ChronyManager
|
||||||
|
|
||||||
from .Manager import Manager
|
from .Manager import Manager
|
||||||
|
|
Loading…
Reference in a new issue