diff --git a/aprsd/cmds/admin.py b/aprsd/cmds/admin.py new file mode 100644 index 0000000..cc77bed --- /dev/null +++ b/aprsd/cmds/admin.py @@ -0,0 +1,54 @@ +import logging +import os +import signal + +import click +from oslo_config import cfg +import socketio + +import aprsd +from aprsd import cli_helper +from aprsd import main as aprsd_main +from aprsd import utils +from aprsd.main import cli + + +os.environ["APRSD_ADMIN_COMMAND"] = "1" +from aprsd import wsgi as aprsd_wsgi + + +CONF = cfg.CONF +LOG = logging.getLogger("APRSD") + + +# main() ### +@cli.command() +@cli_helper.add_options(cli_helper.common_options) +@click.pass_context +@cli_helper.process_standard_options +def admin(ctx): + """Start the aprsd admin interface.""" + signal.signal(signal.SIGINT, aprsd_main.signal_handler) + signal.signal(signal.SIGTERM, aprsd_main.signal_handler) + + level, msg = utils._check_version() + if level: + LOG.warning(msg) + else: + LOG.info(msg) + LOG.info(f"APRSD Started version: {aprsd.__version__}") + # Dump all the config options now. + CONF.log_opt_values(LOG, logging.DEBUG) + + async_mode = "threading" + sio = socketio.Server(logger=True, async_mode=async_mode) + aprsd_wsgi.app.wsgi_app = socketio.WSGIApp(sio, aprsd_wsgi.app.wsgi_app) + aprsd_wsgi.init_app() + sio.register_namespace(aprsd_wsgi.LoggingNamespace("/logs")) + CONF.log_opt_values(LOG, logging.DEBUG) + aprsd_wsgi.app.run( + threaded=True, + debug=False, + port=CONF.admin.web_port, + host=CONF.admin.web_ip, + ) diff --git a/aprsd/main.py b/aprsd/main.py index e052ab9..7609bc0 100644 --- a/aprsd/main.py +++ b/aprsd/main.py @@ -54,7 +54,7 @@ def cli(ctx): def load_commands(): from .cmds import ( # noqa - completion, dev, fetch_stats, healthcheck, list_plugins, listen, + admin, completion, dev, fetch_stats, healthcheck, list_plugins, listen, send_message, server, webchat, ) @@ -79,11 +79,15 @@ def signal_handler(sig, frame): ), ) time.sleep(1.5) - packets.PacketTrack().save() - packets.WatchList().save() - packets.SeenList().save() - packets.PacketList().save() - collector.Collector().collect() + try: + packets.PacketTrack().save() + packets.WatchList().save() + packets.SeenList().save() + packets.PacketList().save() + collector.Collector().collect() + except Exception as e: + LOG.error(f"Failed to save data: {e}") + sys.exit(0) # signal.signal(signal.SIGTERM, sys.exit(0)) # sys.exit(0) diff --git a/aprsd/wsgi.py b/aprsd/wsgi.py index 28fc02e..0d7d2d6 100644 --- a/aprsd/wsgi.py +++ b/aprsd/wsgi.py @@ -3,6 +3,7 @@ import importlib.metadata as imp import io import json import logging +import os import queue import flask @@ -23,6 +24,12 @@ CONF = cfg.CONF LOG = logging.getLogger("gunicorn.access") logging_queue = queue.Queue() + +# ADMIN_COMMAND True means we are running from `aprsd admin` +# the `aprsd admin` command will import this file after setting +# the APRSD_ADMIN_COMMAND environment variable. +ADMIN_COMMAND = os.environ.get("APRSD_ADMIN_COMMAND", False) + auth = HTTPBasicAuth() users: dict[str, str] = {} app = Flask( @@ -262,6 +269,7 @@ def init_app(config_file=None, log_level=None): return log_level +print(f"__name__ = {__name__}") if __name__ == "__main__": async_mode = "threading" @@ -297,7 +305,7 @@ if __name__ == "uwsgi_file_aprsd_wsgi": CONF.log_opt_values(LOG, logging.DEBUG) -if __name__ == "aprsd.wsgi": +if __name__ == "aprsd.wsgi" and not ADMIN_COMMAND: # set async_mode to 'threading', 'eventlet', 'gevent' or 'gevent_uwsgi' to # force a mode else, the best mode is selected automatically from what's # installed