summaryrefslogtreecommitdiffstats
path: root/glances/outputs/glances_bottle.py
diff options
context:
space:
mode:
Diffstat (limited to 'glances/outputs/glances_bottle.py')
-rw-r--r--glances/outputs/glances_bottle.py162
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.