diff --git a/.gitignore b/.gitignore index 3f339ae..4906f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,145 @@ -.DS_Store -.idea -*.log -tmp/ +# Created by https://www.toptal.com/developers/gitignore/api/python +# Edit at https://www.toptal.com/developers/gitignore?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ *.py[cod] -*.egg* -build -htmlcov -__pycache__ +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# End of https://www.toptal.com/developers/gitignore/api/python diff --git a/naxalnet.service b/naxalnet.service index 2691a31..d3ba53d 100644 --- a/naxalnet.service +++ b/naxalnet.service @@ -7,6 +7,8 @@ Requires=systemd-networkd.service Requires=iwd.service Wants=systemd-resolved.service After=iwd.service +After=systemd-networkd.service +After=systemd-resolved.service # Stops NetworkManager and wpa_supplicant if already running Conflicts=NetworkManager.service Conflicts=wpa_supplicant.service @@ -15,6 +17,7 @@ After=NetworkManager.service After=wpa_supplicant.service [Service] +# TODO: change to notify when naxalnet becomes a daemon Type=oneshot RemainAfterExit=yes Restart=on-failure @@ -33,14 +36,8 @@ ExecStop=/usr/bin/find /run/systemd/network -type f -delete ExecStopPost=/usr/bin/networkctl delete bridge0 bat0 # ... and reload the configuration files. ExecStopPost=/usr/bin/networkctl reload -# Make python flush messages instead of buffering. -# When reading the systemd journal, we need to see the messages -# in the exact order. There will suddenly be a lot of messages -# from naxalnet, networkd, iwd and resolved. When buffering is on, -# we won't see the messages from naxalnet in the order they were -# printed. This, among other problems, make it hard while debugging. -# This will no longer be needed when naxalnet sends its messages -# directly to the systtemd journal instead of stdout. + +# Disable python buffering Environment=PYTHONUNBUFFERED=1 [Install] diff --git a/naxalnet/__init__.py b/naxalnet/__init__.py index 0e5a7d2..c2e97a2 100644 --- a/naxalnet/__init__.py +++ b/naxalnet/__init__.py @@ -36,4 +36,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.0" +__version__ = "0.3.0a1.dev1" diff --git a/naxalnet/iwd.py b/naxalnet/iwd.py index 30cb9f9..257adce 100644 --- a/naxalnet/iwd.py +++ b/naxalnet/iwd.py @@ -58,8 +58,8 @@ and what they mean: - node: a machine that runs naxalnet and is therefore connected to the mesh. """ - from dasbus.connection import SystemMessageBus +from naxalnet.log import logger IWD_BUS = "net.connman.iwd" IWD_ROOT_PATH = "/" @@ -165,8 +165,8 @@ class Device: adapter: name of adapter (str) """ - def __init__(self, name: str, bus=SystemMessageBus()): - self._iwd = IWD(bus) + def __init__(self, name: str): + self._iwd = IWD() self._bus = self._iwd._bus self._path = self._iwd.get_device_path_from_name(name) self.reload() @@ -181,11 +181,13 @@ class Device: def power_on(self): """Turn on the device and reload the proxy""" self._proxy.Powered = True + logger.debug("Powered on %s", self.name) self.reload() def power_off(self): """Turn off the device and reload the proxy""" self._proxy.Powered = False + logger.debug("Powered off %s", self.name) self.reload() def reload(self): @@ -225,6 +227,7 @@ class Device: def set_mode(self, mode: str): """change the device mode to mode""" self._proxy.Mode = mode + logger.debug("Set mode on %s to %s", self.name, mode) self.reload() def start_adhoc_open(self, name: str): @@ -242,11 +245,13 @@ class Device: # Stop adhoc if already started self.stop_adhoc() + logger.debug("Starting ad-hoc on %s", self.name) self._proxy.StartOpen(name) def stop_adhoc(self): """stop adhoc if adhoc is started""" if self.is_adhoc_started(): + logger.debug("Stopping ad-hoc on %s", self.name) self._proxy.Stop() self.reload() @@ -277,8 +282,8 @@ class Device: class Adapter: """represents an adapter as a python object""" - def __init__(self, name: str, bus=SystemMessageBus()): - self._iwd = IWD(bus) + def __init__(self, name: str): + self._iwd = IWD() self._bus = self._iwd._bus self._path = self._iwd.get_adapter_path_from_name(name) # Initialise self._proxy diff --git a/naxalnet/log.py b/naxalnet/log.py new file mode 100644 index 0000000..75c2a9c --- /dev/null +++ b/naxalnet/log.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +""" +log.py +------ + +This file contains the logger object, which is required for logging +to the systemd journal +""" + +import logging +from systemd import journal + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +logger.addHandler(journal.JournalHandler()) diff --git a/naxalnet/scripts.py b/naxalnet/scripts.py index 5e70883..11e0de9 100644 --- a/naxalnet/scripts.py +++ b/naxalnet/scripts.py @@ -34,6 +34,7 @@ from dasbus.error import DBusError from naxalnet import __version__ from naxalnet.iwd import Adapter, Device, IWD from naxalnet.config import parse_args +from naxalnet.log import logger def copy_files(args): @@ -44,7 +45,7 @@ def copy_files(args): See man:systemd.network(5) """ - print("Copying network config files") + logger.info("Copying network config files") dest = Path(args.networkd_runtime_dir) src = Path(args.networkd_config_dir) @@ -74,10 +75,13 @@ def setup_devices(args): # ad-hoc or ap. Many adapters will support both, # so we will prioritise ad-hoc over ap. device = Device(i) + logger.debug("Found device %s", device.name) adapter = Adapter(device.adapter) if adapter.supports_mode("ad-hoc"): + logger.debug("The device %s can be used for ad-hoc", device.name) adhoc_devices.append(i) if adapter.supports_mode("ap"): + logger.debug("The device %s can be used for ap", device.name) ap_devices.append(i) if len(adhoc_devices) != 0: @@ -88,11 +92,12 @@ def setup_devices(args): # So we will remove adhoc_device from ap_devices if it exists there if adhoc_device.name in ap_devices: ap_devices.remove(adhoc_device.name) - print("Starting mesh on", adhoc_device.name) + logger.info("Starting mesh on %s", adhoc_device.name) # Turn on adapter if it is off # See issue #9 adhoc_adapter = Adapter(adhoc_device.adapter) if not adhoc_adapter.is_powered_on(): + logger.debug("Adapter %s is off. Turning on", adhoc_adapter.name) adhoc_adapter.power_on() adhoc_device.reload() adhoc_device.start_adhoc_open(args.adhoc_name) @@ -100,12 +105,13 @@ def setup_devices(args): # ie, we have more devices if len(ap_devices) != 0: ap_device = Device(ap_devices.pop()) - print("Starting WiFi Access point on", ap_device.name) - print('Use "naxalnet --print-wifi" to get password') + logger.info("Starting WiFi Access Point on %s", ap_device.name) + logger.info("Use naxalnet --print-wifi to get password") # Turn on adapter if it is off # See issue #9 ap_adapter = Adapter(ap_device.adapter) if not ap_adapter.is_powered_on(): + logger.debug("Adapter %s is off. Turning on", ap_adapter.name) ap_adapter.power_on() ap_adapter.reload() ap_device.start_ap(args.ap_ssid, args.ap_passwd) @@ -144,14 +150,13 @@ def here_be_dragons(): try: copy_files(args) except PermissionError as error: - print(error) - sys.exit("Make sure you are root") + logger.error("Cannot copy file: %s", error) + sys.exit(3) try: setup_devices(args) - except DBusError as error: - print(error) - sys.exit("An error occured while communicating with iwd") + except DBusError: + logger.exception("Error while communicating with iwd") + sys.exit(4) - # naxalnet will print Bye if no errors occured - print("Bye") + logger.debug("Finished.") diff --git a/setup.cfg b/setup.cfg index e03bdf4..badf0bc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,6 +22,7 @@ install_requires = configparser pathlib argparse + systemd [options.entry_points] console_scripts =