diff options
Diffstat (limited to 'glances/outputs/glances_bottle.py')
-rw-r--r-- | glances/outputs/glances_bottle.py | 162 |
1 files changed, 158 insertions, 4 deletions
diff --git a/glances/outputs/glances_bottle.py b/glances/outputs/glances_bottle.py index fb3c7570..da95af15 100644 --- a/glances/outputs/glances_bottle.py +++ b/glances/outputs/glances_bottle.py @@ -22,11 +22,17 @@ import os import sys +# Import Glances libs +from glances.core.glances_globals import logger + +# Import mandatory Bottle lib try: - from bottle import Bottle, template, static_file, TEMPLATE_PATH + from bottle import Bottle, template, static_file, TEMPLATE_PATH, abort, response except ImportError: - print('Bottle module not found. Glances cannot start in web server mode.') - sys.exit(1) + logger.critical('Bottle module not found. Glances cannot start in web server mode.') + print(_("Install it using pip: # pip install bottle")) + sys.exit(2) +import json class GlancesBottle(object): @@ -58,6 +64,7 @@ class GlancesBottle(object): 'BOLD': 'bold', 'SORT': 'sort', 'OK': 'ok', + 'FILTER': 'filter', 'TITLE': 'title', 'CAREFUL': 'careful', 'WARNING': 'warning', @@ -77,13 +84,27 @@ class GlancesBottle(object): self._app.route('/<refresh_time:int>', method=["GET", "POST"], callback=self._index) self._app.route('/<filename:re:.*\.css>', method="GET", callback=self._css) self._app.route('/<filename:re:.*\.js>', method="GET", callback=self._js) + # REST API + self._app.route('/api/2/pluginslist', method="GET", callback=self._api_plugins) + self._app.route('/api/2/all', method="GET", callback=self._api_all) + self._app.route('/api/2/:plugin', method="GET", callback=self._api) + self._app.route('/api/2/:plugin/limits', method="GET", callback=self._api_limits) + self._app.route('/api/2/:plugin/:item', method="GET", callback=self._api_item) + self._app.route('/api/2/:plugin/:item/:value', method="GET", callback=self._api_value) def start(self, stats): """Start the bottle.""" # Init stats self.stats = stats - self._app.run(host=self.args.bind_address, port=self.args.port) + # Init plugin list + self.plugins_list = self.stats.getAllPlugins() + + # Bind the Bottle TCP address/port + bindmsg = _("Glances web server started on http://{0}:{1}/").format(self.args.bind_address, self.args.port) + logger.info(bindmsg) + print(bindmsg) + self._app.run(host=self.args.bind_address, port=self.args.port, quiet=not self.args.debug) def end(self): """End the bottle.""" @@ -91,6 +112,7 @@ class GlancesBottle(object): def _index(self, refresh_time=None): """Bottle callback for index.html (/) file.""" + response.content_type = 'text/html' # Manage parameter if refresh_time is None: refresh_time = self.args.time @@ -103,14 +125,146 @@ class GlancesBottle(object): def _css(self, filename): """Bottle callback for *.css files.""" + response.content_type = 'text/html' # Return the static file return static_file(filename, root=os.path.join(self.STATIC_PATH, 'css')) def _js(self, filename): """Bottle callback for *.js files.""" + response.content_type = 'text/html' # Return the static file return static_file(filename, root=os.path.join(self.STATIC_PATH, 'js')) + def _api_plugins(self): + """ + Glances API RESTFul implementation + Return the plugin list + or 404 error + """ + response.content_type = 'application/json' + + # Update the stat + self.stats.update() + + try: + plist = json.dumps(self.plugins_list) + except Exception as e: + abort(404, "Can not get plugin list (%s)" % str(e)) + return plist + + def _api_all(self): + """ + Glances API RESTFul implementation + Return the JSON representation of all the plugins + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error + """ + response.content_type = 'application/json' + + # Update the stat + self.stats.update() + + try: + # Get the JSON value of the stat ID + statval = json.dumps(self.stats.getAllAsDict()) + except Exception as e: + abort(404, "Can not get stats (%s)" % str(e)) + return statval + + def _api(self, plugin): + """ + Glances API RESTFul implementation + Return the JSON representation of a given plugin + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error + """ + response.content_type = 'application/json' + + if plugin not in self.plugins_list: + abort(400, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list)) + + # Update the stat + self.stats.update() + + try: + # Get the JSON value of the stat ID + statval = self.stats.get_plugin(plugin).get_stats() + except Exception as e: + abort(404, "Can not get plugin %s (%s)" % (plugin, str(e))) + return statval + + def _api_limits(self, plugin): + """ + Glances API RESTFul implementation + Return the JSON limits of a given plugin + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error + """ + response.content_type = 'application/json' + + if plugin not in self.plugins_list: + abort(400, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list)) + + # Update the stat + # self.stats.update() + + try: + # Get the JSON value of the stat ID + limits = self.stats.get_plugin(plugin).get_limits() + except Exception as e: + abort(404, "Can not get limits for plugin %s (%s)" % (plugin, str(e))) + return limits + + def _api_item(self, plugin, item): + """ + Glances API RESTFul implementation + Return the JSON represenation of the couple plugin/item + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error + + """ + response.content_type = 'application/json' + + if plugin not in self.plugins_list: + abort(400, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list)) + + # Update the stat + self.stats.update() + + plist = self.stats.get_plugin(plugin).get_stats_item(item) + + if plist is None: + abort(404, "Can not get item %s in plugin %s" % (item, plugin)) + else: + return plist + + def _api_value(self, plugin, item, value): + """ + Glances API RESTFul implementation + Return the process stats (dict) for the given item=value + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error + """ + response.content_type = 'application/json' + + if plugin not in self.plugins_list: + abort(400, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list)) + + # Update the stat + self.stats.update() + + pdict = self.stats.get_plugin(plugin).get_stats_value(item, value) + + if pdict is None: + abort(404, "Can not get item(%s)=value(%s) in plugin %s" % (item, value, plugin)) + else: + return pdict + def display(self, stats, refresh_time=None): """Display stats on the web page. |