mirror of
https://github.com/craigerl/aprsd.git
synced 2024-11-21 23:55:17 -05:00
replacement of flask-socketio with python-socketio
This patch starts the work to replace flask-socketio with python-socketio so that uwsgi can be used instead of gunicorn. uwsgi can support websockets. Have to rework webchat command next
This commit is contained in:
parent
5383b698ea
commit
89576a3c43
@ -56,7 +56,7 @@ class RPCClient:
|
|||||||
config={}, ipv6=False,
|
config={}, ipv6=False,
|
||||||
keepalive=False, authorizer=None, ):
|
keepalive=False, authorizer=None, ):
|
||||||
|
|
||||||
print(f"Connecting to RPC host {host}:{port}")
|
LOG.info(f"Connecting to RPC host '{host}:{port}'")
|
||||||
try:
|
try:
|
||||||
s = rpc.AuthSocketStream.connect(
|
s = rpc.AuthSocketStream.connect(
|
||||||
host, port, ipv6=ipv6, keepalive=keepalive,
|
host, port, ipv6=ipv6, keepalive=keepalive,
|
||||||
@ -64,7 +64,7 @@ class RPCClient:
|
|||||||
)
|
)
|
||||||
return rpyc.utils.factory.connect_stream(s, service, config=config)
|
return rpyc.utils.factory.connect_stream(s, service, config=config)
|
||||||
except ConnectionRefusedError:
|
except ConnectionRefusedError:
|
||||||
LOG.error(f"Failed to connect to RPC host {host}")
|
LOG.error(f"Failed to connect to RPC host '{host}:{port}'")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_rpc_client(self):
|
def get_rpc_client(self):
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
||||||
<script src="https://cdn.socket.io/4.1.2/socket.io.min.js" integrity="sha384-toS6mmwu70G0fw54EGlWWeA4z3dyJ+dlXBtSURSKN4vyRFOcxd3Bzjj/AoOwY+Rg" crossorigin="anonymous"></script>
|
<script src="https://cdn.socket.io/4.7.1/socket.io.min.js" integrity="sha512-+NaO7d6gQ1YPxvc/qHIqZEchjGm207SszoNeMgppoqD/67fEqmc1edS8zrbxPD+4RQI3gDgT/83ihpFW61TG/Q==" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.bundle.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.bundle.js"></script>
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ import flask
|
|||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask.logging import default_handler
|
from flask.logging import default_handler
|
||||||
from flask_httpauth import HTTPBasicAuth
|
from flask_httpauth import HTTPBasicAuth
|
||||||
from flask_socketio import Namespace, SocketIO
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
import socketio
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
|
|
||||||
import aprsd
|
import aprsd
|
||||||
@ -29,7 +29,8 @@ app = Flask(
|
|||||||
static_folder="web/admin/static",
|
static_folder="web/admin/static",
|
||||||
template_folder="web/admin/templates",
|
template_folder="web/admin/templates",
|
||||||
)
|
)
|
||||||
socket_io = SocketIO(app)
|
bg_thread = None
|
||||||
|
app.config["SECRET_KEY"] = "secret!"
|
||||||
|
|
||||||
|
|
||||||
# HTTPBasicAuth doesn't work on a class method.
|
# HTTPBasicAuth doesn't work on a class method.
|
||||||
@ -119,7 +120,6 @@ def stats():
|
|||||||
return json.dumps(_stats())
|
return json.dumps(_stats())
|
||||||
|
|
||||||
|
|
||||||
@auth.login_required
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
stats = _stats()
|
stats = _stats()
|
||||||
@ -240,51 +240,46 @@ class LogUpdateThread(threads.APRSDThread):
|
|||||||
super().__init__("LogUpdate")
|
super().__init__("LogUpdate")
|
||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
global socket_io
|
if sio:
|
||||||
|
|
||||||
if socket_io:
|
|
||||||
log_entries = aprsd_rpc_client.RPCClient().get_log_entries()
|
log_entries = aprsd_rpc_client.RPCClient().get_log_entries()
|
||||||
|
|
||||||
if log_entries:
|
if log_entries:
|
||||||
|
LOG.info(f"Sending log entries! {len(log_entries)}")
|
||||||
for entry in log_entries:
|
for entry in log_entries:
|
||||||
socket_io.emit(
|
sio.emit(
|
||||||
"log_entry", entry,
|
"log_entry", entry,
|
||||||
namespace="/logs",
|
namespace="/logs",
|
||||||
)
|
)
|
||||||
|
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class LoggingNamespace(Namespace):
|
class LoggingNamespace(socketio.Namespace):
|
||||||
log_thread = None
|
log_thread = None
|
||||||
|
|
||||||
def on_connect(self):
|
def on_connect(self, sid, environ):
|
||||||
global socket_io
|
global sio
|
||||||
socket_io.emit(
|
LOG.debug(f"LOG on_connect {sid}")
|
||||||
|
sio.emit(
|
||||||
"connected", {"data": "/logs Connected"},
|
"connected", {"data": "/logs Connected"},
|
||||||
namespace="/logs",
|
namespace="/logs",
|
||||||
)
|
)
|
||||||
self.log_thread = LogUpdateThread()
|
self.log_thread = LogUpdateThread()
|
||||||
self.log_thread.start()
|
self.log_thread.start()
|
||||||
|
|
||||||
def on_disconnect(self):
|
def on_disconnect(self, sid):
|
||||||
LOG.debug("LOG Disconnected")
|
LOG.debug(f"LOG Disconnected {sid}")
|
||||||
if self.log_thread:
|
if self.log_thread:
|
||||||
self.log_thread.stop()
|
self.log_thread.stop()
|
||||||
|
|
||||||
|
|
||||||
def setup_logging(flask_app, loglevel):
|
def setup_logging(flask_app, loglevel):
|
||||||
flask_log = logging.getLogger("werkzeug")
|
global app, LOG
|
||||||
flask_app.logger.removeHandler(default_handler)
|
|
||||||
flask_log.removeHandler(default_handler)
|
|
||||||
LOG.handlers = []
|
|
||||||
|
|
||||||
log_level = conf.log.LOG_LEVELS[loglevel]
|
log_level = conf.log.LOG_LEVELS[loglevel]
|
||||||
LOG.setLevel(log_level)
|
app.logger.setLevel(log_level)
|
||||||
|
flask_app.logger.removeHandler(default_handler)
|
||||||
|
|
||||||
date_format = CONF.logging.date_format
|
date_format = CONF.logging.date_format
|
||||||
flask_app.logger.disabled = True
|
|
||||||
gunicorn_err = logging.getLogger("gunicorn.error")
|
|
||||||
|
|
||||||
if CONF.logging.rich_logging:
|
if CONF.logging.rich_logging:
|
||||||
log_format = "%(message)s"
|
log_format = "%(message)s"
|
||||||
@ -294,7 +289,7 @@ def setup_logging(flask_app, loglevel):
|
|||||||
rich_tracebacks=True, omit_repeated_times=False,
|
rich_tracebacks=True, omit_repeated_times=False,
|
||||||
)
|
)
|
||||||
rh.setFormatter(log_formatter)
|
rh.setFormatter(log_formatter)
|
||||||
LOG.addHandler(rh)
|
app.logger.addHandler(rh)
|
||||||
|
|
||||||
log_file = CONF.logging.logfile
|
log_file = CONF.logging.logfile
|
||||||
|
|
||||||
@ -306,9 +301,9 @@ def setup_logging(flask_app, loglevel):
|
|||||||
backupCount=4,
|
backupCount=4,
|
||||||
)
|
)
|
||||||
fh.setFormatter(log_formatter)
|
fh.setFormatter(log_formatter)
|
||||||
LOG.addHandler(fh)
|
app.logger.addHandler(fh)
|
||||||
|
|
||||||
gunicorn_err.handlers = LOG.handlers
|
LOG = app.logger
|
||||||
|
|
||||||
|
|
||||||
def init_app(config_file=None, log_level=None):
|
def init_app(config_file=None, log_level=None):
|
||||||
@ -327,11 +322,41 @@ def init_app(config_file=None, log_level=None):
|
|||||||
return log_level
|
return log_level
|
||||||
|
|
||||||
|
|
||||||
print(f"APP {__name__}")
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
socket_io.run(app)
|
async_mode = "threading"
|
||||||
|
sio = socketio.Server(logger=True, async_mode=async_mode)
|
||||||
|
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
|
||||||
|
log_level = init_app(log_level="DEBUG")
|
||||||
|
setup_logging(app, log_level)
|
||||||
|
sio.register_namespace(LoggingNamespace("/logs"))
|
||||||
|
CONF.log_opt_values(LOG, logging.DEBUG)
|
||||||
|
app.run(threaded=True, debug=True, port=8100)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "uwsgi_file_aprsd_wsgi":
|
||||||
|
# Start with
|
||||||
|
# uwsgi --http :8000 --gevent 1000 --http-websockets --master -w aprsd.wsgi --callable app
|
||||||
|
|
||||||
|
async_mode = "gevent_uwsgi"
|
||||||
|
sio = socketio.Server(logger=True, async_mode=async_mode)
|
||||||
|
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
|
||||||
|
log_level = init_app(
|
||||||
|
log_level="DEBUG",
|
||||||
|
config_file="/config/aprsd.conf",
|
||||||
|
)
|
||||||
|
setup_logging(app, log_level)
|
||||||
|
sio.register_namespace(LoggingNamespace("/logs"))
|
||||||
|
CONF.log_opt_values(LOG, logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "aprsd.wsgi":
|
if __name__ == "aprsd.wsgi":
|
||||||
|
# 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
|
||||||
|
async_mode = "threading"
|
||||||
|
sio = socketio.Server(logger=True, async_mode=async_mode)
|
||||||
|
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
|
||||||
|
|
||||||
log_level = init_app(config_file="/config/aprsd.conf", log_level="DEBUG")
|
log_level = init_app(config_file="/config/aprsd.conf", log_level="DEBUG")
|
||||||
socket_io.on_namespace(LoggingNamespace("/logs"))
|
sio.on_namespace(LoggingNamespace("/logs"))
|
||||||
setup_logging(app, log_level)
|
setup_logging(app, log_level)
|
||||||
|
@ -12,14 +12,14 @@ babel==2.12.1 # via sphinx
|
|||||||
black==23.7.0 # via gray
|
black==23.7.0 # via gray
|
||||||
build==0.10.0 # via pip-tools
|
build==0.10.0 # via pip-tools
|
||||||
cachetools==5.3.1 # via tox
|
cachetools==5.3.1 # via tox
|
||||||
certifi==2023.5.7 # via requests
|
certifi==2023.7.22 # via requests
|
||||||
cfgv==3.3.1 # via pre-commit
|
cfgv==3.3.1 # via pre-commit
|
||||||
chardet==5.1.0 # via tox
|
chardet==5.1.0 # via tox
|
||||||
charset-normalizer==3.2.0 # via requests
|
charset-normalizer==3.2.0 # via requests
|
||||||
click==8.1.5 # via black, pip-tools
|
click==8.1.6 # via black, pip-tools
|
||||||
colorama==0.4.6 # via tox
|
colorama==0.4.6 # via tox
|
||||||
commonmark==0.9.1 # via rich
|
commonmark==0.9.1 # via rich
|
||||||
configargparse==1.5.5 # via gray
|
configargparse==1.7 # via gray
|
||||||
coverage[toml]==7.2.7 # via pytest-cov
|
coverage[toml]==7.2.7 # via pytest-cov
|
||||||
distlib==0.3.7 # via virtualenv
|
distlib==0.3.7 # via virtualenv
|
||||||
docutils==0.20.1 # via sphinx
|
docutils==0.20.1 # via sphinx
|
||||||
@ -28,7 +28,7 @@ filelock==3.12.2 # via tox, virtualenv
|
|||||||
fixit==0.1.4 # via gray
|
fixit==0.1.4 # via gray
|
||||||
flake8==6.0.0 # via -r dev-requirements.in, fixit, pep8-naming
|
flake8==6.0.0 # via -r dev-requirements.in, fixit, pep8-naming
|
||||||
gray==0.13.0 # via -r dev-requirements.in
|
gray==0.13.0 # via -r dev-requirements.in
|
||||||
identify==2.5.24 # via pre-commit
|
identify==2.5.26 # via pre-commit
|
||||||
idna==3.4 # via requests
|
idna==3.4 # via requests
|
||||||
imagesize==1.4.1 # via sphinx
|
imagesize==1.4.1 # via sphinx
|
||||||
importlib-resources==6.0.0 # via fixit
|
importlib-resources==6.0.0 # via fixit
|
||||||
@ -46,7 +46,7 @@ nodeenv==1.8.0 # via pre-commit
|
|||||||
packaging==23.1 # via black, build, pyproject-api, pytest, sphinx, tox
|
packaging==23.1 # via black, build, pyproject-api, pytest, sphinx, tox
|
||||||
pathspec==0.11.1 # via black
|
pathspec==0.11.1 # via black
|
||||||
pep8-naming==0.13.3 # via -r dev-requirements.in
|
pep8-naming==0.13.3 # via -r dev-requirements.in
|
||||||
pip-tools==7.0.0 # via -r dev-requirements.in
|
pip-tools==7.1.0 # via -r dev-requirements.in
|
||||||
platformdirs==3.9.1 # via black, tox, virtualenv
|
platformdirs==3.9.1 # via black, tox, virtualenv
|
||||||
pluggy==1.2.0 # via pytest, tox
|
pluggy==1.2.0 # via pytest, tox
|
||||||
pre-commit==3.3.3 # via -r dev-requirements.in
|
pre-commit==3.3.3 # via -r dev-requirements.in
|
||||||
@ -79,9 +79,9 @@ typing-extensions==4.7.1 # via libcst, mypy, typing-inspect
|
|||||||
typing-inspect==0.9.0 # via libcst
|
typing-inspect==0.9.0 # via libcst
|
||||||
unify==0.5 # via gray
|
unify==0.5 # via gray
|
||||||
untokenize==0.1.1 # via unify
|
untokenize==0.1.1 # via unify
|
||||||
urllib3==2.0.3 # via requests
|
urllib3==2.0.4 # via requests
|
||||||
virtualenv==20.24.0 # via pre-commit, tox
|
virtualenv==20.24.1 # via pre-commit, tox
|
||||||
wheel==0.40.0 # via pip-tools
|
wheel==0.41.0 # via pip-tools
|
||||||
|
|
||||||
# The following packages are considered to be unsafe in a requirements file:
|
# The following packages are considered to be unsafe in a requirements file:
|
||||||
# pip
|
# pip
|
||||||
|
@ -13,6 +13,8 @@ if [ ! -z "${APRSD_PLUGINS}" ]; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
pip3 install gevent uwsgi
|
||||||
|
|
||||||
if [ -z "${LOG_LEVEL}" ] || [[ ! "${LOG_LEVEL}" =~ ^(CRITICAL|ERROR|WARNING|INFO)$ ]]; then
|
if [ -z "${LOG_LEVEL}" ] || [[ ! "${LOG_LEVEL}" =~ ^(CRITICAL|ERROR|WARNING|INFO)$ ]]; then
|
||||||
LOG_LEVEL="DEBUG"
|
LOG_LEVEL="DEBUG"
|
||||||
fi
|
fi
|
||||||
@ -28,5 +30,6 @@ fi
|
|||||||
|
|
||||||
export COLUMNS=200
|
export COLUMNS=200
|
||||||
#exec gunicorn -b :8000 --workers 4 "aprsd.admin_web:create_app(config_file='$APRSD_CONFIG', log_level='$LOG_LEVEL')"
|
#exec gunicorn -b :8000 --workers 4 "aprsd.admin_web:create_app(config_file='$APRSD_CONFIG', log_level='$LOG_LEVEL')"
|
||||||
exec gunicorn -b :8000 --workers 4 "aprsd.wsgi:app"
|
# exec gunicorn -b :8000 --workers 4 "aprsd.wsgi:app"
|
||||||
|
exec uwsgi --http :8000 --gevent 1000 --http-websockets --master -w aprsd.wsgi --callable app
|
||||||
#exec aprsd listen -c $APRSD_CONFIG --loglevel ${LOG_LEVEL} ${APRSD_LOAD_PLUGINS} ${APRSD_LISTEN_FILTER}
|
#exec aprsd listen -c $APRSD_CONFIG --loglevel ${LOG_LEVEL} ${APRSD_LOAD_PLUGINS} ${APRSD_LISTEN_FILTER}
|
||||||
|
@ -15,6 +15,8 @@ six
|
|||||||
thesmuggler
|
thesmuggler
|
||||||
update_checker
|
update_checker
|
||||||
flask-socketio
|
flask-socketio
|
||||||
|
python-socketio
|
||||||
|
gevent
|
||||||
eventlet
|
eventlet
|
||||||
tabulate
|
tabulate
|
||||||
# Pinned due to gray needing 12.6.0
|
# Pinned due to gray needing 12.6.0
|
||||||
|
@ -10,12 +10,12 @@ attrs==23.1.0 # via -r requirements.in, ax253, kiss3, rush
|
|||||||
ax253==0.1.5.post1 # via kiss3
|
ax253==0.1.5.post1 # via kiss3
|
||||||
beautifulsoup4==4.12.2 # via -r requirements.in
|
beautifulsoup4==4.12.2 # via -r requirements.in
|
||||||
bidict==0.22.1 # via python-socketio
|
bidict==0.22.1 # via python-socketio
|
||||||
bitarray==2.7.6 # via ax253, kiss3
|
bitarray==2.8.0 # via ax253, kiss3
|
||||||
blinker==1.6.2 # via flask
|
blinker==1.6.2 # via flask
|
||||||
certifi==2023.5.7 # via httpcore, requests
|
certifi==2023.7.22 # via httpcore, requests
|
||||||
cffi==1.15.1 # via cryptography
|
cffi==1.15.1 # via cryptography
|
||||||
charset-normalizer==3.2.0 # via requests
|
charset-normalizer==3.2.0 # via requests
|
||||||
click==8.1.5 # via -r requirements.in, click-completion, click-params, flask
|
click==8.1.6 # via -r requirements.in, click-completion, click-params, flask
|
||||||
click-completion==0.5.2 # via -r requirements.in
|
click-completion==0.5.2 # via -r requirements.in
|
||||||
click-params==0.4.1 # via -r requirements.in
|
click-params==0.4.1 # via -r requirements.in
|
||||||
commonmark==0.9.1 # via rich
|
commonmark==0.9.1 # via rich
|
||||||
@ -32,7 +32,8 @@ flask-httpauth==4.8.0 # via -r requirements.in
|
|||||||
flask-socketio==5.3.4 # via -r requirements.in
|
flask-socketio==5.3.4 # via -r requirements.in
|
||||||
geographiclib==2.0 # via geopy
|
geographiclib==2.0 # via geopy
|
||||||
geopy==2.3.0 # via -r requirements.in
|
geopy==2.3.0 # via -r requirements.in
|
||||||
greenlet==2.0.2 # via eventlet
|
gevent==23.7.0 # via -r requirements.in
|
||||||
|
greenlet==2.0.2 # via eventlet, gevent
|
||||||
h11==0.14.0 # via httpcore
|
h11==0.14.0 # via httpcore
|
||||||
httpcore==0.17.3 # via dnspython
|
httpcore==0.17.3 # via dnspython
|
||||||
idna==3.4 # via anyio, requests
|
idna==3.4 # via anyio, requests
|
||||||
@ -54,7 +55,7 @@ pyopenssl==23.2.0 # via -r requirements.in
|
|||||||
pyserial==3.5 # via pyserial-asyncio
|
pyserial==3.5 # via pyserial-asyncio
|
||||||
pyserial-asyncio==0.6 # via kiss3
|
pyserial-asyncio==0.6 # via kiss3
|
||||||
python-engineio==4.5.1 # via python-socketio
|
python-engineio==4.5.1 # via python-socketio
|
||||||
python-socketio==5.8.0 # via flask-socketio
|
python-socketio==5.8.0 # via -r requirements.in, flask-socketio
|
||||||
pytz==2023.3 # via -r requirements.in
|
pytz==2023.3 # via -r requirements.in
|
||||||
pyyaml==6.0.1 # via -r requirements.in, oslo-config
|
pyyaml==6.0.1 # via -r requirements.in, oslo-config
|
||||||
requests==2.31.0 # via -r requirements.in, oslo-config, update-checker
|
requests==2.31.0 # via -r requirements.in, oslo-config, update-checker
|
||||||
@ -71,9 +72,14 @@ tabulate==0.9.0 # via -r requirements.in
|
|||||||
thesmuggler==1.0.1 # via -r requirements.in
|
thesmuggler==1.0.1 # via -r requirements.in
|
||||||
ua-parser==0.18.0 # via user-agents
|
ua-parser==0.18.0 # via user-agents
|
||||||
update-checker==0.18.0 # via -r requirements.in
|
update-checker==0.18.0 # via -r requirements.in
|
||||||
urllib3==2.0.3 # via requests
|
urllib3==2.0.4 # via requests
|
||||||
user-agents==2.2.0 # via -r requirements.in
|
user-agents==2.2.0 # via -r requirements.in
|
||||||
validators==0.20.0 # via click-params
|
validators==0.20.0 # via click-params
|
||||||
werkzeug==2.3.6 # via -r requirements.in, flask
|
werkzeug==2.3.6 # via -r requirements.in, flask
|
||||||
wrapt==1.15.0 # via -r requirements.in, debtcollector
|
wrapt==1.15.0 # via -r requirements.in, debtcollector
|
||||||
zipp==3.16.2 # via importlib-metadata
|
zipp==3.16.2 # via importlib-metadata
|
||||||
|
zope-event==5.0 # via gevent
|
||||||
|
zope-interface==6.0 # via gevent
|
||||||
|
|
||||||
|
# The following packages are considered to be unsafe in a requirements file:
|
||||||
|
# setuptools
|
||||||
|
Loading…
Reference in New Issue
Block a user