summaryrefslogtreecommitdiffstats
path: root/glances
diff options
context:
space:
mode:
Diffstat (limited to 'glances')
-rw-r--r--glances/__init__.py10
-rw-r--r--glances/autodiscover.py5
-rw-r--r--glances/client.py10
-rw-r--r--glances/client_browser.py6
-rw-r--r--glances/config.py15
-rw-r--r--glances/exports/glances_riemann.py92
-rw-r--r--glances/globals.py5
-rw-r--r--glances/main.py11
-rw-r--r--glances/outputs/glances_bottle.py51
-rw-r--r--glances/outputs/glances_curses.py252
-rw-r--r--glances/outputs/glances_curses_browser.py273
-rw-r--r--glances/password.py5
-rw-r--r--glances/plugins/glances_help.py4
-rw-r--r--glances/plugins/glances_psutilversion.py6
-rw-r--r--glances/plugins/glances_sensors.py2
-rw-r--r--glances/processes.py197
-rw-r--r--glances/processes_tree.py217
-rw-r--r--glances/server.py6
-rw-r--r--glances/static_list.py2
-rw-r--r--glances/stats.py173
-rw-r--r--glances/stats_client.py68
-rw-r--r--glances/stats_client_snmp.py109
-rw-r--r--glances/stats_server.py68
23 files changed, 904 insertions, 683 deletions
diff --git a/glances/__init__.py b/glances/__init__.py
index c937e820..e381f305 100644
--- a/glances/__init__.py
+++ b/glances/__init__.py
@@ -27,13 +27,13 @@ import sys
# Global name
__appname__ = 'glances'
-__version__ = '2.6'
+__version__ = '2.6.1'
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
__license__ = 'LGPL'
# Import psutil
try:
- from psutil import __version__ as __psutil_version
+ from psutil import __version__ as psutil_version
except ImportError:
print('PSutil library not found. Glances cannot start.')
sys.exit(1)
@@ -62,8 +62,8 @@ if sys.version_info[:2] == (2, 6):
# Check PSutil version
psutil_min_version = (2, 0, 0)
-psutil_version = tuple([int(num) for num in __psutil_version.split('.')])
-if psutil_version < psutil_min_version:
+psutil_version_info = tuple([int(num) for num in psutil_version.split('.')])
+if psutil_version_info < psutil_min_version:
print('PSutil 2.0 or higher is needed. Glances cannot start.')
sys.exit(1)
@@ -107,7 +107,7 @@ def main():
logger.info('{0} {1} and PSutil {2} detected'.format(
platform.python_implementation(),
platform.python_version(),
- __psutil_version))
+ psutil_version))
# Share global var
global core, standalone, client, server, webserver
diff --git a/glances/autodiscover.py b/glances/autodiscover.py
index fa1414d4..b2f2fcb9 100644
--- a/glances/autodiscover.py
+++ b/glances/autodiscover.py
@@ -22,7 +22,8 @@
import socket
import sys
-from glances.globals import appname, BSD
+from glances import __appname__
+from glances.globals import BSD
from glances.logger import logger
try:
@@ -46,7 +47,7 @@ if zeroconf_tag:
sys.exit(1)
# Global var
-zeroconf_type = "_%s._tcp." % appname
+zeroconf_type = "_%s._tcp." % __appname__
class AutoDiscovered(object):
diff --git a/glances/client.py b/glances/client.py
index 2dc33bed..a1e68e0b 100644
--- a/glances/client.py
+++ b/glances/client.py
@@ -23,10 +23,10 @@ import json
import socket
import sys
+from glances import __version__
from glances.compat import Fault, ProtocolError, ServerProxy, Transport
-from glances.globals import version
from glances.logger import logger
-from glances.stats import GlancesStatsClient
+from glances.stats_client import GlancesStatsClient
from glances.outputs.glances_curses import GlancesCursesClient
@@ -122,11 +122,11 @@ class GlancesClient(object):
if self.client_mode == 'glances':
# Check that both client and server are in the same major version
- if version.split('.')[0] == client_version.split('.')[0]:
+ if __version__.split('.')[0] == client_version.split('.')[0]:
# Init stats
self.stats = GlancesStatsClient(config=self.config, args=self.args)
self.stats.set_plugins(json.loads(self.client.getAllPlugins()))
- logger.debug("Client version: {0} / Server version: {1}".format(version, client_version))
+ logger.debug("Client version: {0} / Server version: {1}".format(__version__, client_version))
else:
self.log_and_exit("Client and server not compatible: \
Client version: {0} / Server version: {1}".format(version, client_version))
@@ -139,7 +139,7 @@ class GlancesClient(object):
if self.client_mode == 'snmp':
logger.info("Trying to grab stats by SNMP...")
- from glances.stats import GlancesStatsClientSNMP
+ from glances.stats_client_snmp import GlancesStatsClientSNMP
# Init stats
self.stats = GlancesStatsClientSNMP(config=self.config, args=self.args)
diff --git a/glances/client_browser.py b/glances/client_browser.py
index cfcf01a2..ef1348d0 100644
--- a/glances/client_browser.py
+++ b/glances/client_browser.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# Copyright (C) 2015 Nicolargo <nicolas@nicolargo.com>
+# Copyright (C) 2016 Nicolargo <nicolas@nicolargo.com>
#
# Glances is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
@@ -28,7 +28,7 @@ from glances.client import GlancesClient, GlancesClientTransport
from glances.logger import logger
from glances.password_list import GlancesPasswordList as GlancesPassword
from glances.static_list import GlancesStaticServer
-from glances.outputs.glances_curses import GlancesCursesBrowser
+from glances.outputs.glances_curses_browser import GlancesCursesBrowser
class GlancesClientBrowser(object):
@@ -160,7 +160,7 @@ class GlancesClientBrowser(object):
"Server list dictionnary change inside the loop (wait next update)")
# Update the screen (list or Glances client)
- if not self.screen.active_server:
+ if self.screen.active_server is None:
# Display the Glances browser
self.screen.update(self.get_servers_list())
else:
diff --git a/glances/config.py b/glances/config.py
index 3e8570ea..8c53a9ca 100644
--- a/glances/config.py
+++ b/glances/config.py
@@ -23,8 +23,9 @@ import os
import sys
from io import open
+from glances import __appname__
from glances.compat import ConfigParser, NoOptionError
-from glances.globals import appname, BSD, LINUX, OSX, WINDOWS, sys_prefix
+from glances.globals import BSD, LINUX, OSX, WINDOWS, sys_prefix
from glances.logger import logger
@@ -69,22 +70,22 @@ class Config(object):
paths.append(
os.path.join(os.environ.get('XDG_CONFIG_HOME') or
os.path.expanduser('~/.config'),
- appname, self.config_filename))
+ __appname__, self.config_filename))
if BSD:
paths.append(
- os.path.join(sys.prefix, 'etc', appname, self.config_filename))
+ os.path.join(sys.prefix, 'etc', __appname__, self.config_filename))
else:
paths.append(
- os.path.join('/etc', appname, self.config_filename))
+ os.path.join('/etc', __appname__, self.config_filename))
elif OSX:
paths.append(
os.path.join(os.path.expanduser('~/Library/Application Support/'),
- appname, self.config_filename))
+ __appname__, self.config_filename))
paths.append(
- os.path.join(sys_prefix, 'etc', appname, self.config_filename))
+ os.path.join(sys_prefix, 'etc', __appname__, self.config_filename))
elif WINDOWS:
paths.append(
- os.path.join(os.environ.get('APPDATA'), appname, self.config_filename))
+ os.path.join(os.environ.get('APPDATA'), __appname__, self.config_filename))
return paths
diff --git a/glances/exports/glances_riemann.py b/glances/exports/glances_riemann.py
new file mode 100644
index 00000000..a6ec1465
--- /dev/null
+++ b/glances/exports/glances_riemann.py
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of Glances.
+#
+# Copyright (C) 2016 Nicolargo <nicolas@nicolargo.com>
+#
+# Glances is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Glances is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""Riemann interface class."""
+
+import socket
+import sys
+from numbers import Number
+
+from glances.compat import NoOptionError, NoSectionError, range
+from glances.logger import logger
+from glances.exports.glances_export import GlancesExport
+
+# Import pika for Riemann
+import bernhard
+
+
+class Export(GlancesExport):
+
+ """This class manages the Riemann export module."""
+
+ def __init__(self, config=None, args=None):
+ """Init the Riemann export IF."""
+ super(Export, self).__init__(config=config, args=args)
+
+ # Load the rabbitMQ configuration file
+ self.riemann_host = None
+ self.riemann_port = None
+ self.hostname = socket.gethostname()
+ self.export_enable = self.load_conf()
+ if not self.export_enable:
+ sys.exit(2)
+
+ # Init the rabbitmq client
+ self.client = self.init()
+
+ def load_conf(self, section="riemann"):
+ """Load the Riemann configuration in the Glances configuration file."""
+ if self.config is None:
+ return False
+ try:
+ self.riemann_host = self.config.get_value(section, 'host')
+ self.riemann_port = int(self.config.get_value(section, 'port'))
+ except NoSectionError:
+ logger.critical("No riemann configuration found")
+ return False
+ except NoOptionError as e:
+ logger.critical("Error in the Riemann configuration (%s)" % e)
+ return False
+ else:
+ logger.debug("Load Riemann from the Glances configuration file")
+ return True
+
+ def init(self):
+ """Init the connection to the Riemann server."""
+ if not self.export_enable:
+ return None
+ try:
+ client = bernhard.Client(host=self.riemann_host, port=self.riemann_port)
+ return client
+ except Exception as e:
+ logger.critical("Connection to Riemann failed : %s " % e)
+ return None
+
+ def export(self, name, columns, points):
+ """Write the points in Riemann."""
+ for i in range(len(columns)):
+ if not isinstance(points[i], Number):
+ continue
+ else:
+ data = {'host': self.hostname, 'service': name + " " + columns[i], 'metric': points[i]}
+ logger.debug(data)
+ try:
+ self.client.send(data)
+ except Exception as e:
+ logger.error("Can not export stats to Riemann (%s)" % e)
diff --git a/glances/globals.py b/glances/globals.py
index 8eba5090..6b952a76 100644
--- a/glances/globals.py
+++ b/glances/globals.py
@@ -22,11 +22,6 @@
import os
import sys
-# Global information
-appname = 'glances'
-version = __import__('glances').__version__
-psutil_version = __import__('glances').__psutil_version
-
# Operating system flag
# Note: Somes libs depends of OS
BSD = sys.platform.find('bsd') != -1
diff --git a/glances/main.py b/glances/main.py
index a8234295..9be00fcb 100644
--- a/glances/main.py
+++ b/glances/main.py
@@ -24,9 +24,10 @@ import os
import sys
import tempfile
+from glances import __appname__, __version__, psutil_version
from glances.compat import input
from glances.config import Config
-from glances.globals import appname, LINUX, WINDOWS, psutil_version, version
+from glances.globals import LINUX, WINDOWS
from glances.logger import logger
@@ -86,14 +87,14 @@ Start the client browser (browser mode):\n\
def init_args(self):
"""Init all the command line arguments."""
- _version = "Glances v" + version + " with psutil v" + psutil_version
+ version = "Glances v" + __version__ + " with psutil v" + psutil_version
parser = argparse.ArgumentParser(
- prog=appname,
+ prog=__appname__,
conflict_handler='resolve',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=self.example_of_use)
parser.add_argument(
- '-V', '--version', action='version', version=_version)
+ '-V', '--version', action='version', version=version)
parser.add_argument('-d', '--debug', action='store_true', default=False,
dest='debug', help='enable debug mode')
parser.add_argument('-C', '--config', dest='conf_file',
@@ -162,6 +163,8 @@ Start the client browser (browser mode):\n\
dest='export_elasticsearch', help='export stats to an ElasticSearch server (elasticsearch lib needed)')
parser.add_argument('--export-rabbitmq', action='store_true', default=False,
dest='export_rabbitmq', help='export stats to rabbitmq broker (pika lib needed)')
+ parser.add_argument('--export-riemann', action='store_true', default=False,
+ dest='export_riemann', help='export stats to riemann broker (bernhard lib needed)')
# Client/Server option
parser.add_argument('-c', '--client', dest='client',
help='connect to a Glances server by IPv4/IPv6 address or hostname')
diff --git a/glances/outputs/glances_bottle.py b/glances/outputs/glances_bottle.py
index 053a1175..5ea21873 100644
--- a/glances/outputs/glances_bottle.py
+++ b/glances/outputs/glances_bottle.py
@@ -333,15 +333,8 @@ class GlancesBottle(object):
abort(404, "Cannot get views for plugin %s (%s)" % (plugin, str(e)))
return ret
- 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
-
- """
+ def _api_itemvalue(self, plugin, item, value=None):
+ """ Father method for _api_item and _api_value"""
response.content_type = 'application/json'
if plugin not in self.plugins_list:
@@ -350,35 +343,39 @@ class GlancesBottle(object):
# Update the stat
self.stats.update()
- plist = self.stats.get_plugin(plugin).get_stats_item(item)
+ if value is None:
+ ret = self.stats.get_plugin(plugin).get_stats_item(item)
- if plist is None:
- abort(404, "Cannot get item %s in plugin %s" % (item, plugin))
+ if ret is None:
+ abort(404, "Cannot get item %s in plugin %s" % (item, plugin))
else:
- return plist
+ ret = self.stats.get_plugin(plugin).get_stats_value(item, value)
- def _api_value(self, plugin, item, value):
+ if ret is None:
+ abort(404, "Cannot get item(%s)=value(%s) in plugin %s" % (item, value, plugin))
+
+ return ret
+
+ def _api_item(self, plugin, item):
"""Glances API RESTFul implementation.
- Return the process stats (dict) for the given item=value
+ 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()
+ """
+ return self._api_itemvalue(plugin, item)
- pdict = self.stats.get_plugin(plugin).get_stats_value(item, value)
+ def _api_value(self, plugin, item, value):
+ """Glances API RESTFul implementation.
- if pdict is None:
- abort(404, "Cannot get item(%s)=value(%s) in plugin %s" % (item, value, plugin))
- else:
- return pdict
+ 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
+ """
+ return self._api_itemvalue(plugin, item, value)
def _api_args(self):
"""Glances API RESTFul implementation.
diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py
index 4d5934c8..f86f1175 100644
--- a/glances/outputs/glances_curses.py
+++ b/glances/outputs/glances_curses.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# Copyright (C) 2015 Nicolargo <nicolas@nicolargo.com>
+# Copyright (C) 2016 Nicolargo <nicolas@nicolargo.com>
#
# Glances is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
@@ -846,7 +846,7 @@ class _GlancesCurses(object):
else:
# Display the popup
popup.refresh()
- curses.napms(duration * 1000)
+ self.wait(duration * 1000)
return True
def display_plugin(self, plugin_stats,
@@ -986,10 +986,14 @@ class _GlancesCurses(object):
# Redraw display
self.flush(stats, cs_status=cs_status)
# Wait 100ms...
- curses.napms(100)
+ self.wait()
return exitkey
+ def wait(self, delay=100):
+ """Wait delay in ms"""
+ curses.napms(100)
+
def get_stats_display_width(self, curse_msg, without_option=False):
"""Return the width of the formatted curses message.
@@ -1036,248 +1040,6 @@ class GlancesCursesClient(_GlancesCurses):
pass
-class GlancesCursesBrowser(_GlancesCurses):
-
- """Class for the Glances curse client browser."""
-
- def __init__(self, args=None):
- # Init the father class
- super(GlancesCursesBrowser, self).__init__(args=args)
-
- _colors_list = {
- 'UNKNOWN': self.no_color,
- 'SNMP': self.default_color2,
- 'ONLINE': self.default_color2,
- 'OFFLINE': self.ifCRITICAL_color2,
- 'PROTECTED': self.ifWARNING_color2,
- }
- self.colors_list.update(_colors_list)
-
- # First time scan tag
- # Used to display a specific message when the browser is started
- self.first_scan = True
-
- # Init refresh time
- self.__refresh_time = args.time
-
- # Init the cursor position for the client browser
- self.cursor_position = 0
-
- # Active Glances server number
- self._active_server = None
-
- @property
- def active_server(self):
- """Return the active server or None if it's the browser list."""
- return self._active_server
-
- @active_server.setter
- def active_server(self, index):
- """Set the active server or None if no server selected."""
- self._active_server = index
-
- @property
- def cursor(self):
- """Get the cursor position."""
- return self.cursor_position
-
- @cursor.setter
- def cursor(self, position):
- """Set the cursor position."""
- self.cursor_position = position
-
- def cursor_up(self, servers_list):
- """Set the cursor to position N-1 in the list."""
- if self.cursor_position > 0:
- self.cursor_position -= 1
- else:
- self.cursor_position = len(servers_list) - 1
-
- def cursor_down(self, servers_list):
- """Set the cursor to position N-1 in the list."""
- if self.cursor_position < len(servers_list) - 1:
- self.cursor_position += 1
- else:
- self.cursor_position = 0
-
- def __catch_key(self, servers_list):
- # Catch the browser pressed key
- self.pressedkey = self.get_key(self.term_window)
-
- # Actions...
- if self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'):
- # 'ESC'|'q' > Quit
- self.end()
- logger.info("Stop Glances client browser")
- sys.exit(0)
- elif self.pressedkey == 10:
- # 'ENTER' > Run Glances on the selected server
- logger.debug("Server number {0} selected".format(self.cursor + 1))
- self.active_server = self.cursor
- elif self.pressedkey == 259:
- # 'UP' > Up in the server list
- self.cursor_up(servers_list)
- elif self.pressedkey == 258:
- # 'DOWN' > Down in the server list
- self.cursor_down(servers_list)
-
- # Return the key code
- return self.pressedkey
-
- def update(self, servers_list):
- """Update the servers' list screen.
-
- Wait for __refresh_time sec / catch key every 100 ms.
-
- servers_list: Dict of dict with servers stats
- """
- # Flush display
- logger.debug('Servers list: {0}'.format(servers_list))
- self.flush(servers_list)
-
- # Wait
- exitkey = False
- countdown = Timer(self.__refresh_time)
- while not countdown.finished() and not exitkey:
- # Getkey
- pressedkey = self.__catch_key(servers_list)
- # Is it an exit or select server key ?
- exitkey = (
- pressedkey == ord('\x1b') or pressedkey == ord('q') or pressedkey == 10)
- if not exitkey and pressedkey > -1:
- # Redraw display
- self.flush(servers_list)
- # Wait 100ms...
- curses.napms(100)
-
- return self.active_server
-
- def flush(self, servers_list):
- """Update the servers' list screen.
-
- servers_list: List of dict with servers stats
- """
- self.erase()
- self.display(servers_list)
-
- def display(self, servers_list):
- """Display the servers list.
-
- Return:
- True if the stats have been displayed
- False if the stats have not been displayed (no server available)
- """
- # Init the internal line/column for Glances Curses
- self.init_line_column()
-
- # Get the current screen size
- screen_x = self.screen.getmaxyx()[1]
- screen_y = self.screen.getmaxyx()[0]
-
- # Init position
- x = 0
- y = 0
-
- # Display top header
- if len(servers_list) == 0:
- if self.first_scan and not self.args.disable_autodiscover:
- msg = 'Glances is scanning your network. Please wait...'
- self.first_scan = False
- else:
- msg = 'No Glances server available'
- elif len(servers_list) == 1:
- msg = 'One Glances server available'
- else:
- msg = '{0} Glances servers available'.format(len(servers_list))
- if self.args.disable_autodiscover:
- msg += ' ' + '(auto discover is disabled)'
- self.term_window.addnstr(y, x,
- msg,
- screen_x - x,
- self.colors_list['TITLE'])
-
- if len(servers_list) == 0:
- return False
-
- # Display the Glances server list
- # ================================
-
- # Table of table
- # Item description: [stats_id, column name, column size]
- column_def = [
- ['name', 'Name', 16],
- ['alias', None, None],
- ['load_min5', 'LOAD', 6],
- ['cpu_percent', 'CPU%', 5],
- ['mem_percent', 'MEM%', 5],
- ['status', 'STATUS', 9],
- ['ip', 'IP', 15],
- # ['port', 'PORT', 5],
- ['hr_name', 'OS', 16],
- ]
- y = 2
-
- # Display table header
- xc = x + 2
- for cpt, c in enumerate(column_def):
- if xc < screen_x and y < screen_y and c[1] is not None:
- self.term_window.addnstr(y, xc,
- c[1],
- screen_x - x,
- self.colors_list['BOLD'])
- xc += c[2] + self.space_between_column
- y += 1
-
- # If a servers has been deleted from the list...
- # ... and if the cursor is in the latest position
- if self.cursor > len(servers_list) - 1:
- # Set the cursor position to the latest item
- self.cursor = len(servers_list) - 1
-
- # Display table
- line = 0
- for v in servers_list:
- # Get server stats
- server_stat = {}
- for c in column_def:
- try:
- server_stat[c[0]] = v[c[0]]
- except KeyError as e:
- logger.debug(
- "Cannot grab stats {0} from server (KeyError: {1})".format(c[0], e))
- server_stat[c[0]] = '?'
- # Display alias instead of name
- try:
- if c[0] == 'alias' and v[c[0]] is not None:
- server_stat['name'] = v[c[0]]
- except KeyError:
- pass
-
- # Display line for server stats
- cpt = 0
- xc = x
-
- # Is the line selected ?
- if line == self.cursor:
- # Display cursor
- self.term_window.addnstr(
- y, xc, ">", screen_x - xc, self.colors_list['BOLD'])
-
- # Display the line
- xc += 2
- for c in column_def:
- if xc < screen_x and y < screen_y and c[1] is not None:
- # Display server stats
- self.term_window.addnstr(
- y, xc, format(server_stat[c[0]]), c[2], self.colors_list[v['status']])
- xc += c[2] + self.space_between_column
- cpt += 1
- # Next line, next server...
- y += 1
- line += 1
-
- return True
-
if not WINDOWS:
class GlancesTextbox(Textbox, object):
diff --git a/glances/outputs/glances_curses_browser.py b/glances/outputs/glances_curses_browser.py
new file mode 100644
index 00000000..11543fb9
--- /dev/null
+++ b/glances/outputs/glances_curses_browser.py
@@ -0,0 +1,273 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of Glances.
+#
+# Copyright (C) 2016 Nicolargo <nicolas@nicolargo.com>
+#
+# Glances is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Glances is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""Curses browser interface class ."""
+
+import sys
+
+from glances.outputs.glances_curses import _GlancesCurses
+
+from glances.logger import logger
+from glances.timer import Timer
+
+
+class GlancesCursesBrowser(_GlancesCurses):
+
+ """Class for the Glances curse client browser."""
+
+ def __init__(self, args=None):
+ # Init the father class
+ super(GlancesCursesBrowser, self).__init__(args=args)
+
+ _colors_list = {
+ 'UNKNOWN': self.no_color,
+ 'SNMP': self.default_color2,
+ 'ONLINE': self.default_color2,
+ 'OFFLINE': self.ifCRITICAL_color2,
+ 'PROTECTED': self.ifWARNING_color2,
+ }
+ self.colors_list.update(_colors_list)
+
+ # First time scan tag
+ # Used to display a specific message when the browser is started
+ self.first_scan = True
+
+ # Init refresh time
+ self.__refresh_time = args.time
+
+ # Init the cursor position for the client browser
+ self.cursor_position = 0
+
+ # Active Glances server number
+ self._active_server = None
+
+ @property
+ def active_server(self):
+ """Return the active server or None if it's the browser list."""
+ return self._active_server
+
+ @active_server.setter
+ def active_server(self, index):
+ """Set the active server or None if no server selected."""
+ self._active_server = index
+
+ @property
+ def cursor(self):
+ """Get the cursor position."""
+ return self.cursor_position
+
+ @cursor.setter
+ def cursor(self, position):
+ """Set the cursor position."""
+ self.cursor_position = position
+
+ def cursor_up(self, servers_list):
+ """Set the cursor to position N-1 in the list."""
+ if self.cursor_position > 0:
+ self.cursor_position -= 1
+ else:
+ self.cursor_position = len(servers_list) - 1
+
+ def cursor_down(self, servers_list):
+ """Set the cursor to position N-1 in the list."""
+