diff options
author | Nicolas Hennion <nicolas@nicolargo.com> | 2014-07-07 15:54:26 +0200 |
---|---|---|
committer | Nicolas Hennion <nicolas@nicolargo.com> | 2014-07-07 15:54:26 +0200 |
commit | 09ec93a9d96ca3e7a471423b326c5dbfeccd5780 (patch) | |
tree | 28852a6c732fa9b3bb232cccb84da0a084d23982 | |
parent | 2749e967bbbf30f1326705335af9887bb947f72f (diff) |
Add methods to the Restfull/API
-rw-r--r-- | docs/glances-doc.rst | 13 | ||||
-rw-r--r-- | glances/core/glances_stats.py | 12 | ||||
-rw-r--r-- | glances/outputs/glances_bottle.py | 78 | ||||
-rw-r--r-- | glances/plugins/glances_plugin.py | 6 |
4 files changed, 88 insertions, 21 deletions
diff --git a/docs/glances-doc.rst b/docs/glances-doc.rst index c41e49d0..f6dfa97b 100644 --- a/docs/glances-doc.rst +++ b/docs/glances-doc.rst @@ -592,13 +592,15 @@ CSV files have two lines per stats: - Stats description - Stats (comma separated) -API Documentation -================= +APIs Documentations +=================== + +Glances includes a `XML-RPC server`_ and a `RESTFULL-JSON`_ API which and can be used by another client software. -Glances uses a `XML-RPC server`_ and can be used by another client software. +APIs documentations are available at: -API documentation is available at -https://github.com/nicolargo/glances/wiki/The-Glances-2.x-API-How-to. +- XML-RPC: https://github.com/nicolargo/glances/wiki/The-Glances-2.x-API-How-to +- RESTFULL-JSON: https://github.com/nicolargo/glances/wiki/The-Glances-RESTFULL-JSON-API Support ======= @@ -614,3 +616,4 @@ Feel free to contribute! .. _psutil: https://code.google.com/p/psutil/ .. _XML-RPC server: http://docs.python.org/2/library/simplexmlrpcserver.html +.. _RESTFULL-JSON: http://jsonapi.org/
\ No newline at end of file diff --git a/glances/core/glances_stats.py b/glances/core/glances_stats.py index 5cb1d521..6b282692 100644 --- a/glances/core/glances_stats.py +++ b/glances/core/glances_stats.py @@ -127,9 +127,13 @@ class GlancesStats(object): self.__update__(input_stats) def getAll(self): - """Return all the stats.""" + """Return all the stats (list)""" return [self._plugins[p].get_raw() for p in self._plugins] + def getAllAsDict(self): + """Return all the stats (dict)""" + return {p: self._plugins[p].get_raw() for p in self._plugins} + def get_plugin_list(self): """Return the plugin list.""" self._plugins @@ -163,9 +167,13 @@ class GlancesStatsServer(GlancesStats): self.all_stats[p] = self._plugins[p].get_raw() def getAll(self): - """Return the stats as a dict.""" + """Return the stats as a list""" return self.all_stats + def getAllAsDict(self): + """Return the stats as a dict""" + return {p: self.all_stats[p] for p in self._plugins} + def getAllPlugins(self): """Return the plugins list.""" return [p for p in self._plugins] diff --git a/glances/outputs/glances_bottle.py b/glances/outputs/glances_bottle.py index c513e9e8..f96e9e75 100644 --- a/glances/outputs/glances_bottle.py +++ b/glances/outputs/glances_bottle.py @@ -27,7 +27,7 @@ from glances.core.glances_globals import logger # Import mandatory Bottle lib try: - from bottle import Bottle, template, static_file, TEMPLATE_PATH, abort + from bottle import Bottle, template, static_file, TEMPLATE_PATH, abort, response except ImportError: logger.critical('Bottle module not found. Glances cannot start in web server mode.') print(_("Install it using pip: # pip install bottle")) @@ -84,10 +84,11 @@ class GlancesBottle(object): 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) + 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/: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.""" @@ -109,6 +110,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 @@ -121,11 +123,13 @@ 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')) @@ -135,20 +139,53 @@ class GlancesBottle(object): Return the plugin list or 404 error """ + response.content_type = 'application/vnd.api+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 RESTFULL 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/vnd.api+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 RESTFULL implementation Return the JSON representation of a given plugin - or 404 error + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error """ + response.content_type = 'application/vnd.api+json' + if plugin not in self.plugins_list: - abort(404, "Unknown plugin %s (available plugins: %s)" % (plugin, 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() @@ -160,11 +197,21 @@ class GlancesBottle(object): """ Glances API RESTFULL implementation Return the JSON represenation of the couple plugin/item - or 404 error + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error + """ + response.content_type = 'application/vnd.api+json' + if plugin not in self.plugins_list: - abort(404, "Unknown plugin %s (available plugins: %s)" % (plugin, 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: @@ -174,11 +221,20 @@ class GlancesBottle(object): """ Glances API RESTFULL implementation Return the process stats (dict) for the given item=value - or 404 error + HTTP/200 if OK + HTTP/400 if plugin is not found + HTTP/404 if others error """ + response.content_type = 'application/vnd.api+json' + if plugin not in self.plugins_list: - abort(404, "Unknown plugin %s (available plugins: %s)" % (plugin, 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: diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index 4ed3d61b..c0189f24 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -158,7 +158,7 @@ class GlancesPlugin(object): if type(self.stats) is not list: if type(self.stats) is dict: try: - return json.dumps(self.stats[item]) + return json.dumps({ item: self.stats[item] }) except KeyError as e: logger.error(_("Can not get item %s (%s)") % (item, e)) else: @@ -166,7 +166,7 @@ class GlancesPlugin(object): else: try: # Source: http://stackoverflow.com/questions/4573875/python-get-index-of-dictionary-item-in-list - return json.dumps(map(itemgetter(item), self.stats)) + return json.dumps({ item: map(itemgetter(item), self.stats) }) except (KeyError, ValueError) as e: logger.error(_("Can not get item %s (%s)") % (item, e)) return None @@ -182,7 +182,7 @@ class GlancesPlugin(object): if value.isdigit(): value = int(value) try: - return json.dumps([i for i in self.stats if i[item] == value]) + return json.dumps({ value: [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 |