summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolargo <nicolas@nicolargo.com>2014-07-06 20:49:02 +0200
committerNicolargo <nicolas@nicolargo.com>2014-07-06 20:49:02 +0200
commit2749e967bbbf30f1326705335af9887bb947f72f (patch)
tree11cbb5c8c864cf7c91187ac09155a87cabdba2bd
parente0d9fe530d59236b413dacee304240ba9e13e37d (diff)
First version of the RESTFULL API
-rw-r--r--glances/outputs/glances_bottle.py67
-rw-r--r--glances/plugins/glances_plugin.py42
2 files changed, 106 insertions, 3 deletions
diff --git a/glances/outputs/glances_bottle.py b/glances/outputs/glances_bottle.py
index 2e34c9b9..c513e9e8 100644
--- a/glances/outputs/glances_bottle.py
+++ b/glances/outputs/glances_bottle.py
@@ -27,11 +27,12 @@ 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
except ImportError:
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):
@@ -82,12 +83,21 @@ 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/pluginslist', method="GET", callback=self._api_plugins)
+ self._app.route('/api/:plugin', method="GET", callback=self._api)
+ self._app.route('/api/:plugin/:item', method="GET", callback=self._api_item)
+ self._app.route('/api/:plugin/:item/:value', method="GET", callback=self._api_value)
def start(self, stats):
"""Start the bottle."""
# Init stats
self.stats = stats
+ # Init plugin list
+ self.plugins_list = self.stats.getAllPlugins()
+
+ # Bind the Bottle TCP address/port
bindmsg = _("Glances web server started on http://{}:{}/").format(self.args.bind_address, self.args.port)
logger.info(bindmsg)
print(bindmsg)
@@ -119,6 +129,61 @@ class GlancesBottle(object):
# Return the static file
return static_file(filename, root=os.path.join(self.STATIC_PATH, 'js'))
+ def _api_plugins(self):
+ """
+ Glances API RESTFULL implementation
+ Return the plugin list
+ or 404 error
+ """
+ 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(self, plugin):
+ """
+ Glances API RESTFULL implementation
+ Return the JSON representation of a given plugin
+ or 404 error
+ """
+ if plugin not in self.plugins_list:
+ abort(404, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list))
+ 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_item(self, plugin, item):
+ """
+ Glances API RESTFULL implementation
+ Return the JSON represenation of the couple plugin/item
+ or 404 error
+ """
+ if plugin not in self.plugins_list:
+ abort(404, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list))
+ 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 RESTFULL implementation
+ Return the process stats (dict) for the given item=value
+ or 404 error
+ """
+ if plugin not in self.plugins_list:
+ abort(404, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list))
+ 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.
diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py
index a78d5986..4ed3d61b 100644
--- a/glances/plugins/glances_plugin.py
+++ b/glances/plugins/glances_plugin.py
@@ -25,9 +25,10 @@ I am your father...
# Import system libs
import json
+from operator import itemgetter
# Import Glances lib
-from glances.core.glances_globals import glances_logs
+from glances.core.glances_globals import glances_logs, logger
class GlancesPlugin(object):
@@ -146,9 +147,46 @@ class GlancesPlugin(object):
return self.stats
def get_stats(self):
- """Return the stats object in JSON format for the XML-RPC API."""
+ """Return the stats object in JSON format"""
return json.dumps(self.stats)
+ def get_stats_item(self, item):
+ """
+ Return the stats object for a specific item (in JSON format)
+ Stats should be a list of dict (processlist, network...)
+ """
+ if type(self.stats) is not list:
+ if type(self.stats) is dict:
+ try:
+ return json.dumps(self.stats[item])
+ except KeyError as e:
+ logger.error(_("Can not get item %s (%s)") % (item, e))
+ else:
+ return None
+ else:
+ try:
+ # Source: http://stackoverflow.com/questions/4573875/python-get-index-of-dictionary-item-in-list
+ return json.dumps(map(itemgetter(item), self.stats))
+ except (KeyError, ValueError) as e:
+ logger.error(_("Can not get item %s (%s)") % (item, e))
+ return None
+
+ def get_stats_value(self, item, value):
+ """
+ Return the stats object for a specific item=value (in JSON format)
+ Stats should be a list of dict (processlist, network...)
+ """
+ if type(self.stats) is not list:
+ return None
+ else:
+ if value.isdigit():
+ value = int(value)
+ try:
+ return json.dumps([i for i in self.stats if i[item] == value])
+ except (KeyError, ValueError) as e:
+ logger.error(_("Can not get item(%s)=value(%s) (%s)") % (item, value,e))
+ return None
+
def load_limits(self, config):
"""Load the limits from the configuration file."""
if (hasattr(config, 'has_section') and