From 68b53ccad10c785ffbbe659c680a68edf19243ab Mon Sep 17 00:00:00 2001 From: Pranav Jerry Date: Tue, 7 Sep 2021 11:19:14 +0530 Subject: [PATCH] implemented daemon naxalnet is now a daemon! When run from systemd, it checks for new devices or removal of devices and reloads the wifi configuration. Updated the systemd service and changed Type to notify. Unfortunately, there is some problem with logging. The messages from naxalnet.iwd could not be found in the systemd journal or while running without --systemd. --- naxalnet.service | 19 +++++++------------ naxalnet/__init__.py | 2 +- naxalnet/config.py | 2 -- naxalnet/daemon.py | 42 +++++++++++++++++++++++++++--------------- naxalnet/iwd.py | 1 - naxalnet/scripts.py | 29 +++++++++++++++++++++++------ 6 files changed, 58 insertions(+), 37 deletions(-) diff --git a/naxalnet.service b/naxalnet.service index 78cbee3..624f8c3 100644 --- a/naxalnet.service +++ b/naxalnet.service @@ -17,28 +17,23 @@ After=NetworkManager.service After=wpa_supplicant.service [Service] -# TODO: change to notify when naxalnet becomes a daemon -Type=oneshot -RemainAfterExit=yes +Type=notify +NotifyAccess=all Restart=on-failure RestartSec=2sec -# IWD takes some time to find devices. -# If naxalnet is run before iwd finds devices, -# naxalnet cannot start a mesh network but exits without errors. -# So, we give a 2s delay. -ExecStartPre=/usr/bin/sleep 2 ExecStart=/usr/bin/naxalnet --systemd # Reload systemd-networkd after naxalnet exits ExecStartPost=/usr/bin/networkctl reload # Delete all files starting with mesh.* in /run/systemd/network -ExecStop=/usr/bin/find /run/systemd/network -type f -delete -name "mesh.*" +ExecStopPost=/usr/bin/find /run/systemd/network -type f -delete -name "mesh.*" # Delete the interfaces created... ExecStopPost=/usr/bin/networkctl delete bridge0 bat0 # ... and reload the configuration files. ExecStopPost=/usr/bin/networkctl reload - -# Disable python buffering -Environment=PYTHONUNBUFFERED=1 +# naxalnet already logs to systemd journal so we don't need +# stdout and stderr. +StandardOutput=null +StandardError=null [Install] WantedBy=multi-user.target diff --git a/naxalnet/__init__.py b/naxalnet/__init__.py index b20beec..7151a24 100644 --- a/naxalnet/__init__.py +++ b/naxalnet/__init__.py @@ -35,4 +35,4 @@ See README.md for documentation. # # In case you forgot to change the version, skip the number # and put the next number in the next commit. -__version__ = "0.3.0a2.dev3" +__version__ = "0.3.0a2.dev4" diff --git a/naxalnet/config.py b/naxalnet/config.py index f541cda..34cb551 100644 --- a/naxalnet/config.py +++ b/naxalnet/config.py @@ -61,8 +61,6 @@ from configparser import ConfigParser from argparse import ArgumentParser, Namespace from naxalnet.default import CONFIG, CONFIG_FILES, CONFIG_DIRS -# from naxalnet.log import logger - def get_config_files(): """ diff --git a/naxalnet/daemon.py b/naxalnet/daemon.py index 9d539f5..a04a47d 100644 --- a/naxalnet/daemon.py +++ b/naxalnet/daemon.py @@ -22,38 +22,50 @@ The daemon part. This is currently under construction. """ import logging -from naxalnet.iwd import IWD +from dasbus.loop import EventLoop +from naxalnet.iwd import IWD, IWD_DEVICE_INTERFACE + +logger = logging.getLogger(__name__) class Daemon: """implements the daemon part""" - logger = logging.getLogger(__name__) - def __init__(self): - iwd = IWD() - self.device_add_call = self.device_remove_call = None + self.loop = EventLoop() + self.iwd = IWD() - def on_device_add(self, callback): + def on_device_add(self, path, data): """ - run the given callback with no arguments - every time a device is added + this function will be run every time a device is added """ - self.device_add_call = callback + if IWD_DEVICE_INTERFACE in data: + logger.debug("New device %s found", str(data[IWD_DEVICE_INTERFACE]["Name"])) + logger.info("Reloading") + self.callback() - def on_device_remove(self, callback): + def on_device_remove(self, path, data): """ - run the given callback with no arguments - every time a device is removed + this function will be run every time a device is removed """ - self.device_remove_call = callback + if IWD_DEVICE_INTERFACE in data: + logger.debug("A device was removed") + logger.info("Reloading") + self.callback() - def register_callbacks(self): + def add_callback(self, callback): """ - register the callbacks with D-Bus + register the callback with D-Bus so that callback is + run every time a device is added or removed """ + self.callback = callback + proxy = self.iwd._proxy + proxy.InterfacesAdded.connect(self.on_device_add) + proxy.InterfacesRemoved.connect(self.on_device_remove) def start(self): """ start the daemon """ + logger.debug("Starting daemon") + self.loop.run() diff --git a/naxalnet/iwd.py b/naxalnet/iwd.py index 19b87b5..ea58643 100644 --- a/naxalnet/iwd.py +++ b/naxalnet/iwd.py @@ -59,7 +59,6 @@ and what they mean: import logging from dasbus.connection import SystemMessageBus -# from naxalnet.log import logger logger = logging.getLogger(__name__) IWD_BUS = "net.connman.iwd" diff --git a/naxalnet/scripts.py b/naxalnet/scripts.py index 99ae572..60242a8 100644 --- a/naxalnet/scripts.py +++ b/naxalnet/scripts.py @@ -32,13 +32,16 @@ from pathlib import Path from shutil import copy from dasbus.error import DBusError from systemd import journal +from systemd.daemon import notify from naxalnet import __version__ from naxalnet.iwd import Adapter, Device, IWD from naxalnet.config import parse_args +from naxalnet.daemon import Daemon -# from naxalnet.log import logger - -logger = logging.getLogger(__name__) +# Do not use getLogger(__name__) here. +# getLogger() without any args will give us +# the root logger, which is waht we need. +logger = logging.getLogger() args = parse_args() @@ -50,6 +53,7 @@ def copy_files(): See man:systemd.network(5) """ try: + notify("STATUS=Configuring the network...") logger.info("Copying network config files") dest = Path(args.networkd_runtime_dir) src = Path(args.networkd_config_dir) @@ -72,6 +76,7 @@ def setup_devices(): is connected or removed. """ try: + notify("STATUS=Setting up mesh...") iwd = IWD() devices = iwd.get_devices() adhoc_devices = [] @@ -122,11 +127,12 @@ def setup_devices(): ap_adapter.power_on() ap_device.start_ap(args.ap_ssid, args.ap_passwd) else: - logger.info("Not setting up WiFi AP.") + logger.warning("Not setting up WiFi AP.") else: logger.warning( "No device found to setup mesh. Make sure a WiFi adapter is connected" ) + except DBusError: logger.exception("Error while communicating with iwd") sys.exit(4) @@ -170,7 +176,7 @@ def main(): # if --systemd is given, log to systemd journal if args.systemd: - logger.setLevel(level=logging.DEBUG) + logging.basicConfig(level=logging.DEBUG) logger.addHandler(journal.JournalHandler()) else: logging.basicConfig(level=loglevel) @@ -178,6 +184,17 @@ def main(): copy_files() setup_devices() + # Notify systemd that naxalnet is ready. + # see man:sd_notify(3) + notify("READY=1") - # naxalnet prints Bye if no errors occured + # Start the daemon so that setup_devices() is called every + # time a device is connected or removed. + daemon = Daemon() + daemon.add_callback(setup_devices) + + notify("STATUS=Waiting for changes") + daemon.start() + + # naxalnet prints Bye while exiting. logger.info("Bye")