logging #16

Merged
pranav merged 8 commits from logging into master 2021-09-05 10:33:33 +02:00
17 changed files with 268 additions and 76 deletions

151
.gitignore vendored
View File

@ -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

View File

@ -1,5 +1,10 @@
# Changelog
## [Unreleased][] - 2021-09-05
- Now logs to systemd journal. New dependency - `python3-systemd`
- Fixed dependency order in systemd service
## [v0.3.0][] - 2021-08-19
- Support for arguments

View File

@ -17,7 +17,7 @@ network.
<!-- NOTE TO ACTIVISTS
Running this program in the world's largest partly-free democracy
Running this program in the world's largest (partly-free) democracy
may result in you getting arrested under the UAPA, and not
getting bail because of false evidence planted in your phone by
Pegasus, or by a forensic lab in Gujarat.
@ -41,16 +41,17 @@ with anyone currently at risk of death in overcrowded prisons.
## Requirements
- [systemd v248 or more][batman-systemd]
- [systemd-networkd v248 or more][batman-systemd]
- Linux kernel with batman-adv module
- [iwd][]
- python
- python-setuptools (for building and installing)
- [dasbus][]
- WiFi adapter with ad-hoc support
- two or more computers, or laptops with WiFi adapter, called nodes
- [iwd][] for controlling the WiFi adapter
- python3
- python3-setuptools, for building and installing naxalnet
- python3-systemd, for logging to systemd journal
- [dasbus][], for communicating with iwd
- two or more machines with a WiFi adapter having ad-hoc support, called
nodes or peers
- batctl (optional, for debugging)
- python pip (optional, for uninstalling)
- python3-pip (optional, for `make uninstall` to work)
## Installing
@ -74,17 +75,17 @@ you need it.
naxalnet is not packaged for Ubuntu, so you will have to build
and install it manually.
Currently, only the [unreleased 21.10][ubuntu-systemd] comes with the
required version of systemd. Therefore, naxalnet won't work on Ubuntu
21.04 or older.
Currently, only the **unreleased 21.10** comes with the
required version of systemd. Therefore, naxalnet **won't work on Ubuntu
21.04 or older**.
<!-- TODO: remove this message when systemd 248 arrives in 21.04 -->
<!-- TODO: remove this message if systemd 248 arrives in 21.04 -->
Install the requirements from the Ubuntu repositories:
```sh
# batctl is optional
sudo apt install systemd python3-pip iwd batctl build-essential
sudo apt install python3-pip python3-systemd iwd batctl build-essential
# Now, install dasbus with pip
sudo pip3 install dasbus
```
@ -96,11 +97,11 @@ Now follow the instructions in the
naxalnet is not packaged for Fedora, so it should be installed
manually. naxalnet requires atleast systemd v248 which is only
available on Fedora 34 and above. Install the dependencies:
available on **Fedora 34 and above**. Install the dependencies:
```sh
# systemd-resolved may be required for rawhide
sudo dnf install systemd-networkd iwd python3-dasbus python3-setuptools
sudo dnf install systemd-networkd iwd python3-dasbus python3-setuptools python3-systemd
```
Now head over to the [next section][install-manual] to install naxalnet.
@ -221,10 +222,10 @@ naxalnet --help
## How it works
There are three modes commonly supported by WiFi adapters -
`ap` (WiFi hotspot), `station` (for joining WiFi networks) and `ad-hoc`
(for decentralised networks). There are some other modes too,
like `p2p` (WiFi direct), but we won't go into the details.
There are three modes commonly supported by WiFi adapters - `ap` (WiFi
hotspot), `station` (for joining WiFi networks) and `ad-hoc` (for
decentralised networks). There are other modes supported by some WiFi
adapters too, like `p2p` (WiFi direct), but this program doesn't use them.
naxalnet uses two modes - `ad-hoc` and `ap`, for connecting to the
mesh. naxalnet uses iwd to start an `ad-hoc` network and configures
@ -234,8 +235,8 @@ naxalnet starts an ad-hoc on one of them and an ap on the other.
You can use the ap for connecting mobile phones and other devices
to the mesh network.
Read the code to learn the details.
See [systemd-networkd](systemd-networkd) to see how
Read the code and the documentation to learn the details.
See the directory [systemd-networkd](systemd-networkd) to see how
systemd-networkd configures the network.
## Use cases
@ -245,15 +246,22 @@ systemd-networkd configures the network.
naxalnet can be used to share connections in remote areas.
You need at least one device with internet access.
<!--
### Malign democracies and well-established institutions
Withheld due to national security reasons.
-->
### Internet shutdown
You can communicate with neighbouring devices running naxalnet,
using services like [IPFS][], [Jami][], [Secure Scuttlebutt][ssb]
and others which can work on an intranet.
They should be installed on your machine _before_ your friendly
democratic government announces an [internet shutdown][], since you
cannot download and install them during a shutdown.
When a shutdown occurs, [enable naxalnet][enablenx]
You can communicate with neighbouring devices running naxalnet, using
services like [IPFS][], [Jami][], [Secure Scuttlebutt][ssb] and others
which can work on an intranet. They should be installed on your
machine _before_ your friendly democratic government announces an
[internet shutdown][], since you cannot download and install them
during a shutdown. When a shutdown occurs, [enable naxalnet][enablenx].
## Uninstalling
@ -273,10 +281,16 @@ See [HACKING.md](HACKING.md)
## Similar projects
The following projects are similar to naxalnet, but are not designed
to be used in a machine with WiFi adapter. If you live in
an area where the materials required for any of them are easily
available, consider using them instead of naxalnet.
Many projects make setting up B.A.T.M.A.N. Advanced mesh networks with
WiFi routers easier. They are easier to setup and are more
configurable. But naxalnet is different from them. It simplifies
setting up mesh networks with _laptops or computers_, and is not
designed to work with routers.
The following projects does something similar to naxalnet, but
requires special devices or routers to work. If you live in an area
where the materials required for any of them are easily available,
consider using them instead of naxalnet.
- [LibreMesh][]: framework for OpenWrt-based firmwares
- [disaster.radio][]: solar-powered communications network
@ -306,6 +320,5 @@ See [LICENSE](LICENSE) for the complete version of the license.
[iwd]: https://iwd.wiki.kernel.org "WiFi daemon"
[free-sw]: https://gnu.org/philosophy/free-sw.html "What is free software?"
[enablenx]: #running-at-boot
[ubuntu-systemd]: https://packages.ubuntu.com/impish/systemd
[requirements]: #requirements
[install-manual]: #manually

