Removed flask-classful from webchat

This patch removed the dependency on flask-classful.  This required
making all of the flask web routing non class based.

This patch also changes the aprsis class to allow retries for failed
connections when the aprsis servers are full and not responding to
login requests.
This commit is contained in:
Hemna 2023-07-19 11:27:34 -04:00
parent e1183a7e30
commit 6a6e854caf
5 changed files with 127 additions and 120 deletions

View File

@ -152,9 +152,10 @@ class APRSISClient(Client):
except LoginError as e:
LOG.error(f"Failed to login to APRS-IS Server '{e}'")
connected = False
raise e
time.sleep(backoff)
except Exception as e:
LOG.error(f"Unable to connect to APRS-IS server. '{e}' ")
connected = False
time.sleep(backoff)
backoff = backoff * 2
continue

View File

@ -112,23 +112,23 @@ class Aprsdis(aprslib.IS):
self._sendall(login_str)
self.sock.settimeout(5)
test = self.sock.recv(len(login_str) + 100)
self.logger.debug("Server: '%s'", test)
if is_py3:
test = test.decode("latin-1")
test = test.rstrip()
self.logger.debug("Server: %s", test)
self.logger.debug("Server: '%s'", test)
a, b, callsign, status, e = test.split(" ", 4)
if not test:
raise LoginError(f"Server Response Empty: '{test}'")
_, _, callsign, status, e = test.split(" ", 4)
s = e.split(",")
if len(s):
server_string = s[0].replace("server ", "")
else:
server_string = e.replace("server ", "")
self.logger.info(f"Connected to {server_string}")
self.server_string = server_string
stats.APRSDStats().set_aprsis_server(server_string)
if callsign == "":
raise LoginError("Server responded with empty callsign???")
if callsign != self.callsign:
@ -141,6 +141,10 @@ class Aprsdis(aprslib.IS):
else:
self.logger.info("Login successful")
self.logger.info(f"Connected to {server_string}")
self.server_string = server_string
stats.APRSDStats().set_aprsis_server(server_string)
except LoginError as e:
self.logger.error(str(e))
self.close()
@ -148,6 +152,7 @@ class Aprsdis(aprslib.IS):
except Exception as e:
self.close()
self.logger.error(f"Failed to login '{e}'")
self.logger.exception(e)
raise LoginError("Failed to login")
def consumer(self, callback, blocking=True, immortal=False, raw=False):

View File

