From d29e3a68a7ffcbb08a68a1cd7990f4ba57f259e7 Mon Sep 17 00:00:00 2001 From: Nicolargo Date: Sun, 22 Jun 2014 10:29:23 +0200 Subject: Update docs --- docs/glances-doc.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/glances-doc.html b/docs/glances-doc.html index f584c296..1f044548 100644 --- a/docs/glances-doc.html +++ b/docs/glances-doc.html @@ -123,7 +123,7 @@ td.option-group {

Glances

-

This manual describes Glances version 2.0.

+

This manual describes Glances version 2.0.1.

Copyright © 2012-2014 Nicolas Hennion <nicolas@nicolargo.com>

June 2014

-- cgit v1.2.3 From d27e07bb257f2c0a52952f92f7ad5f1e737e3132 Mon Sep 17 00:00:00 2001 From: Nicolargo Date: Wed, 25 Jun 2014 11:07:52 +0200 Subject: Implement issue #374: display loaded configuration file in the help screen --- glances/core/glances_config.py | 11 ++++++++++- glances/core/glances_main.py | 19 +++++-------------- glances/core/glances_stats.py | 8 +++++++- glances/plugins/glances_help.py | 17 +++++++++++++++-- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/glances/core/glances_config.py b/glances/core/glances_config.py index 6db373ea..c8a1666a 100644 --- a/glances/core/glances_config.py +++ b/glances/core/glances_config.py @@ -52,9 +52,12 @@ class Config(object): def __init__(self, location=None): self.location = location + self.config_filename = 'glances.conf' self.parser = RawConfigParser() + + self._loaded_config_file = None self.load() def load(self): @@ -70,10 +73,16 @@ class Config(object): except UnicodeDecodeError as e: print(_("Error: Cannot decode configuration file '{0}': {1}").format(config_file, e)) sys.exit(1) + # Save the loaded configuration file path (issue #374) + self._loaded_config_file = config_file break + def get_loaded_config_file(self): + """Return the loaded configuration file""" + return self._loaded_config_file + def get_config_paths(self): - r"""Get a list of config file paths. + """Get a list of config file paths. The list is built taking into account of the OS, priority and location. diff --git a/glances/core/glances_main.py b/glances/core/glances_main.py index 4d866b2d..649124f0 100644 --- a/glances/core/glances_main.py +++ b/glances/core/glances_main.py @@ -114,7 +114,7 @@ class GlancesMain(object): """Parse command line arguments.""" args = self.init_args().parse_args() - # Load the configuration file, it it exists + # Load the configuration file, if it exists self.config = Config(args.conf_file) # In web server mode, default: @@ -146,15 +146,6 @@ class GlancesMain(object): # Default is no password args.password = self.password - # !!! Change global variables regarding to user args - # !!! To be refactor to use directly the args list in the code - self.server_tag = args.server - self.webserver_tag = args.webserver - if args.client is not None: - self.client_tag = True - self.server_ip = args.client - # /!!! - # By default help is hidden args.help_tag = False @@ -186,19 +177,19 @@ class GlancesMain(object): def is_standalone(self): """Return True if Glances is running in standalone mode.""" - return not self.client_tag and not self.server_tag and not self.webserver_tag + return not self.args.client and not self.args.server and not self.args.webserver def is_client(self): """Return True if Glances is running in client mode.""" - return self.client_tag and not self.server_tag + return self.args.client and not self.args.server def is_server(self): """Return True if Glances is running in server mode.""" - return not self.client_tag and self.server_tag + return not self.args.client and self.args.server def is_webserver(self): """Return True if Glances is running in Web server mode.""" - return not self.client_tag and self.webserver_tag + return not self.args.client and self.args.webserver def get_config(self): """Return configuration file object.""" diff --git a/glances/core/glances_stats.py b/glances/core/glances_stats.py index 4f265e06..d36c0e94 100644 --- a/glances/core/glances_stats.py +++ b/glances/core/glances_stats.py @@ -34,6 +34,9 @@ class GlancesStats(object): # Init the plugin list dict self._plugins = collections.defaultdict(dict) + # Set the config instance + self.config = config + # Load the plugins self.load_plugins() @@ -76,7 +79,10 @@ class GlancesStats(object): # for example, the file glances_xxx.py # generate self._plugins_list["xxx"] = ... plugin_name = os.path.basename(item)[len(header):-3].lower() - self._plugins[plugin_name] = plugin.Plugin(args=args) + if plugin_name == 'help': + self._plugins[plugin_name] = plugin.Plugin(args=args, config=self.config) + else: + self._plugins[plugin_name] = plugin.Plugin(args=args) # Restoring system path sys.path = sys_path diff --git a/glances/plugins/glances_help.py b/glances/plugins/glances_help.py index d824f194..24baf68e 100644 --- a/glances/plugins/glances_help.py +++ b/glances/plugins/glances_help.py @@ -32,10 +32,13 @@ class Plugin(GlancesPlugin): """Glances' help plugin.""" - def __init__(self, args=None): + def __init__(self, args=None, config=None): """Init the plugin.""" GlancesPlugin.__init__(self, args=args) + # Set the config instance + self.config = config + # We want to display the stat in the curse interface self.display_curse = True # Set the message position @@ -58,10 +61,20 @@ class Plugin(GlancesPlugin): # Header msg = '{0} {1}'.format(appname.title(), version) ret.append(self.curse_add_line(msg, "TITLE")) - msg = _(" with psutil {0}").format(psutil_version) + msg = _(" with PSutil {0}").format(psutil_version) ret.append(self.curse_add_line(msg)) ret.append(self.curse_new_line()) + # Configuration file path + try: + msg = '{0}: {1}'.format(_("Configuration file"), self.config.get_loaded_config_file()) + except AttributeError as e: + pass + else: + ret.append(self.curse_new_line()) + ret.append(self.curse_add_line(msg)) + ret.append(self.curse_new_line()) + # Keys msg_col = ' {0:1} {1:35}' msg_col2 = ' {0:1} {1:35}' -- cgit v1.2.3 From 1820a200b1baabdeff448c6710f29fff01aedbb9 Mon Sep 17 00:00:00 2001 From: Nicolargo Date: Wed, 25 Jun 2014 13:15:59 +0200 Subject: Put the 'r' back because there is backslash in the docstring... --- glances/core/glances_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glances/core/glances_config.py b/glances/core/glances_config.py index c8a1666a..1ea0d82e 100644 --- a/glances/core/glances_config.py +++ b/glances/core/glances_config.py @@ -82,7 +82,7 @@ class Config(object): return self._loaded_config_file def get_config_paths(self): - """Get a list of config file paths. + r"""Get a list of config file paths. The list is built taking into account of the OS, priority and location. -- cgit v1.2.3 From 5252eab9c00cebcd5592bd1c01e136f32f0b322d Mon Sep 17 00:00:00 2001 From: Nicolargo Date: Wed, 25 Jun 2014 16:12:46 +0200 Subject: Improve Windows SNMP get --- glances/core/glances_stats.py | 41 ++++++++++++++++++++++++-- glances/plugins/glances_cpu.py | 12 ++++---- glances/plugins/glances_fs.py | 59 ++++++++++++++++++++++++++++---------- glances/plugins/glances_load.py | 2 +- glances/plugins/glances_network.py | 27 +++++++++++++---- glances/plugins/glances_plugin.py | 10 ++++++- glances/plugins/glances_system.py | 29 +++++++++++++++++-- 7 files changed, 147 insertions(+), 33 deletions(-) diff --git a/glances/core/glances_stats.py b/glances/core/glances_stats.py index d36c0e94..9ae35a87 100644 --- a/glances/core/glances_stats.py +++ b/glances/core/glances_stats.py @@ -22,9 +22,17 @@ import collections import os import sys +import re from glances.core.glances_globals import plugins_path, sys_path +# SNMP OID regexp pattern to short system name dict +oid_to_short_system_name = {'.*Linux.*': 'linux', + '.*BSD.*': 'bsd', + '.*Darwin.*': 'mac', + '.*Windows.*': 'windows', + '.*Cisco.*': 'cisco'} + class GlancesStats(object): @@ -203,6 +211,9 @@ class GlancesStatsClientSNMP(GlancesStats): # Init the arguments self.args = args + # OS name is used because OID is differents between system + self.os_name = None + # Load plugins self.load_plugins(args=self.args) @@ -219,14 +230,40 @@ class GlancesStatsClientSNMP(GlancesStats): user=self.args.snmp_user, auth=self.args.snmp_auth) - return clientsnmp.get_by_oid("1.3.6.1.2.1.1.5.0") != {} + # If we can not grab the hostname, then exit... + ret = clientsnmp.get_by_oid("1.3.6.1.2.1.1.5.0") != {} + if ret: + # Get the OS name (need to grab the good OID...) + oid_os_name = clientsnmp.get_by_oid("1.3.6.1.2.1.1.1.0") + try: + self.system_name = self.get_system_name(oid_os_name['1.3.6.1.2.1.1.1.0']) + except KeyError: + self.system_name = None + + return ret + + def get_system_name(self, oid_system_name): + """Get the short os name from the OS name OID string""" + short_system_name = None + + if oid_system_name == '': + return short_system_name + + # Find the short name in the oid_to_short_os_name dict + for r,v in oid_to_short_system_name.iteritems(): + if re.search(r, oid_system_name): + short_system_name = v + break + + return short_system_name + def update(self): """Update the stats using SNMP.""" # For each plugins, call the update method for p in self._plugins: # Set the input method to SNMP - self._plugins[p].set_input('snmp') + self._plugins[p].set_input('snmp', self.system_name) # print "DEBUG: Update %s stats using SNMP request" % p try: self._plugins[p].update() diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 479e6358..9d37ab07 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -27,10 +27,9 @@ import psutil # percentage of user CPU time: .1.3.6.1.4.1.2021.11.9.0 # percentages of system CPU time: .1.3.6.1.4.1.2021.11.10.0 # percentages of idle CPU time: .1.3.6.1.4.1.2021.11.11.0 -snmp_oid = {'user': '1.3.6.1.4.1.2021.11.9.0', - 'system': '1.3.6.1.4.1.2021.11.10.0', - 'idle': '1.3.6.1.4.1.2021.11.11.0'} - +snmp_oid = {'default': {'user': '1.3.6.1.4.1.2021.11.9.0', + 'system': '1.3.6.1.4.1.2021.11.10.0', + 'idle': '1.3.6.1.4.1.2021.11.11.0'}} class Plugin(GlancesPlugin): @@ -91,7 +90,10 @@ class Plugin(GlancesPlugin): self.stats[cpu] = getattr(cputimespercent, cpu) elif self.get_input() == 'snmp': # Update stats using SNMP - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid) + try: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()]) + except KeyError: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid['default']) if self.stats['user'] == '': self.reset() diff --git a/glances/plugins/glances_fs.py b/glances/plugins/glances_fs.py index c4f7d322..ca3d01dc 100644 --- a/glances/plugins/glances_fs.py +++ b/glances/plugins/glances_fs.py @@ -19,6 +19,8 @@ """File system plugin.""" +import base64 + from glances.plugins.glances_plugin import GlancesPlugin import psutil @@ -37,11 +39,15 @@ import psutil # Used space on the disk: .1.3.6.1.4.1.2021.9.1.8.1 # Percentage of space used on disk: .1.3.6.1.4.1.2021.9.1.9.1 # Percentage of inodes used on disk: .1.3.6.1.4.1.2021.9.1.10.1 -snmp_oid = {'mnt_point': '1.3.6.1.4.1.2021.9.1.2', - 'device_name': '1.3.6.1.4.1.2021.9.1.3', - 'size': '1.3.6.1.4.1.2021.9.1.6', - 'used': '1.3.6.1.4.1.2021.9.1.8', - 'percent': '1.3.6.1.4.1.2021.9.1.9'} +snmp_oid = {'default': {'mnt_point': '1.3.6.1.4.1.2021.9.1.2', + 'device_name': '1.3.6.1.4.1.2021.9.1.3', + 'size': '1.3.6.1.4.1.2021.9.1.6', + 'used': '1.3.6.1.4.1.2021.9.1.8', + 'percent': '1.3.6.1.4.1.2021.9.1.9'}, + 'windows': {'mnt_point': '1.3.6.1.2.1.25.2.3.1.3', + 'alloc_unit': '1.3.6.1.2.1.25.2.3.1.4', + 'size': '1.3.6.1.2.1.25.2.3.1.5', + 'used': '1.3.6.1.2.1.25.2.3.1.6'}} class Plugin(GlancesPlugin): @@ -110,17 +116,38 @@ class Plugin(GlancesPlugin): # Update stats using SNMP # SNMP bulk command to get all file system in one shot - fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid, bulk=True) + + try: + fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], + bulk=True) + except KeyError: + fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid['default'], + bulk=True) # Loop over fs - for fs in fs_stat: - fs_current = {} - fs_current['device_name'] = fs_stat[fs]['device_name'] - fs_current['mnt_point'] = fs - fs_current['size'] = int(fs_stat[fs]['size']) * 1024 - fs_current['used'] = int(fs_stat[fs]['used']) * 1024 - fs_current['percent'] = float(fs_stat[fs]['percent']) - self.stats.append(fs_current) + if self.get_short_system_name() == 'windows': + # Windows tips + for fs in fs_stat: + # Memory stats are grabed in the same OID table (ignore it) + if fs == 'Virtual Memory' or fs == 'Physical Memory': + continue + fs_current = {} + fs_current['device_name'] = '' + fs_current['mnt_point'] = fs.partition(' ')[0] + fs_current['size'] = int(fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit']) + fs_current['used'] = int(fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit']) + fs_current['percent'] = float(fs_current['used'] * 100 / fs_current['size']) + self.stats.append(fs_current) + else: + # Default behavor + for fs in fs_stat: + fs_current = {} + fs_current['device_name'] = fs_stat[fs]['device_name'] + fs_current['mnt_point'] = fs + fs_current['size'] = int(fs_stat[fs]['size']) * 1024 + fs_current['used'] = int(fs_stat[fs]['used']) * 1024 + fs_current['percent'] = float(fs_stat[fs]['percent']) + self.stats.append(fs_current) return self.stats @@ -146,7 +173,9 @@ class Plugin(GlancesPlugin): for i in sorted(self.stats, key=lambda fs: fs['mnt_point']): # New line ret.append(self.curse_new_line()) - if len(i['mnt_point']) + len(i['device_name'].split('/')[-1]) <= 6: + if i['device_name'] == '': + mnt_point = i['mnt_point'] + elif len(i['mnt_point']) + len(i['device_name'].split('/')[-1]) <= 6: # If possible concatenate mode info... Glances touch inside :) mnt_point = i['mnt_point'] + ' (' + i['device_name'].split('/')[-1] + ')' elif len(i['mnt_point']) > 9: diff --git a/glances/plugins/glances_load.py b/glances/plugins/glances_load.py index 4b6a7a14..526a3bda 100644 --- a/glances/plugins/glances_load.py +++ b/glances/plugins/glances_load.py @@ -116,7 +116,7 @@ class Plugin(GlancesPlugin): ret.append(self.curse_add_line(msg, "TITLE")) # Core number if self.stats['cpucore'] > 0: - msg = _("{0}-core").format(self.stats['cpucore'], '>1') + msg = _("{0:d}-core").format(int(self.stats['cpucore']), '>1') ret.append(self.curse_add_line(msg)) # New line ret.append(self.curse_new_line()) diff --git a/glances/plugins/glances_network.py b/glances/plugins/glances_network.py index 356832f1..5dd5f515 100644 --- a/glances/plugins/glances_network.py +++ b/glances/plugins/glances_network.py @@ -19,6 +19,8 @@ """Network plugin.""" +import base64 + from glances.core.glances_timer import getTimeSinceLastUpdate from glances.plugins.glances_plugin import GlancesPlugin @@ -27,9 +29,9 @@ import psutil # SNMP OID # http://www.net-snmp.org/docs/mibs/interfaces.html # Dict key = interface_name -snmp_oid = {'interface_name': '1.3.6.1.2.1.2.2.1.2', - 'cumulative_rx': '1.3.6.1.2.1.2.2.1.10', - 'cumulative_tx': '1.3.6.1.2.1.2.2.1.16'} +snmp_oid = {'default': {'interface_name': '1.3.6.1.2.1.2.2.1.2', + 'cumulative_rx': '1.3.6.1.2.1.2.2.1.10', + 'cumulative_tx': '1.3.6.1.2.1.2.2.1.16'}} class Plugin(GlancesPlugin): @@ -94,7 +96,7 @@ class Plugin(GlancesPlugin): for net in network_new: try: # Try necessary to manage dynamic network interface - netstat = {} + netstat = {} netstat['interface_name'] = net netstat['time_since_update'] = time_since_update netstat['cumulative_rx'] = network_new[net].bytes_recv @@ -118,7 +120,12 @@ class Plugin(GlancesPlugin): # Update stats using SNMP # SNMP bulk command to get all network interface in one shot - netiocounters = self.set_stats_snmp(snmp_oid=snmp_oid, bulk=True) + try: + netiocounters = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], + bulk=True) + except KeyError: + netiocounters = self.set_stats_snmp(snmp_oid=snmp_oid['default'], + bulk=True) # Previous network interface stats are stored in the network_old variable if not hasattr(self, 'network_old'): @@ -138,7 +145,15 @@ class Plugin(GlancesPlugin): try: # Try necessary to manage dynamic network interface netstat = {} - netstat['interface_name'] = net + # Windows: a tips is needed to convert HEX to TXT + # http://blogs.technet.com/b/networking/archive/2009/12/18/how-to-query-the-list-of-network-interfaces-using-snmp-via-the-ifdescr-counter.aspx + if self.get_short_system_name() == 'windows': + try: + netstat['interface_name'] = str(base64.b16decode(net[2:-2].upper())) + except TypeError: + netstat['interface_name'] = net + else: + netstat['interface_name'] = net netstat['time_since_update'] = time_since_update netstat['cumulative_rx'] = float(network_new[net]['cumulative_rx']) netstat['rx'] = (float(network_new[net]['cumulative_rx']) - diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index a1daf1c9..dd439b8f 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -44,6 +44,7 @@ class GlancesPlugin(object): # Init the input method self.input_method = 'local' + self.short_system_name = None # Init the stats list self.stats = None @@ -59,20 +60,27 @@ class GlancesPlugin(object): """Return the human-readable stats.""" return str(self.stats) - def set_input(self, input_method): + def set_input(self, input_method, short_system_name=None): """Set the input method. * local: system local grab (psutil or direct access) * snmp: Client server mode via SNMP * glances: Client server mode via Glances API + + For SNMP, short_system_name is detected short OS name """ self.input_method = input_method + self.short_system_name = short_system_name return self.input_method def get_input(self): """Get the input method.""" return self.input_method + def get_short_system_name(self): + """Get the short detected OS name""" + return self.short_system_name + def set_stats(self, input_stats): """Set the stats to input_stats.""" self.stats = input_stats diff --git a/glances/plugins/glances_system.py b/glances/plugins/glances_system.py index d51ace3c..efb8bf30 100644 --- a/glances/plugins/glances_system.py +++ b/glances/plugins/glances_system.py @@ -22,13 +22,25 @@ # Import system libs import os import platform +import re # Import Glances libs from glances.plugins.glances_plugin import GlancesPlugin # SNMP OID -snmp_oid = {'hostname': '1.3.6.1.2.1.1.5.0', - 'os_name': '1.3.6.1.2.1.1.1.0'} +snmp_oid = {'default': {'hostname': '1.3.6.1.2.1.1.5.0', + 'system_name': '1.3.6.1.2.1.1.1.0'}} + +# SNMP to human read +# Dict (key: OS short name) of dict (reg exp OID to human) +# Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx +snmp_to_human = {'windows': {'Windows Version 6.3': 'Windows 8.1 or Server 2012R2', + 'Windows Version 6.2': 'Windows 8 or Server 2012', + 'Windows Version 6.1': 'Windows 7 or Server 2008R2', + 'Windows Version 6.0': 'Windows Vista or Server 2008', + 'Windows Version 5.2': 'Windows XP 64bits or 2003 server', + 'Windows Version 5.1': 'Windows XP', + 'Windows Version 5.0': 'Windows 2000'}} class Plugin(GlancesPlugin): @@ -90,7 +102,18 @@ class Plugin(GlancesPlugin): self.stats['os_version'] = "" elif self.get_input() == 'snmp': # Update stats using SNMP - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid) + try: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()]) + except KeyError: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid['default']) + # Default behavor: display all the information + self.stats['os_name'] = self.stats['system_name'] + # Windows OS tips + if self.get_short_system_name() == 'windows': + for r,v in snmp_to_human['windows'].iteritems(): + if re.search(r, self.stats['system_name']): + self.stats['os_name'] = v + break return self.stats -- cgit v1.2.3 From 9dda132c5e58fa62740980f2aa969aad4e787cd0 Mon Sep 17 00:00:00 2001 From: Nicolargo Date: Thu, 26 Jun 2014 23:15:18 +0200 Subject: Add CPU for WIndows OS --- glances/outputs/glances_curses.py | 2 +- glances/plugins/glances_cpu.py | 37 +++++++++++++++----- glances/plugins/glances_fs.py | 3 +- glances/plugins/glances_mem.py | 73 +++++++++++++++++++++++++-------------- glances/plugins/glances_plugin.py | 46 +++++++++++++++--------- 5 files changed, 107 insertions(+), 54 deletions(-) diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index 34355e3e..d37f6a1d 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -379,7 +379,7 @@ class GlancesCurses(object): if plugin_stats['line'] not in self.line_to_y: self.line_to_y[plugin_stats['line']] = plugin_stats['line'] display_y = self.line_to_y[plugin_stats['line']] - + # Display x = display_x y = display_y diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 9d37ab07..14dccaa8 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -29,7 +29,8 @@ import psutil # percentages of idle CPU time: .1.3.6.1.4.1.2021.11.11.0 snmp_oid = {'default': {'user': '1.3.6.1.4.1.2021.11.9.0', 'system': '1.3.6.1.4.1.2021.11.10.0', - 'idle': '1.3.6.1.4.1.2021.11.11.0'}} + 'idle': '1.3.6.1.4.1.2021.11.11.0'}, + 'windows': {'percent': '1.3.6.1.2.1.25.3.3.1.2'}} class Plugin(GlancesPlugin): @@ -90,15 +91,33 @@ class Plugin(GlancesPlugin): self.stats[cpu] = getattr(cputimespercent, cpu) elif self.get_input() == 'snmp': # Update stats using SNMP - try: - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()]) - except KeyError: - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid['default']) - - if self.stats['user'] == '': - self.reset() - return self.stats + if self.get_short_system_name() == 'windows': + # Windows + # You can find the CPU utilization of windows system by querying the oid + # Give also the number of core (number of element in the table) + # print snmp_oid[self.get_short_system_name()] + try: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], + bulk=True) + except KeyError: + self.reset() + + # TODO: iter through CPU... startswith('percent') + self.stats['idle'] = self.stats['percent.3'] + + else: + # Default behavor + try: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()]) + except KeyError: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid['default']) + + if self.stats['idle'] == '': + self.reset() + return self.stats + + # Convert SNMP stats to float for key in self.stats.iterkeys(): self.stats[key] = float(self.stats[key]) diff --git a/glances/plugins/glances_fs.py b/glances/plugins/glances_fs.py index ca3d01dc..26a867b1 100644 --- a/glances/plugins/glances_fs.py +++ b/glances/plugins/glances_fs.py @@ -115,8 +115,7 @@ class Plugin(GlancesPlugin): elif self.get_input() == 'snmp': # Update stats using SNMP - # SNMP bulk command to get all file system in one shot - + # SNMP bulk command to get all file system in one shot try: fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], bulk=True) diff --git a/glances/plugins/glances_mem.py b/glances/plugins/glances_mem.py index c89ac343..db69b980 100644 --- a/glances/plugins/glances_mem.py +++ b/glances/plugins/glances_mem.py @@ -30,13 +30,16 @@ import psutil # Total RAM Shared: .1.3.6.1.4.1.2021.4.13.0 # Total RAM Buffered: .1.3.6.1.4.1.2021.4.14.0 # Total Cached Memory: .1.3.6.1.4.1.2021.4.15.0 -snmp_oid = {'total': '1.3.6.1.4.1.2021.4.5.0', - # 'used': '1.3.6.1.4.1.2021.4.6.0', - 'free': '1.3.6.1.4.1.2021.4.11.0', - 'shared': '1.3.6.1.4.1.2021.4.13.0', - 'buffers': '1.3.6.1.4.1.2021.4.14.0', - 'cached': '1.3.6.1.4.1.2021.4.15.0'} - +# Note: For Windows, stats are in the FS table +snmp_oid = {'default': {'total': '1.3.6.1.4.1.2021.4.5.0', + 'free': '1.3.6.1.4.1.2021.4.11.0', + 'shared': '1.3.6.1.4.1.2021.4.13.0', + 'buffers': '1.3.6.1.4.1.2021.4.14.0', + 'cached': '1.3.6.1.4.1.2021.4.15.0'}, + 'windows': {'mnt_point': '1.3.6.1.2.1.25.2.3.1.3', + 'alloc_unit': '1.3.6.1.2.1.25.2.3.1.4', + 'size': '1.3.6.1.2.1.25.2.3.1.5', + 'used': '1.3.6.1.2.1.25.2.3.1.6'}} class Plugin(GlancesPlugin): @@ -88,7 +91,7 @@ class Plugin(GlancesPlugin): # cached: (Linux, BSD): cache for various things. # wired: (BSD, OSX): memory that is marked to always stay in RAM. It is never moved to disk. # shared: (BSD): memory that may be simultaneously accessed by multiple processes. - self.stats = {} + self.reset() for mem in ['total', 'available', 'percent', 'used', 'free', 'active', 'inactive', 'buffers', 'cached', 'wired', 'shared']: @@ -106,24 +109,42 @@ class Plugin(GlancesPlugin): self.stats['used'] = self.stats['total'] - self.stats['free'] elif self.get_input() == 'snmp': # Update stats using SNMP - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid) - - if self.stats['total'] == '': - self.reset() - return self.stats - - for key in self.stats.iterkeys(): - if self.stats[key] != '': - self.stats[key] = float(self.stats[key]) * 1024 - - # Use the 'free'/htop calculation - self.stats['free'] = self.stats['free'] - self.stats['total'] + (self.stats['buffers'] + self.stats['cached']) - - # used=total-free - self.stats['used'] = self.stats['total'] - self.stats['free'] - - # percent: the percentage usage calculated as (total - available) / total * 100. - self.stats['percent'] = float((self.stats['total'] - self.stats['free']) / self.stats['total'] * 100) + if self.get_short_system_name() == 'windows': + # Mem stats for Windows OS are stored in the FS table + try: + fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], + bulk=True) + except KeyError: + self.reset() + else: + for fs in fs_stat: + # Memory stats are grabed in the same OID table (ignore it) + if fs == 'Virtual Memory': + self.stats['total'] = int(fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit']) + self.stats['used'] = int(fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit']) + self.stats['percent'] = float(self.stats['used'] * 100 / self.stats['total']) + self.stats['free'] = self.stats['total'] - self.stats['used'] + break + else: + # Default behavor for others OS + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid['default']) + + if self.stats['total'] == '': + self.reset() + return self.stats + + for key in self.stats.iterkeys(): + if self.stats[key] != '': + self.stats[key] = float(self.stats[key]) * 1024 + + # Use the 'free'/htop calculation + self.stats['free'] = self.stats['free'] - self.stats['total'] + (self.stats['buffers'] + self.stats['cached']) + + # used=total-free + self.stats['used'] = self.stats['total'] - self.stats['free'] + + # percent: the percentage usage calculated as (total - available) / total * 100. + self.stats['percent'] = float((self.stats['total'] - self.stats['free']) / self.stats['total'] * 100) return self.stats diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index dd439b8f..36f16116 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -105,22 +105,36 @@ class GlancesPlugin(object): # Bulk request snmpresult = clientsnmp.getbulk_by_oid(0, 10, *snmp_oid.values()) - # Build the internal dict with the SNMP result - # key is the first item in the snmp_oid - index = 1 - for item in snmpresult: - item_stats = {} - item_key = None - for key in snmp_oid.iterkeys(): - oid = snmp_oid[key] + '.' + str(index) - if oid in item: - if item_key is None: - item_key = item[oid] - else: - item_stats[key] = item[oid] - if item_stats != {}: - ret[item_key] = item_stats - index += 1 + if len(snmp_oid) == 1: + # Bulk command for only one OID + # Note: key is the item indexed but the OID result + for item in snmpresult: + if item.keys()[0].startswith(snmp_oid.values()[0]): + ret[snmp_oid.keys()[0] + item.keys()[0].split(snmp_oid.values()[0])[1]] = item.values()[0] + else: + # Build the internal dict with the SNMP result + # Note: key is the first item in the snmp_oid + index = 1 + for item in snmpresult: + item_stats = {} + item_key = None + for key in snmp_oid.iterkeys(): + oid = snmp_oid[key] + '.' + str(index) + if oid in item: + if item_key is None: + item_key = item[oid] + else: + item_stats[key] = item[oid] + if item_stats != {}: + ret[item_key] = item_stats + index += 1 + + # if '1.3.6.1.2.1.25.3.3.1.2' in snmp_oid.values(): + # # if '1.3.6.1.2.1.25.2.3.1.3' in snmp_oid.values(): + # print snmp_oid + # print snmpresult + # print ret + else: # Simple get request snmpresult = clientsnmp.get_by_oid(*snmp_oid.values()) -- cgit v1.2.3 From 0e7685ff16612e6e8b86bed4c39644bd41427004 Mon Sep 17 00:00:00 2001 From: Nicolas Hennion Date: Fri, 27 Jun 2014 13:57:01 +0200 Subject: MEMSWAP + CPU ok on Windows SNMP fallback mode --- glances/plugins/glances_cpu.py | 45 ++++++++++++++++++++++-------- glances/plugins/glances_mem.py | 6 ++-- glances/plugins/glances_memswap.py | 56 ++++++++++++++++++++++++++------------ 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 14dccaa8..8ca12648 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -98,13 +98,21 @@ class Plugin(GlancesPlugin): # Give also the number of core (number of element in the table) # print snmp_oid[self.get_short_system_name()] try: - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], - bulk=True) + cpu_stats = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], + bulk=True) except KeyError: self.reset() - # TODO: iter through CPU... startswith('percent') - self.stats['idle'] = self.stats['percent.3'] + # Iter through CPU and compute the idle CPU stats + self.stats['nb_log_core'] = 0 + self.stats['idle'] = 0 + for c in cpu_stats: + if c.startswith('percent'): + self.stats['idle'] += float(cpu_stats['percent.3']) + self.stats['nb_log_core'] += 1 + if self.stats['nb_log_core'] > 0: + self.stats['idle'] = self.stats['idle'] / self.stats['nb_log_core'] + self.stats['idle'] = 100 - self.stats['idle'] else: # Default behavor @@ -117,9 +125,9 @@ class Plugin(GlancesPlugin): self.reset() return self.stats - # Convert SNMP stats to float - for key in self.stats.iterkeys(): - self.stats[key] = float(self.stats[key]) + # Convert SNMP stats to float + for key in self.stats.iterkeys(): + self.stats[key] = float(self.stats[key]) return self.stats @@ -133,12 +141,17 @@ class Plugin(GlancesPlugin): return ret # Build the string message + # If user stat is not here, display only idle / total CPU usage (for exemple on Windows OS) + idle_tag = 'user' not in self.stats # Header msg = '{0:8}'.format(_("CPU")) ret.append(self.curse_add_line(msg, "TITLE")) # Total CPU usage msg = '{0:>6.1%}'.format((100 - self.stats['idle']) / 100) - ret.append(self.curse_add_line(msg)) + if idle_tag: + ret.append(self.curse_add_line(msg, self.get_alert_log((100 - self.stats['idle']) / 100, header="system"))) + else: + ret.append(self.curse_add_line(msg)) # Nice CPU if 'nice' in self.stats: msg = ' {0:8}'.format(_("nice:")) @@ -152,7 +165,12 @@ class Plugin(GlancesPlugin): msg = '{0:8}'.format(_("user:")) ret.append(self.curse_add_line(msg)) msg = '{0:>6.1%}'.format(self.stats['user'] / 100) - ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['user'], header="user"))) + ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['user'], header="user"))) + elif 'idle' in self.stats: + msg = '{0:8}'.format(_("idle:")) + ret.append(self.curse_add_line(msg)) + msg = '{0:>6.1%}'.format(self.stats['idle'] / 100) + ret.append(self.curse_add_line(msg)) # IRQ CPU if 'irq' in self.stats: msg = ' {0:8}'.format(_("irq:")) @@ -162,11 +180,16 @@ class Plugin(GlancesPlugin): # New line ret.append(self.curse_new_line()) # System CPU - if 'system' in self.stats: + if 'system' in self.stats and not idle_tag: msg = '{0:8}'.format(_("system:")) ret.append(self.curse_add_line(msg)) msg = '{0:>6.1%}'.format(self.stats['system'] / 100) ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['system'], header="system"))) + else: + msg = '{0:8}'.format(_("core:")) + ret.append(self.curse_add_line(msg)) + msg = '{0:>6}'.format(self.stats['nb_log_core']) + ret.append(self.curse_add_line(msg)) # IOWait CPU if 'iowait' in self.stats: msg = ' {0:8}'.format(_("iowait:")) @@ -176,7 +199,7 @@ class Plugin(GlancesPlugin): # New line ret.append(self.curse_new_line()) # Idle CPU - if 'idle' in self.stats: + if 'idle' in self.stats and not idle_tag: msg = '{0:8}'.format(_("idle:")) ret.append(self.curse_add_line(msg)) msg = '{0:>6.1%}'.format(self.stats['idle'] / 100) diff --git a/glances/plugins/glances_mem.py b/glances/plugins/glances_mem.py index db69b980..1983e3a1 100644 --- a/glances/plugins/glances_mem.py +++ b/glances/plugins/glances_mem.py @@ -117,9 +117,9 @@ class Plugin(GlancesPlugin): except KeyError: self.reset() else: - for fs in fs_stat: - # Memory stats are grabed in the same OID table (ignore it) - if fs == 'Virtual Memory': + for fs in fs_stat: + # The Physical Memory gives statistics on RAM usage and availability. + if fs == 'Physical Memory': self.stats['total'] = int(fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit']) self.stats['used'] = int(fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit']) self.stats['percent'] = float(self.stats['used'] * 100 / self.stats['total']) diff --git a/glances/plugins/glances_memswap.py b/glances/plugins/glances_memswap.py index 1d0091b3..cfe876c7 100644 --- a/glances/plugins/glances_memswap.py +++ b/glances/plugins/glances_memswap.py @@ -26,8 +26,12 @@ import psutil # SNMP OID # Total Swap Size: .1.3.6.1.4.1.2021.4.3.0 # Available Swap Space: .1.3.6.1.4.1.2021.4.4.0 -snmp_oid = {'total': '1.3.6.1.4.1.2021.4.3.0', - 'free': '1.3.6.1.4.1.2021.4.4.0'} +snmp_oid = {'default': {'total': '1.3.6.1.4.1.2021.4.3.0', + 'free': '1.3.6.1.4.1.2021.4.4.0'}, + 'windows': {'mnt_point': '1.3.6.1.2.1.25.2.3.1.3', + 'alloc_unit': '1.3.6.1.2.1.25.2.3.1.4', + 'size': '1.3.6.1.2.1.25.2.3.1.5', + 'used': '1.3.6.1.2.1.25.2.3.1.6'}} class Plugin(GlancesPlugin): @@ -80,21 +84,39 @@ class Plugin(GlancesPlugin): self.stats[swap] = getattr(sm_stats, swap) elif self.get_input() == 'snmp': # Update stats using SNMP - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid) - - if self.stats['total'] == '': - self.reset() - return self.stats - - for key in self.stats.iterkeys(): - if self.stats[key] != '': - self.stats[key] = float(self.stats[key]) * 1024 - - # used=total-free - self.stats['used'] = self.stats['total'] - self.stats['free'] - - # percent: the percentage usage calculated as (total - available) / total * 100. - self.stats['percent'] = float((self.stats['total'] - self.stats['free']) / self.stats['total'] * 100) + if self.get_short_system_name() == 'windows': + # Mem stats for Windows OS are stored in the FS table + try: + fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], + bulk=True) + except KeyError: + self.reset() + else: + for fs in fs_stat: + # The virtual memory concept is used by the operating system to extend (virtually) the physical + # memory and thus to run more programs by swapping unused memory zone (page) to a disk file. + if fs == 'Virtual Memory': + self.stats['total'] = int(fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit']) + self.stats['used'] = int(fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit']) + self.stats['percent'] = float(self.stats['used'] * 100 / self.stats['total']) + self.stats['free'] = self.stats['total'] - self.stats['used'] + break + else: + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid) + + if self.stats['total'] == '': + self.reset() + return self.stats + + for key in self.stats.iterkeys(): + if self.stats[key] != '': + self.stats[key] = float(self.stats[key]) * 1024 + + # used=total-free + self.stats['used'] = self.stats['total'] - self.stats['free'] + + # percent: the percentage usage calculated as (total - available) / total * 100. + self.stats['percent'] = float((self.stats['total'] - self.stats['free']) / self.stats['total'] * 100) return self.stats -- cgit v1.2.3 From 3980730150d71b8eb9a084f6a0795a8866a911f7 Mon Sep 17 00:00:00 2001 From: Nicolargo Date: Fri, 27 Jun 2014 20:41:05 +0200 Subject: First try for ESXi --- glances/core/glances_stats.py | 5 +++-- glances/plugins/glances_cpu.py | 7 ++++--- glances/plugins/glances_mem.py | 15 ++++++++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/glances/core/glances_stats.py b/glances/core/glances_stats.py index 9ae35a87..e785a02b 100644 --- a/glances/core/glances_stats.py +++ b/glances/core/glances_stats.py @@ -28,10 +28,11 @@ from glances.core.glances_globals import plugins_path, sys_path # SNMP OID regexp pattern to short system name dict oid_to_short_system_name = {'.*Linux.*': 'linux', - '.*BSD.*': 'bsd', '.*Darwin.*': 'mac', + '.*BSD.*': 'bsd', '.*Windows.*': 'windows', - '.*Cisco.*': 'cisco'} + '.*Cisco.*': 'cisco', + '.*VMware ESXi.*': 'esxi'} class GlancesStats(object): diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 8ca12648..58d7f686 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -30,7 +30,8 @@ import psutil snmp_oid = {'default': {'user': '1.3.6.1.4.1.2021.11.9.0', 'system': '1.3.6.1.4.1.2021.11.10.0', 'idle': '1.3.6.1.4.1.2021.11.11.0'}, - 'windows': {'percent': '1.3.6.1.2.1.25.3.3.1.2'}} + 'windows': {'percent': '1.3.6.1.2.1.25.3.3.1.2'}, + 'esxi': {'percent': '1.3.6.1.2.1.25.3.3.1.2'}} class Plugin(GlancesPlugin): @@ -92,8 +93,8 @@ class Plugin(GlancesPlugin): elif self.get_input() == 'snmp': # Update stats using SNMP - if self.get_short_system_name() == 'windows': - # Windows + if self.get_short_system_name() in ('windows', 'esxi'): + # Windows or VMWare ESXi # You can find the CPU utilization of windows system by querying the oid # Give also the number of core (number of element in the table) # print snmp_oid[self.get_short_system_name()] diff --git a/glances/plugins/glances_mem.py b/glances/plugins/glances_mem.py index 1983e3a1..aebe3d7f 100644 --- a/glances/plugins/glances_mem.py +++ b/glances/plugins/glances_mem.py @@ -39,7 +39,11 @@ snmp_oid = {'default': {'total': '1.3.6.1.4.1.2021.4.5.0', 'windows': {'mnt_point': '1.3.6.1.2.1.25.2.3.1.3', 'alloc_unit': '1.3.6.1.2.1.25.2.3.1.4', 'size': '1.3.6.1.2.1.25.2.3.1.5', - 'used': '1.3.6.1.2.1.25.2.3.1.6'}} + 'used': '1.3.6.1.2.1.25.2.3.1.6'}, + 'esxi': {'mnt_point': '1.3.6.1.2.1.25.2.3.1.3', + 'alloc_unit': '1.3.6.1.2.1.25.2.3.1.4', + 'size': '1.3.6.1.2.1.25.2.3.1.5', + 'used': '1.3.6.1.2.1.25.2.3.1.6'}} class Plugin(GlancesPlugin): @@ -109,8 +113,8 @@ class Plugin(GlancesPlugin): self.stats['used'] = self.stats['total'] - self.stats['free'] elif self.get_input() == 'snmp': # Update stats using SNMP - if self.get_short_system_name() == 'windows': - # Mem stats for Windows OS are stored in the FS table + if self.get_short_system_name() in ('windows', 'esxi'): + # Mem stats for Windows|Vmware Esxi are stored in the FS table try: fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], bulk=True) @@ -118,8 +122,9 @@ class Plugin(GlancesPlugin): self.reset() else: for fs in fs_stat: - # The Physical Memory gives statistics on RAM usage and availability. - if fs == 'Physical Memory': + # The Physical Memory (Windows) or Real Memory (VmWare) + # gives statistics on RAM usage and availability. + if fs in ('Physical Memory', 'Real Memory'): self.stats['total'] = int(fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit']) self.stats['used'] = int(fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit']) self.stats['percent'] = float(self.stats['used'] * 100 / self.stats['total']) -- cgit v1.2.3 From c39789b96c98ce5e74be10b9c8b7c7a6b8b6e8f0 Mon Sep 17 00:00:00 2001 From: Nicolargo Date: Sun, 29 Jun 2014 14:13:52 +0200 Subject: Side bar use more space in SNMP mode --- glances/outputs/glances_curses.py | 17 ++++-- glances/plugins/glances_fs.py | 21 +++++--- glances/plugins/glances_memswap.py | 2 +- glances/plugins/glances_network.py | 18 ++++--- glances/plugins/glances_plugin.py | 32 +++++++++--- glances/plugins/glances_processlist.py | 94 ++++++++++++++++++++++------------ 6 files changed, 127 insertions(+), 57 deletions(-) diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index d37f6a1d..9d5f32cb 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -304,23 +304,30 @@ class GlancesCurses(object): stats_memswap = stats.get_plugin('memswap').get_stats_display() l += self.get_stats_display_width(stats_load) + self.get_stats_display_width(stats_mem) + self.get_stats_display_width(stats_memswap) # Space between column - if screen_x > (3 * self.space_between_column + l): - self.space_between_column = int((screen_x - l) / 3) + space_number = int(stats_load['msgdict'] != []) + int(stats_mem['msgdict'] != []) + int(stats_memswap['msgdict'] != []) + if screen_x > (space_number * self.space_between_column + l): + self.space_between_column = int((screen_x - l) / space_number) # Display if self.args.percpu: self.display_plugin(stats_percpu) else: self.display_plugin(stats_cpu, display_optional=(screen_x >= 80)) self.display_plugin(stats_load) - self.display_plugin(stats_mem, display_optional=(screen_x >= (3 * self.space_between_column + l))) + self.display_plugin(stats_mem, display_optional=(screen_x >= (space_number * self.space_between_column + l))) self.display_plugin(stats_memswap) # Space between column self.space_between_column = 3 # Display left sidebar (NETWORK+DISKIO+FS+SENSORS) - self.display_plugin(stats.get_plugin('network').get_stats_display(args=self.args)) + if cs_status == 'SNMP': + # No process list + # More space for others plugins + plugin_max_width = 43 + else: + plugin_max_width = None + self.display_plugin(stats.get_plugin('network').get_stats_display(args=self.args, max_width=plugin_max_width)) self.display_plugin(stats.get_plugin('diskio').get_stats_display(args=self.args)) - self.display_plugin(stats.get_plugin('fs').get_stats_display(args=self.args)) + self.display_plugin(stats.get_plugin('fs').get_stats_display(args=self.args, max_width=plugin_max_width)) self.display_plugin(stats.get_plugin('sensors').get_stats_display(args=self.args)) # Display last line (currenttime) self.display_plugin(stats.get_plugin('now').get_stats_display()) diff --git a/glances/plugins/glances_fs.py b/glances/plugins/glances_fs.py index 26a867b1..0db97189 100644 --- a/glances/plugins/glances_fs.py +++ b/glances/plugins/glances_fs.py @@ -150,7 +150,7 @@ class Plugin(GlancesPlugin): return self.stats - def msg_curse(self, args=None): + def msg_curse(self, args=None, max_width=None): """Return the dict to display in the curse interface.""" # Init the return message ret = [] @@ -159,9 +159,16 @@ class Plugin(GlancesPlugin): if self.stats == [] or args.disable_fs: return ret + # Max size for the fsname name + if max_width is not None and max_width >= 23: + # Interface size name = max_width - space for interfaces bitrate + fsname_max_width = max_width - 14 + else: + fsname_max_width = 9 + # Build the string message # Header - msg = '{0:9}'.format(_("FILE SYS")) + msg = '{0:{width}}'.format(_("FILE SYS"), width=fsname_max_width) ret.append(self.curse_add_line(msg, "TITLE")) msg = '{0:>7}'.format(_("Used")) ret.append(self.curse_add_line(msg)) @@ -172,17 +179,17 @@ class Plugin(GlancesPlugin): for i in sorted(self.stats, key=lambda fs: fs['mnt_point']): # New line ret.append(self.curse_new_line()) - if i['device_name'] == '': + if i['device_name'] == '' or i['device_name'] == 'none': mnt_point = i['mnt_point'] - elif len(i['mnt_point']) + len(i['device_name'].split('/')[-1]) <= 6: + elif len(i['mnt_point']) + len(i['device_name'].split('/')[-1]) <= fsname_max_width - 3: # If possible concatenate mode info... Glances touch inside :) mnt_point = i['mnt_point'] + ' (' + i['device_name'].split('/')[-1] + ')' - elif len(i['mnt_point']) > 9: + elif len(i['mnt_point']) > fsname_max_width: # Cut mount point name if it is too long - mnt_point = '_' + i['mnt_point'][-8:] + mnt_point = '_' + i['mnt_point'][-fsname_max_width+1:] else: mnt_point = i['mnt_point'] - msg = '{0:9}'.format(mnt_point) + msg = '{0:{width}}'.format(mnt_point, width=fsname_max_width) ret.append(self.curse_add_line(msg)) msg = '{0:>7}'.format(self.auto_unit(i['used'])) ret.append(self.curse_add_line(msg, self.get_alert(i['used'], max=i['size']))) diff --git a/glances/plugins/glances_memswap.py b/glances/plugins/glances_memswap.py index cfe876c7..4b656614 100644 --- a/glances/plugins/glances_memswap.py +++ b/glances/plugins/glances_memswap.py @@ -102,7 +102,7 @@ class Plugin(GlancesPlugin): self.stats['free'] = self.stats['total'] - self.stats['used'] break else: - self.stats = self.set_stats_snmp(snmp_oid=snmp_oid) + self.stats = self.set_stats_snmp(snmp_oid=snmp_oid['default']) if self.stats['total'] == '': self.reset() diff --git a/glances/plugins/glances_network.py b/glances/plugins/glances_network.py index 5dd5f515..4c515611 100644 --- a/glances/plugins/glances_network.py +++ b/glances/plugins/glances_network.py @@ -174,9 +174,8 @@ class Plugin(GlancesPlugin): return self.stats - def msg_curse(self, args=None): + def msg_curse(self, args=None, max_width=None): """Return the dict to display in the curse interface.""" - # !!! TODO: Add alert on network interface bitrate # Init the return message ret = [] @@ -185,9 +184,16 @@ class Plugin(GlancesPlugin): if self.stats == [] or args.disable_network: return ret + # Max size for the interface name + if max_width is not None and max_width >= 23: + # Interface size name = max_width - space for interfaces bitrate + ifname_max_width = max_width - 14 + else: + ifname_max_width = 9 + # Build the string message # Header - msg = '{0:9}'.format(_("NETWORK")) + msg = '{0:{width}}'.format(_("NETWORK"), width=ifname_max_width) ret.append(self.curse_add_line(msg, "TITLE")) if args.network_cumul: # Cumulative stats @@ -219,9 +225,9 @@ class Plugin(GlancesPlugin): continue # Format stats ifname = i['interface_name'].split(':')[0] - if len(ifname) > 9: + if len(ifname) > ifname_max_width: # Cut interface name if it is too long - ifname = '_' + ifname[-8:] + ifname = '_' + ifname[-ifname_max_width+1:] if args.byte: # Bytes per second (for dummy) if args.network_cumul: @@ -248,7 +254,7 @@ class Plugin(GlancesPlugin): int(i['tx'] // i['time_since_update'] * 8)) + "b" # New line ret.append(self.curse_new_line()) - msg = '{0:9}'.format(ifname) + msg = '{0:{width}}'.format(ifname, width=ifname_max_width) ret.append(self.curse_add_line(msg)) if args.network_sum: msg = '{0:>14}'.format(sx) diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index 36f16116..e3f7a8a3 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -268,11 +268,11 @@ class GlancesPlugin(object): """Return True if the value is in the hide configuration list.""" return value in self.get_hide(header=header) - def msg_curse(self, args): + def msg_curse(self, args=None, max_width=None): """Return default string to display in the curse interface.""" return [self.curse_add_line(str(self.stats))] - def get_stats_display(self, args=None): + def get_stats_display(self, args=None, max_width=None): """Return a dict with all the information needed to display the stat. key | description @@ -293,10 +293,18 @@ class GlancesPlugin(object): if hasattr(self, 'line_curse'): line_curse = self.line_curse - return {'display': display_curse, - 'msgdict': self.msg_curse(args), - 'column': column_curse, - 'line': line_curse} + if max_width is not None: + ret = {'display': display_curse, + 'msgdict': self.msg_curse(args, max_width=max_width), + 'column': column_curse, + 'line': line_curse} + else: + ret = {'display': display_curse, + 'msgdict': self.msg_curse(args), + 'column': column_curse, + 'line': line_curse} + + return ret def curse_add_line(self, msg, decoration="DEFAULT", optional=False, splittable=False): """Return a dict with: { 'msg': msg, 'decoration': decoration, 'optional': False }. @@ -328,6 +336,18 @@ class GlancesPlugin(object): """Go to a new line.""" return self.curse_add_line('\n') + def set_curse_column(self, column): + """Set the Curse column + Enter -1 to right align + """ + self.column_curse = column + + def set_curse_line(self, line): + """Set the Curse line + Enter -1 to right align + """ + self.line_curse = line + def auto_unit(self, number, low_precision=False): """Make a nice human-readable string out of number. diff --git a/glances/plugins/glances_processlist.py b/glances/plugins/glances_processlist.py index 348ea4a6..62a41010 100644 --- a/glances/plugins/glances_processlist.py +++ b/glances/plugins/glances_processlist.py @@ -63,10 +63,9 @@ class Plugin(GlancesPlugin): # Update stats using the standard system lib # Note: Update is done in the processcount plugin # Just return the processes list - self.stats = glances_processes.getlist() + self.stats = glances_processes.getlist() elif self.get_input() == 'snmp': - # Update stats using SNMP - # !!! TODO + # No SNMP grab for processes pass return self.stats @@ -124,42 +123,68 @@ class Plugin(GlancesPlugin): for p in self.sortlist(process_sort_key): ret.append(self.curse_new_line()) # CPU - msg = '{0:>6.1f}'.format(p['cpu_percent']) - ret.append(self.curse_add_line(msg, - self.get_alert(p['cpu_percent'], header="cpu"))) + if 'cpu_percent' in p: + msg = '{0:>6.1f}'.format(p['cpu_percent']) + ret.append(self.curse_add_line(msg, + self.get_alert(p['cpu_percent'], header="cpu"))) + else: + msg = '{0:>6}'.format('?') + ret.append(self.curse_add_line(msg)) # MEM - msg = '{0:>6.1f}'.format(p['memory_percent']) - ret.append(self.curse_add_line(msg, - self.get_alert(p['memory_percent'], header="mem"))) - # VMS - msg = '{0:>6}'.format(self.auto_unit(p['memory_info'][1], low_precision=False)) - ret.append(self.curse_add_line(msg, optional=True)) - # RSS - msg = '{0:>6}'.format(self.auto_unit(p['memory_info'][0], low_precision=False)) - ret.append(self.curse_add_line(msg, optional=True)) + if 'memory_percent' in p: + msg = '{0:>6.1f}'.format(p['memory_percent']) + ret.append(self.curse_add_line(msg, + self.get_alert(p['memory_percent'], header="mem"))) + else: + msg = '{0:>6}'.format('?') + ret.append(self.curse_add_line(msg)) + # VMS/RSS + if 'memory_info' in p: + # VMS + msg = '{0:>6}'.format(self.auto_unit(p['memory_info'][1], low_precision=False)) + ret.append(self.curse_add_line(msg, optional=True)) + # RSS + msg = '{0:>6}'.format(self.auto_unit(p['memory_info'][0], low_precision=False)) + ret.append(self.curse_add_line(msg, optional=True)) + else: + msg = '{0:>6}'.format('?') + ret.append(self.curse_add_line(msg)) + ret.append(self.curse_add_line(msg)) # PID msg = '{0:>6}'.format(p['pid']) ret.append(self.curse_add_line(msg)) # USER - # docker internal users are displayed as ints only, therefore str() - msg = ' {0:9}'.format(str(p['username'])[:9]) - ret.append(self.curs