def reset_stats_history(self): """Reset the stats history (dict of list)""" if self.args is not None and self.args.enable_history and self.get_items_history_list() is not None: reset_list = [i['name'] for i in self.get_items_history_list()] logger.debug("Reset history for plugin {0} (items: {0})".format(self.plugin_name, reset_list)) self.stats_history = {} return self.stats_history
def __init__(self, config=None, args=None): # Init stats self.stats = GlancesStats(config=config, args=args) # Default number of processes to displayed is set to 20 glances_processes.set_max_processes(20) # If process extended stats is disabled by user if args.disable_process_extended: logger.info(_("Extended stats for top process is disabled")) glances_processes.disable_extended() else: logger.debug( _("Extended stats for top process is enabled (default behavor)" )) glances_processes.enable_extended() # Manage optionnal process filter if args.process_filter is not None: glances_processes.set_process_filter(args.process_filter) # Initial system informations update self.stats.update() # Init CSV output if args.output_csv is not None: from glances.outputs.glances_csv import GlancesCSV self.csvoutput = GlancesCSV(args=args) self.csv_tag = True else: self.csv_tag = False # Init screen self.screen = GlancesCurses(args=args)
def __init__(self, config=None, args=None, timeout=7, return_to_browser=False): # Store the arg/config self.args = args self.config = config # Client mode: self.set_mode() # Build the URI if args.password != "": uri = 'http://{0}:{1}@{2}:{3}'.format(args.username, args.password, args.client, args.port) else: uri = 'http://{0}:{1}'.format(args.client, args.port) logger.debug("Try to connect to {0}".format(uri)) # Try to connect to the URI transport = GlancesClientTransport() # Configure the server timeout transport.set_timeout(timeout) try: self.client = ServerProxy(uri, transport=transport) except Exception as e: msg = "Client couldn't create socket {0}: {1}".format(uri, e) if not return_to_browser: logger.critical(msg) sys.exit(2) else: logger.error(msg)
def __init__(self, config=None, args=None): # Init stats self.stats = GlancesStats(config=config, args=args) # Default number of processes to displayed is set to 50 glances_processes.set_max_processes(50) # If process extended stats is disabled by user if args.disable_process_extended: logger.info(_("Extended stats for top process is disabled")) glances_processes.disable_extended() else: logger.debug(_("Extended stats for top process is enabled (default behavor)")) glances_processes.enable_extended() # Manage optionnal process filter if args.process_filter is not None: glances_processes.set_process_filter(args.process_filter) # Initial system informations update self.stats.update() # Init CSV output if args.output_csv is not None: from glances.outputs.glances_csv import GlancesCSV self.csvoutput = GlancesCSV(args=args) self.csv_tag = True else: self.csv_tag = False # Init screen self.screen = GlancesCurses(args=args)
def init_stats_history(self): """Init the stats history (dict of list)""" ret = None if self.args is not None and self.args.enable_history and self.get_items_history_list() is not None: init_list = [i['name'] for i in self.get_items_history_list()] logger.debug("Stats history activated for plugin {0} (items: {0})".format(self.plugin_name, init_list)) ret = {} return ret
def wrapper(*args, **kw): ret = fct(*args, **kw) if is_py3: logger.debug("%s %s %s return %s" % (args[0].__class__.__name__, args[ 0].__class__.__module__[len('glances_'):], fct.__name__, ret)) else: logger.debug("%s %s %s return %s" % (args[0].__class__.__name__, args[ 0].__class__.__module__[len('glances_'):], fct.func_name, ret)) return ret
def __init__(self): """Init batteries stats.""" try: self.bat = batinfo.batteries() self.initok = True self.bat_list = [] self.update() except Exception as e: self.initok = False logger.debug("Cannot init GlancesGrabBat class (%s)" % e)
def reset_stats_history(self): """Reset the stats history (dict of list)""" if self.args is not None and self.args.enable_history and self.get_items_history_list() is not None: iList = [i['name'] for i in self.get_items_history_list()] logger.debug(_("Reset history for plugin %s (items: %s)") % (self.plugin_name, iList)) self.stats_history = {} # First column for the date self.stats_history['date'] = [] for i in self.get_items_history_list(): # One column per item self.stats_history[i['name']] = [] return self.stats_history
def remove_server(self, name): """Remove a server from the dict""" for i in self._server_list: if i['key'] == name: try: self._server_list.remove(i) logger.debug("Remove server %s from the list" % name) logger.debug("Updated servers list (%s servers): %s" % ( len(self._server_list), self._server_list)) except ValueError: logger.error( "Cannot remove server %s from the list" % name)
def init_stats_history(self): """Init the stats history (dict of list)""" ret = None if self.args is not None and self.args.enable_history and self.get_items_history_list() is not None: iList = [i['name'] for i in self.get_items_history_list()] logger.debug(_("Stats history activated for plugin %s (items: %s)") % (self.plugin_name, iList)) ret = {} # First column for the date ret['date'] = [] for i in self.get_items_history_list(): # One column per item ret[i['name']] = [] return ret
def add_server(self, name, ip, port): """Add a new server to the list""" new_server = {'key': name, # Zeroconf name with both hostname and port 'name': name.split(':')[0], # Short name 'ip': ip, # IP address seen by the client 'port': port, # TCP port 'username': '******', # Default username 'password': '', # Default password 'status': 'UNKNOWN', # Server status: 'UNKNOWN', 'OFFLINE', 'ONLINE', 'PROTECTED' 'type': 'DYNAMIC', # Server type: 'STATIC' or 'DYNAMIC' } self._server_list.append(new_server) logger.debug("Updated servers list (%s servers): %s" % (len(self._server_list), self._server_list))
def set_process_filter(self, value): """Set the process filter""" logger.info(_("Set process filter to %s") % value) self.process_filter = value if value is not None: try: self.process_filter_re = re.compile(value) logger.debug(_("Process filter regular expression compilation OK: %s") % self.get_process_filter()) except: logger.error(_("Can not compile process filter regular expression: %s") % value) self.process_filter_re = None else: self.process_filter_re = None return self.process_filter
def set_plugins(self, input_plugins): """Set the plugin list according to the Glances server.""" header = "glances_" for item in input_plugins: # Import the plugin plugin = __import__(header + item) # Add the plugin to the dictionary # The key is the plugin name # for example, the file glances_xxx.py # generate self._plugins_list["xxx"] = ... logger.debug(_("Init %s plugin") % item) self._plugins[item] = plugin.Plugin() # Restoring system path sys.path = sys_path
def get_key(self, window): # Catch ESC key AND numlock key (issue #163) keycode = [0, 0] keycode[0] = window.getch() keycode[1] = window.getch() if keycode != [-1, -1]: logger.debug("Keypressed (code: %s)" % keycode) if keycode[0] == 27 and keycode[1] != -1: # Do not escape on specials keys return -1 else: return keycode[0]
def set_process_filter(self, value): """Set the process filter""" logger.info("Set process filter to {0}".format(value)) self.process_filter = value if value is not None: try: self.process_filter_re = re.compile(value) logger.debug("Process filter regex compilation OK: {0}".format(self.get_process_filter())) except Exception: logger.error("Cannot compile process filter regex: {0}".format(value)) self.process_filter_re = None else: self.process_filter_re = None return self.process_filter
def __init__(self, config=None, args=None): # Init stats self.stats = GlancesStats(config=config, args=args) # If configured, set the maximum processes number to display try: max_processes = int( self.stats.get_plugin('processlist').get_conf_value( 'max_processes')) logger.debug( _("Limit maximum displayed processes to %s") % max_processes) except: max_processes = None logger.warning( _("Maximum displayed processes is not configured (high CPU consumption)" )) glances_processes.set_max_processes(max_processes) # If process extended stats is disabled by user if args.disable_process_extended: logger.info(_("Extended stats for top process is disabled")) glances_processes.disable_extended() else: logger.debug( _("Extended stats for top process is enabled (default behavor)" )) glances_processes.enable_extended() # Manage optionnal process filter if args.process_filter is not None: glances_processes.set_process_filter(args.process_filter) # Initial system informations update self.stats.update() # Init CSV output if args.output_csv is not None: from glances.outputs.glances_csv import GlancesCSV self.csvoutput = GlancesCSV(args=args) self.csv_tag = True else: self.csv_tag = False # Init screen self.screen = GlancesCurses(args=args)
def load(self, config): """Load the server list from the configuration file""" server_list = [] if config is None: logger.warning("No configuration file available. Cannot load server list.") elif not config.has_section(self._section): logger.warning("No [%s] section in the configuration file. Cannot load server list." % self._section) else: logger.info("Start reading the [%s] section in the configuration file" % self._section) for i in range(1, 256): new_server = {} postfix = 'server_%s_' % str(i) # Read the server name (mandatory) for s in ['name', 'port', 'alias']: new_server[s] = config.get_raw_option(self._section, '%s%s' % (postfix, s)) if new_server['name'] is not None: # Manage optionnal information if new_server['port'] is None: new_server['port'] = 61209 new_server['username'] = '******' new_server['password'] = '' try: new_server['ip'] = gethostbyname(new_server['name']) except gaierror as e: logger.error("Cannot get IP address for server %s (%s)" % (new_server['name'], e)) continue new_server['key'] = new_server['name'] + ':' + new_server['port'] # Default status is 'UNKNOWN' new_server['status'] = 'UNKNOWN' # Server type is 'STATIC' new_server['type'] = 'STATIC' # Add the server to the list logger.debug("Add server %s to the static list" % new_server['name']) server_list.append(new_server) # Server list loaded logger.info("%s server(s) loaded from the configuration file" % len(server_list)) logger.debug("Static server list: %s" % server_list) return server_list
def set_process_filter(self, value): """Set the process filter""" logger.info(_("Set process filter to %s") % value) self.process_filter = value if value is not None: try: self.process_filter_re = re.compile(value) logger.debug( _("Process filter regular expression compilation OK: %s") % self.get_process_filter()) except: logger.error( _("Can not compile process filter regular expression: %s") % value) self.process_filter_re = None else: self.process_filter_re = None return self.process_filter
def __init__(self, config=None, args=None): # Init stats self.stats = GlancesStats(config=config, args=args) # Default number of processes to displayed is set to 50 glances_processes.set_max_processes(50) # If process extended stats is disabled by user if not args.enable_process_extended: logger.info("Extended stats for top process are disabled (default behavior)") glances_processes.disable_extended() else: logger.debug("Extended stats for top process are enabled") glances_processes.enable_extended() # Manage optionnal process filter if args.process_filter is not None: glances_processes.set_process_filter(args.process_filter) if (not is_windows) and args.no_kernel_threads: # Ignore kernel threads in process list glances_processes.disable_kernel_threads() if args.process_tree: # Enable process tree view glances_processes.enable_tree() # Initial system informations update self.stats.update() # Init CSV output if args.output_csv is not None: from glances.outputs.glances_csv import GlancesCSV self.csvoutput = GlancesCSV(args=args) self.csv_tag = True else: self.csv_tag = False # Init screen self.screen = GlancesCursesStandalone(args=args)
def load_plugins(self, args=None): """Load all plugins in the 'plugins' folder.""" header = "glances_" for item in os.listdir(plugins_path): if (item.startswith(header) and item.endswith(".py") and item != (header + "plugin.py")): # Import the plugin plugin = __import__(os.path.basename(item)[:-3]) # Add the plugin to the dictionary # The key is the plugin name # for example, the file glances_xxx.py # generate self._plugins_list["xxx"] = ... plugin_name = os.path.basename(item)[len(header):-3].lower() 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 # Log plugins list logger.debug(_("Available plugins list: %s"), self.getAllPlugins())
def __init__(self, config=None, args=None): # Init stats self.stats = GlancesStats(config=config, args=args) # If configured, set the maximum processes number to display try: max_processes = int(self.stats.get_plugin('processlist').get_conf_value('max_processes')) logger.debug(_("Limit maximum displayed processes to %s") % max_processes) except: max_processes = None logger.warning(_("Maximum displayed processes is not configured (high CPU consumption)")) glances_processes.set_max_processes(max_processes) # If process extended stats is disabled by user if args.disable_process_extended: logger.info(_("Extended stats for top process is disabled")) glances_processes.disable_extended() else: logger.debug(_("Extended stats for top process is enabled (default behavor)")) glances_processes.enable_extended() # Manage optionnal process filter if args.process_filter is not None: glances_processes.set_process_filter(args.process_filter) # Initial system informations update self.stats.update() # Init CSV output if args.output_csv is not None: from glances.outputs.glances_csv import GlancesCSV self.csvoutput = GlancesCSV(args=args) self.csv_tag = True else: self.csv_tag = False # Init screen self.screen = GlancesCurses(args=args)
def add_service(self, zeroconf, srv_type, srv_name): """Method called when a new Zeroconf client is detected Return True if the zeroconf client is a Glances server Note: the return code will never be used """ if srv_type != zeroconf_type: return False logger.debug("Check new Zeroconf server: %s / %s" % (srv_type, srv_name)) info = zeroconf.get_service_info(srv_type, srv_name) if info: new_server_ip = socket.inet_ntoa(info.address) new_server_port = info.port # Add server to the global dict self.servers.add_server(srv_name, new_server_ip, new_server_port) logger.info("New Glances server detected (%s from %s:%s)" % (srv_name, new_server_ip, new_server_port)) else: logger.warning( "New Glances server detected, but Zeroconf info failed to be grabbed") return True
def load_plugins(self, args=None): """Load all plugins in the 'plugins' folder.""" header = "glances_" for item in os.listdir(plugins_path): if (item.startswith(header) and item.endswith(".py") and item != (header + "plugin.py")): # Import the plugin plugin = __import__(os.path.basename(item)[:-3]) # Add the plugin to the dictionary # The key is the plugin name # for example, the file glances_xxx.py # generate self._plugins_list["xxx"] = ... plugin_name = os.path.basename(item)[len(header):-3].lower() 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 # Log plugins list logger.debug(_("Available plugins list: %s"), self.getAllPlugins())
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 %s selected" % (self.cursor_get() + 1)) self.set_active(self.cursor_get()) elif self.pressedkey == 259: # 'UP' > Up in the server list logger 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 generate_graph(self, stats): """ Generate graphs from plugins history Return the number of output files generated by the function """ if not self.graph_enabled(): return 0 index_all = 0 for p in stats.getAllPlugins(): h = stats.get_plugin(p).get_stats_history() # Data if h is None: # History (h) not available for plugin (p) continue # Init graph plt.clf() index_graph = 0 handles = [] labels = [] for i in stats.get_plugin(p).get_items_history_list(): if i['name'] in h.keys(): # The key exist # Add the curves in the current chart logger.debug("Generate graph: %s %s" % (p, i['name'])) index_graph += 1 # Labels handles.append(plt.Rectangle((0, 0), 1, 1, fc=self.get_graph_color(i), ec=self.get_graph_color(i), linewidth=2)) labels.append(self.get_graph_legend(i)) # Legend plt.ylabel(self.get_graph_yunit(i, pre_label='')) # Curves plt.grid(True) plt.plot_date(h['date'], h[i['name']], fmt='', drawstyle='default', linestyle='-', color=self.get_graph_color(i), xdate=True, ydate=False) if index_graph == 1: # Title only on top of the first graph plt.title(p.capitalize()) else: # The key did not exist # Find if anothers key ends with the key # Ex: key='tx' => 'ethernet_tx' # Add one curve per chart stats_history_filtered = [key for key in h.keys() if key.endswith('_' + i['name'])] stats_history_filtered.sort() logger.debug("Generate graphs: %s %s" % (p, stats_history_filtered)) if len(stats_history_filtered) > 0: # Create 'n' graph # Each graph iter through the stats plt.clf() index_item = 0 for k in stats_history_filtered: index_item += 1 plt.subplot( len(stats_history_filtered), 1, index_item) plt.ylabel(self.get_graph_yunit(i, pre_label=k)) plt.grid(True) plt.plot_date(h['date'], h[k], fmt='', drawstyle='default', linestyle='-', color=self.get_graph_color(i), xdate=True, ydate=False) if index_item == 1: # Title only on top of the first graph plt.title(p.capitalize() + ' ' + i['name']) # Save the graph to output file fig = plt.gcf() fig.set_size_inches(20, 5 * index_item) plt.xlabel('Date') plt.savefig( os.path.join(self.output_folder, 'glances_%s_%s.png' % (p, i['name'])), dpi=72) index_all += 1 if index_graph > 0: # Save the graph to output file fig = plt.gcf() fig.set_size_inches(20, 10) plt.legend(handles, labels, loc=1, prop={'size': 9}) plt.xlabel('Date') plt.savefig( os.path.join(self.output_folder, 'glances_%s.png' % (p)), dpi=72) index_all += 1 plt.close() return index_all
def load_limits(self, config): """Load the monitored list from the conf file.""" logger.debug("Monitor plugin configuration detected in the configuration file") self.glances_monitors = glancesMonitorList(config)
def parse_args(self): """Parse command line arguments.""" args = self.init_args().parse_args() # Load the configuration file, if it exists self.config = Config(args.conf_file) # Debug mode if args.debug: from logging import DEBUG logger.setLevel(DEBUG) # Client/server Port if args.port is None: if args.webserver: args.port = self.web_server_port else: args.port = self.server_port # Autodiscover if args.disable_autodiscover: logger.info("Auto discover mode is disabled") # In web server mode, defaul refresh time: 5 sec if args.webserver: args.time = 5 # Server or client login/password args.username = self.username if args.password_arg is not None: from hashlib import sha256 # Password is given as an argument # Hash with SHA256 # Only the SHA will be transmit on the network args.password = sha256(args.password_arg).hexdigest() elif args.password_prompt: # Interactive or file password if args.server: args.password = self.__get_password( description=_( "Define the password for the Glances server"), confirm=True) elif args.client: args.password = self.__get_password( description=_("Enter the Glances server password"), clear=True) else: # Default is no password args.password = self.password # By default help is hidden args.help_tag = False # Display Rx and Tx, not the sum for the network args.network_sum = False args.network_cumul = False # Control parameter and exit if it is not OK self.args = args # Filter is only available in standalone mode if args.process_filter is not None and not self.is_standalone(): logger.critical("Process filter is only available in standalone mode") sys.exit(2) # Check graph output path if args.enable_history and args.path_history is not None: if not os.access(args.path_history, os.W_OK): logger.critical("History output path {0} do not exist or is not writable".format(args.path_history)) sys.exit(2) logger.debug("History output path is set to {0}".format(args.path_history)) return args
def display(self, stats, cs_status="None"): """Display stats on the screen. stats: Stats database to display cs_status: "None": standalone or server mode "Connected": Client is connected to a Glances server "SNMP": Client is connected to a SNMP server "Disconnected": Client is disconnected from the server Return: True if the stats have been displayed False if the help have been displayed """ # Init the internal line/column for Glances Curses self.init_line_column() # Get the screen size screen_x = self.screen.getmaxyx()[1] screen_y = self.screen.getmaxyx()[0] # No processes list in SNMP mode if cs_status == 'SNMP': # so... more space for others plugins plugin_max_width = 43 else: plugin_max_width = None # Update the stats messages ########################### # Update the client server status self.args.cs_status = cs_status stats_system = stats.get_plugin('system').get_stats_display( args=self.args) stats_uptime = stats.get_plugin('uptime').get_stats_display() if self.args.percpu: stats_percpu = stats.get_plugin('percpu').get_stats_display() else: stats_cpu = stats.get_plugin('cpu').get_stats_display() stats_load = stats.get_plugin('load').get_stats_display() stats_mem = stats.get_plugin('mem').get_stats_display() stats_memswap = stats.get_plugin('memswap').get_stats_display() stats_network = stats.get_plugin('network').get_stats_display( args=self.args, max_width=plugin_max_width) stats_diskio = stats.get_plugin('diskio').get_stats_display( args=self.args) stats_fs = stats.get_plugin('fs').get_stats_display( args=self.args, max_width=plugin_max_width) stats_sensors = stats.get_plugin('sensors').get_stats_display( args=self.args) stats_now = stats.get_plugin('now').get_stats_display() stats_processcount = stats.get_plugin( 'processcount').get_stats_display(args=self.args) stats_monitor = stats.get_plugin('monitor').get_stats_display( args=self.args) stats_alert = stats.get_plugin('alert').get_stats_display( args=self.args) # Adapt number of processes to the available space max_processes_displayed = screen_y - 11 - self.get_stats_display_height( stats_alert) if not self.args.disable_process_extended: max_processes_displayed -= 4 if max_processes_displayed < 0: max_processes_displayed = 0 if glances_processes.get_max_processes() is None or \ glances_processes.get_max_processes() != max_processes_displayed: logger.debug( _("Set number of displayed processes to %s") % max_processes_displayed) glances_processes.set_max_processes(max_processes_displayed) stats_processlist = stats.get_plugin('processlist').get_stats_display( args=self.args) # Display the stats on the curses interface ########################################### # Help screen (on top of the other stats) if self.args.help_tag: # Display the stats... self.display_plugin( stats.get_plugin('help').get_stats_display(args=self.args)) # ... and exit return False # Display first line (system+uptime) self.new_line() l = self.get_stats_display_width( stats_system) + self.get_stats_display_width( stats_uptime) + self.space_between_column self.display_plugin(stats_system, display_optional=(screen_x >= l)) self.new_column() self.display_plugin(stats_uptime) # Display second line (CPU|PERCPU+LOAD+MEM+SWAP+<SUMMARY>) # CPU|PERCPU self.init_column() self.new_line() if self.args.percpu: l = self.get_stats_display_width(stats_percpu) else: l = self.get_stats_display_width(stats_cpu) 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 space_number = int(stats_load['msgdict'] != []) + int( stats_mem['msgdict'] != []) + int(stats_memswap['msgdict'] != []) if space_number == 0: space_number = 1 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.new_column() self.display_plugin(stats_load) self.new_column() self.display_plugin( stats_mem, display_optional=(screen_x >= (space_number * self.space_between_column + l))) self.new_column() self.display_plugin(stats_memswap) # Space between column self.space_between_column = 3 # Backup line position self.saved_line = self.next_line # Display left sidebar (NETWORK+DISKIO+FS+SENSORS+Current time) self.init_column() self.new_line() self.display_plugin(stats_network) self.new_line() self.display_plugin(stats_diskio) self.new_line() self.display_plugin(stats_fs) self.new_line() self.display_plugin(stats_sensors) self.new_line() self.display_plugin(stats_now) # If space available... if screen_x > 52: # Restore line position self.next_line = self.saved_line # Display right sidebar (PROCESS_COUNT+MONITORED+PROCESS_LIST+ALERT) self.new_column() self.new_line() self.display_plugin(stats_processcount) if glances_processes.get_process_filter( ) == None and cs_status == 'None': # Do not display stats monitor list if a filter exist self.new_line() self.display_plugin(stats_monitor) self.new_line() self.display_plugin( stats_processlist, display_optional=(screen_x > 102), display_additional=(is_mac == False), max_y=(screen_y - self.get_stats_display_height(stats_alert) - 2)) self.new_line() self.display_plugin(stats_alert) # History option # Generate history graph if self.history_tag and self.args.enable_history: self.display_popup( _("Graphs history generated in %s") % self.glances_history.get_output_folder()) self.glances_history.generate_graph(stats) elif self.reset_history_tag and self.args.enable_history: self.display_popup(_("Reset history")) self.glances_history.reset(stats) elif (self.history_tag or self.reset_history_tag) and not self.args.enable_history: self.display_popup( _("History disabled\nEnable it using --enable-history")) self.history_tag = False self.reset_history_tag = False # Display edit filter popup # Only in standalone mode (cs_status == 'None') if self.edit_filter and cs_status == 'None': new_filter = self.display_popup( _("Process filter pattern: "), is_input=True, input_value=glances_processes.get_process_filter()) glances_processes.set_process_filter(new_filter) elif self.edit_filter and cs_status != 'None': self.display_popup( _("Process filter only available in standalone mode")) self.edit_filter = False return True
# 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/>. """Battery plugin.""" # Import Glances libs from glances.core.glances_globals import logger from glances.plugins.glances_plugin import GlancesPlugin # Batinfo library (optional; Linux-only) try: import batinfo except ImportError: logger.debug(_("Cannot grab battery sensor. Missing BatInfo library.")) class Plugin(GlancesPlugin): """Glances' battery capacity plugin. stats is a list """ def __init__(self, args=None): """Init the plugin.""" GlancesPlugin.__init__(self, args=args) # Init the sensor class self.glancesgrabbat = GlancesGrabBat()
def display_popup(self, message, size_x=None, size_y=None, duration=3, is_input=False, input_size=30, input_value=None): """ If is_input is False: Display a centered popup with the given message during duration seconds If size_x and size_y: set the popup size else set it automatically Return True if the popup could be displayed If is_input is True: Display a centered popup with the given message and a input field If size_x and size_y: set the popup size else set it automatically Return the input string or None if the field is empty """ # Center the popup if size_x is None: size_x = len(message) + 4 # Add space for the input field if is_input: size_x += input_size if size_y is None: size_y = message.count('\n') + 1 + 4 screen_x = self.screen.getmaxyx()[1] screen_y = self.screen.getmaxyx()[0] if size_x > screen_x or size_y > screen_y: # No size to display the popup => abord return False pos_x = int((screen_x - size_x) / 2) pos_y = int((screen_y - size_y) / 2) # Create the popup popup = curses.newwin(size_y, size_x, pos_y, pos_x) # Fill the popup popup.border() # Add the message y = 0 for m in message.split('\n'): popup.addnstr(2 + y, 2, m, len(m)) y += 1 if is_input and not is_windows: # Create a subwindow for the text field subpop = popup.derwin(1, input_size, 2, 2 + len(m)) subpop.attron(self.__colors_list['FILTER']) # Init the field with the current value if input_value is not None: subpop.addnstr(0, 0, input_value, len(input_value)) # Display the popup popup.refresh() subpop.refresh() # Create the textbox inside the subwindows self.set_cursor(2) textbox = glances_textbox(subpop, insert_mode=False) textbox.edit() self.set_cursor(0) if textbox.gather() != '': logger.debug( _("User enters the following process filter patern: %s") % textbox.gather()) return textbox.gather()[:-1] else: logger.debug(_("User clears the process filter patern")) return None else: # Display the popup popup.refresh() curses.napms(duration * 1000) return True
# 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/>. """Battery plugin.""" # Import Glances libs from glances.core.glances_globals import logger from glances.plugins.glances_plugin import GlancesPlugin # Batinfo library (optional; Linux-only) try: import batinfo except ImportError: logger.debug("Batinfo library not found. Glances cannot grab battery info.") pass class Plugin(GlancesPlugin): """Glances' battery capacity plugin. stats is a list """ def __init__(self, args=None): """Init the plugin.""" GlancesPlugin.__init__(self, args=args) # Init the sensor class
def load_limits(self, config): """Load the monitored list from the conf file.""" logger.debug(_("Monitor plugin configuration detected in the configuration file")) self.glances_monitors = glancesMonitorList(config)
def display(self, stats, cs_status="None"): """Display stats on the screen. stats: Stats database to display cs_status: "None": standalone or server mode "Connected": Client is connected to a Glances server "SNMP": Client is connected to a SNMP server "Disconnected": Client is disconnected from the server Return: True if the stats have been displayed False if the help have been displayed """ # Init the internal line/column for Glances Curses self.init_line_column() # Get the screen size screen_x = self.screen.getmaxyx()[1] screen_y = self.screen.getmaxyx()[0] # No processes list in SNMP mode if cs_status == 'SNMP': # so... more space for others plugins plugin_max_width = 43 else: plugin_max_width = None # Update the stats messages ########################### # Update the client server status self.args.cs_status = cs_status stats_system = stats.get_plugin( 'system').get_stats_display(args=self.args) stats_uptime = stats.get_plugin('uptime').get_stats_display() if self.args.percpu: stats_percpu = stats.get_plugin('percpu').get_stats_display() else: stats_cpu = stats.get_plugin('cpu').get_stats_display() stats_load = stats.get_plugin('load').get_stats_display() stats_mem = stats.get_plugin('mem').get_stats_display() stats_memswap = stats.get_plugin('memswap').get_stats_display() stats_network = stats.get_plugin('network').get_stats_display( args=self.args, max_width=plugin_max_width) stats_diskio = stats.get_plugin( 'diskio').get_stats_display(args=self.args) stats_fs = stats.get_plugin('fs').get_stats_display( args=self.args, max_width=plugin_max_width) stats_sensors = stats.get_plugin( 'sensors').get_stats_display(args=self.args) stats_now = stats.get_plugin('now').get_stats_display() stats_processcount = stats.get_plugin( 'processcount').get_stats_display(args=self.args) stats_monitor = stats.get_plugin( 'monitor').get_stats_display(args=self.args) stats_alert = stats.get_plugin( 'alert').get_stats_display(args=self.args) # Adapt number of processes to the available space max_processes_displayed = screen_y - 11 - \ self.get_stats_display_height(stats_alert) if self.args.enable_process_extended and not self.args.process_tree: max_processes_displayed -= 4 if max_processes_displayed < 0: max_processes_displayed = 0 if glances_processes.get_max_processes() is None or \ glances_processes.get_max_processes() != max_processes_displayed: logger.debug("Set number of displayed processes to %s" % max_processes_displayed) glances_processes.set_max_processes(max_processes_displayed) stats_processlist = stats.get_plugin( 'processlist').get_stats_display(args=self.args) # Display the stats on the curses interface ########################################### # Help screen (on top of the other stats) if self.args.help_tag: # Display the stats... self.display_plugin( stats.get_plugin('help').get_stats_display(args=self.args)) # ... and exit return False # Display first line (system+uptime) self.new_line() l = self.get_stats_display_width( stats_system) + self.get_stats_display_width(stats_uptime) + self.space_between_column self.display_plugin(stats_system, display_optional=(screen_x >= l)) self.new_column() self.display_plugin(stats_uptime) # Display second line (CPU|PERCPU+LOAD+MEM+SWAP+<SUMMARY>) # CPU|PERCPU self.init_column() self.new_line() if self.args.percpu: l = self.get_stats_display_width(stats_percpu) else: l = self.get_stats_display_width(stats_cpu) 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 space_number = int(stats_load['msgdict'] != [ ]) + int(stats_mem['msgdict'] != []) + int(stats_memswap['msgdict'] != []) if space_number == 0: space_number = 1 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.new_column() self.display_plugin(stats_load) self.new_column() self.display_plugin(stats_mem, display_optional=( screen_x >= (space_number * self.space_between_column + l))) self.new_column() self.display_plugin(stats_memswap) # Space between column self.space_between_column = 3 # Backup line position self.saved_line = self.next_line # Display left sidebar (NETWORK+DISKIO+FS+SENSORS+Current time) self.init_column() if (not (self.args.disable_network and self.args.disable_diskio and self.args.disable_fs and self.args.disable_sensors)) \ and not self.args.disable_left_sidebar: self.new_line() self.display_plugin(stats_network) self.new_line() self.display_plugin(stats_diskio) self.new_line() self.display_plugin(stats_fs) self.new_line() self.display_plugin(stats_sensors) self.new_line() self.display_plugin(stats_now) # If space available... if screen_x > 52: # Restore line position self.next_line = self.saved_line # Display right sidebar # (PROCESS_COUNT+MONITORED+PROCESS_LIST+ALERT) self.new_column() self.new_line() self.display_plugin(stats_processcount) if glances_processes.get_process_filter() is None and cs_status == 'None': # Do not display stats monitor list if a filter exist self.new_line() self.display_plugin(stats_monitor) self.new_line() self.display_plugin(stats_processlist, display_optional=(screen_x > 102), display_additional=(not is_mac), max_y=(screen_y - self.get_stats_display_height(stats_alert) - 2)) self.new_line() self.display_plugin(stats_alert) # History option # Generate history graph if self.history_tag and self.args.enable_history: self.display_popup( _("Generate graphs history in %s\nPlease wait...") % self.glances_history.get_output_folder()) self.display_popup( _("Generate graphs history in %s\nDone: %s graphs generated") % (self.glances_history.get_output_folder(), self.glances_history.generate_graph(stats))) elif self.reset_history_tag and self.args.enable_history: self.display_popup(_("Reset history")) self.glances_history.reset(stats) elif (self.history_tag or self.reset_history_tag) and not self.args.enable_history: try: self.glances_history.graph_enabled() except Exception: self.display_popup( _("History disabled\nEnable it using --enable-history")) else: self.display_popup( _("History disabled\nPlease install MatPlotLib")) self.history_tag = False self.reset_history_tag = False # Display edit filter popup # Only in standalone mode (cs_status == 'None') if self.edit_filter and cs_status == 'None': new_filter = self.display_popup(_("Process filter pattern: "), is_input=True, input_value=glances_processes.get_process_filter()) glances_processes.set_process_filter(new_filter) elif self.edit_filter and cs_status != 'None': self.display_popup( _("Process filter only available in standalone mode")) self.edit_filter = False return True
def login(self, return_to_browser=False): """Logon to the server.""" ret = True if not self.args.snmp_force: # First of all, trying to connect to a Glances server self.set_mode('glances') client_version = None try: client_version = self.client.init() except socket.error as err: # Fallback to SNMP logger.error("Connection to Glances server failed (%s)" % err) self.set_mode('snmp') fallbackmsg = _("Trying fallback to SNMP...") if not return_to_browser: print(fallbackmsg) else: logger.info(fallbackmsg) except ProtocolError as err: # Others errors if str(err).find(" 401 ") > 0: msg = "Connection to server failed (bad password)" else: msg = "Connection to server failed ({0})".format(err) if not return_to_browser: logger.critical(msg) sys.exit(2) else: logger.error(msg) return False if self.get_mode() == 'glances' and version[:3] == client_version[:3]: # Init stats self.stats = GlancesStatsClient() self.stats.set_plugins(json.loads(self.client.getAllPlugins())) logger.debug( "Client version: %s / Server version: %s" % (version, client_version)) else: logger.error( "Client and server not compatible: Client version: %s / Server version: %s" % (version, client_version)) else: self.set_mode('snmp') if self.get_mode() == 'snmp': logger.info("Trying to grab stats by SNMP...") # Fallback to SNMP if needed from glances.core.glances_stats import GlancesStatsClientSNMP # Init stats self.stats = GlancesStatsClientSNMP(args=self.args) if not self.stats.check_snmp(): logger.error("Connection to SNMP server failed") if not return_to_browser: sys.exit(2) else: return False if ret: # Load limits from the configuration file # Each client can choose its owns limits self.stats.load_limits(self.config) # Init screen self.screen = GlancesCursesClient(args=self.args) # Return result return ret
def display_popup(self, message, size_x=None, size_y=None, duration=3, is_input=False, input_size=30, input_value=None): """ If is_input is False: Display a centered popup with the given message during duration seconds If size_x and size_y: set the popup size else set it automatically Return True if the popup could be displayed If is_input is True: Display a centered popup with the given message and a input field If size_x and size_y: set the popup size else set it automatically Return the input string or None if the field is empty """ # Center the popup sentence_list = message.split('\n') if size_x is None: size_x = len(max(sentence_list, key=len)) + 4 # Add space for the input field if is_input: size_x += input_size if size_y is None: size_y = len(sentence_list) + 4 screen_x = self.screen.getmaxyx()[1] screen_y = self.screen.getmaxyx()[0] if size_x > screen_x or size_y > screen_y: # No size to display the popup => abord return False pos_x = int((screen_x - size_x) / 2) pos_y = int((screen_y - size_y) / 2) # Create the popup popup = curses.newwin(size_y, size_x, pos_y, pos_x) # Fill the popup popup.border() # Add the message y = 0 for m in message.split('\n'): popup.addnstr(2 + y, 2, m, len(m)) y += 1 if is_input and not is_windows: # Create a subwindow for the text field subpop = popup.derwin(1, input_size, 2, 2 + len(m)) subpop.attron(self.colors_list['FILTER']) # Init the field with the current value if input_value is not None: subpop.addnstr(0, 0, input_value, len(input_value)) # Display the popup popup.refresh() subpop.refresh() # Create the textbox inside the subwindows self.set_cursor(2) textbox = GlancesTextbox(subpop, insert_mode=False) textbox.edit() self.set_cursor(0) if textbox.gather() != '': logger.debug( "User enters the following process filter patern: %s" % textbox.gather()) return textbox.gather()[:-1] else: logger.debug("User clears the process filter patern") return None else: # Display the popup popup.refresh() curses.napms(duration * 1000) return True
# 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/>. """Battery plugin.""" # Import Glances libs from glances.core.glances_globals import logger from glances.plugins.glances_plugin import GlancesPlugin # Batinfo library (optional; Linux-only) try: import batinfo except ImportError: logger.debug(_("Cannot grab battery sensor. Missing BatInfo library.")) class Plugin(GlancesPlugin): """Glances' battery capacity plugin. stats is a list """ def __init__(self, args=None): """Init the plugin.""" GlancesPlugin.__init__(self, args=args) # Init the sensor class self.glancesgrabbat = GlancesGrabBat() # We do not want to display the stat in a dedicated area
ServiceBrowser, ServiceInfo, Zeroconf ) zeroconf_tag = True except ImportError: zeroconf_tag = False # Import Glances libs from glances.core.glances_globals import appname, logger # Zeroconf 0.16 or higher is needed if zeroconf_tag: zeroconf_min_version = (0, 16, 0) zeroconf_version = tuple([int(num) for num in __zeroconf_version.split('.')]) logger.debug("Zeroconf version {0} detected.".format(__zeroconf_version)) if zeroconf_version < zeroconf_min_version: logger.critical("Please install zeroconf 0.16 or higher.") sys.exit(1) # Global var zeroconf_type = "_%s._tcp." % appname class AutoDiscovered(object): """Class to manage the auto discovered servers dict""" def __init__(self): # server_dict is a list of dict (JSON compliant) # [ {'key': 'zeroconf name', ip': '172.1.2.3', 'port': 61209, 'cpu': 3, 'mem': 34 ...} ... ]
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 servers available") elif len(servers_list) == 1: msg = _("One Glances server available") else: msg = _("%d Glances servers available" % 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'), 8], ['ip', _('IP'), 15], # ['port', _('PORT'), 5], ['hr_name', _('OS'), 16], ] y = 2 # Display table header cpt = 0 xc = x + 2 for c in 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 cpt += 1 y += 1 # If a servers has been deleted from the list... # ... and if the cursor is in the latest position if self.cursor_get() > len(servers_list) - 1: # Set the cursor position to the latest item self.cursor_set(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 as e: pass # Display line for server stats cpt = 0 xc = x # Is the line selected ? if line == self.cursor_get(): # Display cursor self.term_window.addnstr(y, xc, ">", screen_x - xc, self.colors_list['BOLD']) # Display alias instead of name server_stat # 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, "%s" % 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