View File

@ -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
@ -27,20 +30,14 @@ ExecStartPre=/usr/bin/sleep 2
ExecStart=/usr/bin/naxalnet
# Reload systemd-networkd after naxalnet exits
ExecStartPost=/usr/bin/networkctl reload
# Delete all files in /run/systemd/network
ExecStop=/usr/bin/find /run/systemd/network -type f -delete
# Delete all files starting with mesh.* in /run/systemd/network
ExecStop=/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
# 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]

View File

@ -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.0a2"

View File

@ -46,6 +46,7 @@ from pathlib import Path
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():
@ -54,6 +55,7 @@ def get_config_files():
of files that exists as pathlib.Path objects
"""
config_files = []
for directory in CONFIG_DIRS:
path = Path(directory)
if path.exists():
@ -68,12 +70,14 @@ def parse_config():
Parse all configuration files, with the values in
default.py as fallback
"""
logger.debug("Parsing config files")
parser = ConfigParser()
# encoded defaults
parser.read_dict(CONFIG)
# read config files
files = get_config_files()
for i in files:
logger.debug("Reading config file %s", str(i))
parser.read_file(i.open())
return parser
@ -141,4 +145,5 @@ def parse_args() -> Namespace:
help="prints the version and exit",
)
logger.debug("Parsing arguments")
return parser.parse_args()

View File

@ -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()
@ -265,11 +270,15 @@ class Device:
# Stop ap if already started
self.stop_ap()
logger.debug(
"Starting ap on %s with ssid %s and password %s", self.name, ssid, passwd
)
self._proxy.Start(ssid, passwd)
def stop_ap(self):
"""stop ap if an ap is started"""
if self.is_ap_started():
logger.debug("Stopping ap on %s", self.name)
self._proxy.Stop()
self.reload()
@ -277,8 +286,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
@ -300,10 +309,12 @@ class Adapter:
def power_on(self):
"""power on the adapter"""
self._proxy.Powered = True
logger.debug("Powered on adapter %s", self.name)
def power_off(self):
"""power off the adapter"""
self._proxy.Powered = False
logger.debug("Powered off adapter %s", self.name)
def supports_mode(self, mode: str) -> bool:
"""

16
naxalnet/log.py Normal file
View File

@ -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())

View File

@ -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,16 +105,20 @@ 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)
# naxalnet prints Bye if no errors occured
logger.info("Bye")
def print_wifi(args):
"""
@ -144,14 +153,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.")

View File

@ -19,9 +19,11 @@ packages = find:
python_requires = >=3.6
install_requires =
dasbus
# pathlib, configparser and argparse are in the standard library
configparser
pathlib
argparse
systemd
[options.entry_points]
console_scripts =
@ -33,10 +35,10 @@ lib/systemd/system =
/etc/naxalnet =
naxalnet.conf.example
share/naxalnet/networkd =
systemd-networkd/01-batman.netdev
systemd-networkd/02-bridge.netdev
systemd-networkd/03-wireless-ad-hoc.network
systemd-networkd/04-batman.network
systemd-networkd/05-wireless-ap.network
systemd-networkd/06-eth.network
systemd-networkd/07-bridge.network
systemd-networkd/mesh.01-batman.netdev
systemd-networkd/mesh.02-bridge.netdev
systemd-networkd/mesh.03-wireless-ad-hoc.network
systemd-networkd/mesh.04-batman.network
systemd-networkd/mesh.05-wireless-ap.network
systemd-networkd/mesh.06-eth.network
systemd-networkd/mesh.07-bridge.network