summaryrefslogtreecommitdiffstats
path: root/glances/outputs/glances_restful_api.py
diff options
context:
space:
mode:
Diffstat (limited to 'glances/outputs/glances_restful_api.py')
-rw-r--r--glances/outputs/glances_restful_api.py63
1 files changed, 55 insertions, 8 deletions
diff --git a/glances/outputs/glances_restful_api.py b/glances/outputs/glances_restful_api.py
index ca8da563..b65f77d1 100644
--- a/glances/outputs/glances_restful_api.py
+++ b/glances/outputs/glances_restful_api.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# SPDX-FileCopyrightText: 2023 Nicolas Hennion <nicolas@nicolargo.com>
+# SPDX-FileCopyrightText: 2024 Nicolas Hennion <nicolas@nicolargo.com>
#
# SPDX-License-Identifier: LGPL-3.0-only
#
@@ -14,7 +14,6 @@ import sys
import tempfile
from io import open
import webbrowser
-import socket
from urllib.parse import urljoin
# Replace typing_extensions by typing when Python 3.8 support will be dropped
@@ -43,10 +42,37 @@ try:
except ImportError:
logger.critical('Uvicorn import error. Glances cannot start in web server mode.')
sys.exit(2)
+import contextlib
+import threading
+import time
security = HTTPBasic()
+class GlancesUvicornServer(uvicorn.Server):
+ def install_signal_handlers(self):
+ pass
+
+ @contextlib.contextmanager
+ def run_in_thread(self, timeout=3):
+ thread = threading.Thread(target=self.run)
+ thread.start()
+ try:
+ chrono = Timer(timeout)
+ while not self.started and not chrono.finished():
+ time.sleep(0.5)
+ # Timeout reached
+ # Something go wrong...
+ # The Uvicorn server should be stopped
+ if not self.started:
+ self.should_exit = True
+ thread.join()
+ yield
+ finally:
+ self.should_exit = True
+ thread.join()
+
+
class GlancesRestfulApi(object):
"""This class manages the Restful API server."""
@@ -88,8 +114,13 @@ class GlancesRestfulApi(object):
self._app.include_router(APIRouter(prefix=self.url_prefix.rstrip('/')))
# Set path for WebUI
- self.STATIC_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static/public')
- self.TEMPLATE_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static/templates')
+ webui_root_path = config.get_value(
+ 'outputs', 'webui_root_path', default=os.path.dirname(os.path.realpath(__file__))
+ )
+ if webui_root_path == '':
+ webui_root_path = os.path.dirname(os.path.realpath(__file__))
+ self.STATIC_PATH = os.path.join(webui_root_path, 'static/public')
+ self.TEMPLATE_PATH = os.path.join(webui_root_path, 'static/templates')
self._templates = Jinja2Templates(directory=self.TEMPLATE_PATH)
# FastAPI Enable CORS
@@ -245,6 +276,8 @@ class GlancesRestfulApi(object):
# Statics files
self._app.mount("/static", StaticFiles(directory=self.STATIC_PATH), name="static")
+ logger.info("Get WebUI in {}".format(self.STATIC_PATH))
+
bindmsg = 'Glances Web User Interface started on {}'.format(self.bind_url)
else:
bindmsg = 'The WebUI is disable (--disable-webui)'
@@ -269,11 +302,23 @@ class GlancesRestfulApi(object):
# 2) Glances standalone mode is running on Windows OS
webbrowser.open(self.bind_url, new=2, autoraise=1)
- # Run the Web application
+ # Start Uvicorn server
+ self._start_uvicorn()
+
+ def _start_uvicorn(self):
+ # Run the Uvicorn Web server
+ uvicorn_config = uvicorn.Config(
+ self._app, host=self.args.bind_address, port=self.args.port, access_log=self.args.debug
+ )
try:
- uvicorn.run(self._app, host=self.args.bind_address, port=self.args.port, access_log=self.args.debug)
- except socket.error as e:
+ self.uvicorn_server = GlancesUvicornServer(config=uvicorn_config)
+ except Exception as e:
logger.critical('Error: Can not ran Glances Web server ({})'.format(e))
+ self.uvicorn_server = None
+ else:
+ with self.uvicorn_server.run_in_thread():
+ while not self.uvicorn_server.should_exit:
+ time.sleep(1)
def end(self):
"""End the Web server"""
@@ -467,12 +512,14 @@ class GlancesRestfulApi(object):
try:
# Get the RAW value of the stat ID
- statval = self.stats.get_plugin(plugin).get_export()
+ statval = self.stats.get_plugin(plugin).get_raw()
except Exception as e:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin %s (%s)" % (plugin, str(e))
)
+ print(statval)
+
if isinstance(statval, list):
statval = statval[:nb]