@ -12,7 +12,6 @@ import click
import flask
from flask import request
from flask.logging import default_handler
import flask_classful
from flask_httpauth import HTTPBasicAuth
from flask_socketio import Namespace, SocketIO
from oslo_config import cfg
@ -31,9 +30,16 @@ from aprsd.utils import objectstore, trace
CONF = cfg.CONF
LOG = logging.getLogger("APRSD")
auth = HTTPBasicAuth()
users = None
users = {}
socketio = None
flask_app = flask.Flask(
"aprsd",
static_url_path="/static",
static_folder="web/chat/static",
template_folder="web/chat/templates",
)
def signal_handler(sig, frame):
@ -174,16 +180,11 @@ class WebChatProcessPacketThread(rx.APRSDProcessPacketThread):
)
class WebChatFlask(flask_classful.FlaskView):
def set_config(self):
def set_config():
global users
self.users = {}
user = CONF.admin.user
self.users[user] = generate_password_hash(CONF.admin.password)
users = self.users
def _get_transport(self, stats):
def _get_transport(stats):
if CONF.aprs_network.enabled:
transport = "aprs-is"
aprs_connection = (
@ -212,13 +213,15 @@ class WebChatFlask(flask_classful.FlaskView):
return transport, aprs_connection
@auth.login_required
def index(self):
@flask_app.route("/")
def index():
ua_str = request.headers.get("User-Agent")
# this takes about 2 seconds :(
user_agent = ua_parse(ua_str)
LOG.debug(f"Is mobile? {user_agent.is_mobile}")
stats = self._stats()
stats = _stats()
if user_agent.is_mobile:
html_template = "mobile.html"
@ -230,7 +233,7 @@ class WebChatFlask(flask_classful.FlaskView):
LOG.debug(f"Template {html_template}")
transport, aprs_connection = self._get_transport(stats)
transport, aprs_connection = _get_transport(stats)
LOG.debug(f"transport {transport} aprs_connection {aprs_connection}")
stats["transport"] = transport
@ -245,14 +248,17 @@ class WebChatFlask(flask_classful.FlaskView):
version=aprsd.__version__,
)
@auth.login_required
def send_message_status(self):
@flask_app.route("//send-message-status")
def send_message_status():
LOG.debug(request)
msgs = SentMessages()
info = msgs.get_all()
return json.dumps(info)
def _stats(self):
def _stats():
stats_obj = stats.APRSDStats()
now = datetime.datetime.now()
@ -272,8 +278,10 @@ class WebChatFlask(flask_classful.FlaskView):
return result
def stats(self):
return json.dumps(self._stats())
@flask_app.route("/stats")
def get_stats():
return json.dumps(_stats())
class SendMessageNamespace(Namespace):
@ -377,21 +385,9 @@ def setup_logging(flask_app, loglevel, quiet):
@trace.trace
def init_flask(loglevel, quiet):
global socketio
global socketio, flask_app
flask_app = flask.Flask(
"aprsd",
static_url_path="/static",
static_folder="web/chat/static",
template_folder="web/chat/templates",
)
setup_logging(flask_app, loglevel, quiet)
server = WebChatFlask()
server.set_config()
flask_app.route("/", methods=["GET"])(server.index)
flask_app.route("/stats", methods=["GET"])(server.stats)
# flask_app.route("/send-message", methods=["GET"])(server.send_message)
flask_app.route("/send-message-status", methods=["GET"])(server.send_message_status)
socketio = SocketIO(
flask_app, logger=False, engineio_logger=False,
@ -407,7 +403,7 @@ def init_flask(loglevel, quiet):
"/sendmsg",
),
)
return socketio, flask_app
return socketio
# main() ###
@ -448,6 +444,8 @@ def webchat(ctx, flush, port):
LOG.info(f"APRSD Started version: {aprsd.__version__}")
CONF.log_opt_values(LOG, logging.DEBUG)
user = CONF.admin.user
users[user] = generate_password_hash(CONF.admin.password)
# Initialize the client factory and create
# The correct client object ready for use
@ -466,7 +464,7 @@ def webchat(ctx, flush, port):
packets.WatchList()
packets.SeenList()
(socketio, app) = init_flask(loglevel, quiet)
socketio = init_flask(loglevel, quiet)
rx_thread = rx.APRSDPluginRXThread(
packet_queue=threads.packet_queue,
)
@ -482,7 +480,7 @@ def webchat(ctx, flush, port):
keepalive.start()
LOG.info("Start socketio.run()")
socketio.run(
app,
flask_app,
ssl_context="adhoc",
host=CONF.admin.web_ip,
port=port,

View File

@ -187,6 +187,7 @@ def index():
plugin_count=plugin_count,
)
@auth.login_required
def messages():
track = packets.PacketTrack()
@ -197,9 +198,10 @@ def messages():
return flask.render_template("messages.html", messages=json.dumps(msgs))
@auth.login_required
@app.route("/packets")
def packets():
def get_packets():
LOG.debug("/packets called")
packet_list = aprsd_rpc_client.RPCClient().get_packet_list()
if packet_list:
@ -212,6 +214,7 @@ def packets():
else:
return json.dumps([])
@auth.login_required
@app.route("/plugins")
def plugins():
@ -221,6 +224,7 @@ def plugins():
return "reloaded"
@auth.login_required
@app.route("/save")
def save():
@ -230,7 +234,6 @@ def save():
return json.dumps({"messages": "saved"})
class LogUpdateThread(threads.APRSDThread):
def __init__(self):

View File

@ -39,9 +39,9 @@ class TestSendMessageCommand(unittest.TestCase):
CliRunner()
self.config_and_init()
socketio, flask_app = webchat.init_flask("DEBUG", False)
socketio = webchat.init_flask("DEBUG", False)
self.assertIsInstance(socketio, flask_socketio.SocketIO)
self.assertIsInstance(flask_app, flask.Flask)
self.assertIsInstance(webchat.flask_app, flask.Flask)
@mock.patch("aprsd.packets.tracker.PacketTrack.remove")
@mock.patch("aprsd.cmds.webchat.socketio")