def run(self, stat_name, criticity, commands, mustache_dict=None): """Run the commands (in background). - stats_name: plugin_name (+ header) - criticity: criticity of the trigger - commands: a list of command line with optional {{mustache}} - mustache_dict: Plugin stats (can be use within {{mustache}}) Return True if the commands have been ran. """ if self.get(stat_name) == criticity or not self.start_timer.finished(): # Action already executed => Exit return False logger.debug("Run action {} for {} ({}) with stats {}".format( commands, stat_name, criticity, mustache_dict)) # Run all actions in background for cmd in commands: # Replace {{arg}} by the dict one (Thk to {Mustache}) if pystache_tag: cmd_full = pystache.render(cmd, mustache_dict) else: cmd_full = cmd # Execute the action logger.info("Action triggered for {} ({}): {}".format(stat_name, criticity, cmd_full)) logger.debug("Stats value for the trigger: {}".format(mustache_dict)) try: Popen(cmd_full, shell=True) except OSError as e: logger.error("Can't execute the action ({})".format(e)) self.set(stat_name, criticity) return True
def init(self): """Init the connection to the ES server.""" if not self.export_enable: return None try: es = Elasticsearch(hosts=['{}:{}'.format(self.host, self.port)]) except Exception as e: logger.critical( "Cannot connect to ElasticSearch server %s:%s (%s)" % (self.host, self.port, e)) sys.exit(2) else: logger.info("Connected to the ElasticSearch server %s:%s" % (self.host, self.port)) try: index_count = es.count(index=self.index)['count'] except Exception as e: # Index did not exist, it will be created at the first write # Create it... es.indices.create(self.index) else: logger.info( "There is already %s entries in the ElasticSearch %s index" % (index_count, self.index)) return es
def end(): """Stop Glances.""" worker.end() logger.info("Stop Glances (with CTRL-C)") # The end... sys.exit(0)
def main(): """Main entry point for Glances. Select the mode (standalone, client or server) Run it... """ # Log Glances and PSutil version logger.info('Start Glances {}'.format(__version__)) logger.info('{} {} and PSutil {} detected'.format( platform.python_implementation(), platform.python_version(), psutil_version)) # Share global var global core, worker # Create the Glances main instance core = GlMain() # Catch the CTRL-C signal signal.signal(signal.SIGINT, __signal_handler) # Init the worker worker = Worker(config=core.get_config(), args=core.get_args()) # Start the standalone (CLI) loop worker.run()
def filter(self, value): """Set the filter (as a sting) and compute the regular expression A filter could be one of the following: - python > Process name of cmd start with python - .*python.* > Process name of cmd contain python - username:nicolargo > Process of nicolargo user """ self._filter_input = value if value is None: self._filter = None self._filter_key = None else: new_filter = value.split(':') if len(new_filter) == 1: self._filter = new_filter[0] self._filter_key = None else: self._filter = new_filter[1] self._filter_key = new_filter[0] self._filter_re = None if self.filter is not None: logger.info("Set filter to {} on key {}".format( self.filter, self.filter_key)) # Compute the regular expression try: self._filter_re = re.compile(self.filter) logger.debug("Filter regex compilation OK: {}".format( self.filter)) except Exception as e: logger.error("Cannot compile filter regex: {} ({})".format( self.filter, e)) self._filter = None self._filter_re = None self._filter_key = None
def load(self, config): """Load the server list from the configuration file.""" server_list = [] if config is None: logger.debug( "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_value(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'] = '******' # By default, try empty (aka no) password 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 _init_history(self): '''Init the history option''' self.reset_history_tag = False self.graph_tag = False if self.args.export_graph: logger.info('Export graphs function enabled with output path %s' % self.args.path_graph) from gl.exports.graph import GlancesGraph self.glances_graph = GlancesGraph(self.args.path_graph) if not self.glances_graph.graph_enabled(): self.args.export_graph = False logger.error('Export graphs disabled')
def __init__(self, config=None, args=None): logger.debug("[Worker.__init__]") # Quiet mode self._quiet = args.quiet self.refresh_time = args.time # Init stats self.stats = Stats(config=config, args=args) # If process extended stats is disabled by user if not args.enable_process_extended: logger.debug("Extended stats for top process are disabled") gl_processes.disable_extended() else: logger.debug("Extended stats for top process are enabled") gl_processes.enable_extended() # Manage optionnal process filter if args.process_filter is not None: gl_processes.process_filter = args.process_filter if args.no_kernel_threads: # Ignore kernel threads in process list gl_processes.disable_kernel_threads() try: if args.process_tree: # Enable process tree view gl_processes.enable_tree() except AttributeError: pass # Initial system informations update self.stats.update() if self.quiet: logger.info("Quiet mode is ON: Nothing will be displayed") # In quiet mode, nothing is displayed gl_processes.max_processes = 0 else: # Default number of processes to displayed is set to 50 gl_processes.max_processes = 50 # Init screen self.screen = Screen(config=config, args=args)
def parse_tags(self, tags): """Parse tags into a dict. tags: a comma separated list of 'key:value' pairs. Example: foo:bar,spam:eggs dtags: a dict of tags. Example: {'foo': 'bar', 'spam': 'eggs'} """ dtags = {} if tags: try: dtags = dict([x.split(':') for x in tags.split(',')]) except ValueError: # one of the 'key:value' pairs was missing logger.info('Invalid tags passed: %s', tags) dtags = {} return dtags
def init(self): """Init the connection to the InfluxDB server.""" if not self.export_enable: return None # Cluster try: cluster = Cluster([self.host], port=int(self.port), protocol_version=int(self.protocol_version)) session = cluster.connect() except Exception as e: logger.critical( "Cannot connect to Cassandra cluster '%s:%s' (%s)" % (self.host, self.port, e)) sys.exit(2) # Keyspace try: session.set_keyspace(self.keyspace) except InvalidRequest as e: logger.info("Create keyspace {} on the Cassandra cluster".format( self.keyspace)) c = "CREATE KEYSPACE %s WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '%s' }" % ( self.keyspace, self.replication_factor) session.execute(c) session.set_keyspace(self.keyspace) logger.info( "Stats will be exported to Cassandra cluster {0} ({1}) in keyspace {2}" .format(cluster.metadata.cluster_name, cluster.metadata.all_hosts(), self.keyspace)) # Table try: session.execute( "CREATE TABLE %s (plugin text, time timeuuid, stat map<text,float>, PRIMARY KEY (plugin, time)) WITH CLUSTERING ORDER BY (time DESC)" % self.table) except: logger.debug("Cassandra table %s already exist" % self.table) return cluster, session
def init(self): """Init the connection to the InfluxDB server.""" if not self.export_enable: return None try: db = InfluxDBClient(host=self.host, port=self.port, username=self.user, password=self.password, database=self.db) get_all_db = [i['name'] for i in db.get_list_database()] self.version = INFLUXDB_09PLUS except InfluxDBClientError: # https://github.com/influxdb/influxdb-python/issues/138 logger.info("Trying fallback to InfluxDB v0.8") db = InfluxDBClient08(host=self.host, port=self.port, username=self.user, password=self.password, database=self.db) get_all_db = [i['name'] for i in db.get_list_database()] self.version = INFLUXDB_08 except InfluxDBClientError08 as e: logger.critical("Cannot connect to InfluxDB database '%s' (%s)" % (self.db, e)) sys.exit(2) if self.db in get_all_db: logger.info("Stats will be exported to InfluxDB server: {}".format( db._baseurl)) else: logger.critical( "InfluxDB database '%s' did not exist. Please create it" % self.db) sys.exit(2) return db
def __init__(self, config=None, args=None): """Init the CSV export IF.""" super(Export, self).__init__(config=config, args=args) # CSV file name self.csv_filename = args.export_csv # Set the CSV output file try: if PY3: self.csv_file = open(self.csv_filename, 'w', newline='') else: self.csv_file = open(self.csv_filename, 'wb') self.writer = csv.writer(self.csv_file) except IOError as e: logger.critical("Cannot create the CSV file: {}".format(e)) sys.exit(2) logger.info("Stats exported to CSV file: {}".format(self.csv_filename)) self.export_enable = True self.first_line = True
import os from gl.compat import iterkeys from gl.logger import logger try: from matplotlib import __version__ as matplotlib_version import matplotlib.pyplot as plt except ImportError: matplotlib_check = False logger.warning( 'Cannot load Matplotlib library. Please install it using "pip install matplotlib"' ) else: matplotlib_check = True logger.info('Load Matplotlib version %s' % matplotlib_version) class GlancesGraph(object): """Thanks to this class, Glances can export history to graphs.""" def __init__(self, output_folder): self.output_folder = output_folder def get_output_folder(self): """Return the output folder where the graph are generated.""" return self.output_folder def graph_enabled(self): """Return True if Glances can generate history graphs.""" return matplotlib_check
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) # 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 # Manage full quicklook option if args.full_quicklook: logger.info("Disable QuickLook menu") args.disable_quicklook = False args.disable_cpu = True args.disable_mem = True args.disable_swap = True args.disable_load = False # Manage disable_top option if args.disable_top: logger.info("Disable top menu") args.disable_quicklook = True args.disable_cpu = True args.disable_mem = True args.disable_swap = True args.disable_load = True # Control parameter and exit if it is not OK self.args = args # Check graph output path if args.export_graph and args.path_graph is not None: if not os.access(args.path_graph, os.W_OK): logger.critical( "Graphs output path {0} do not exist or is not writable". format(args.path_graph)) sys.exit(2) logger.debug("Graphs output path is set to {0}".format( args.path_graph)) # For export graph, history is mandatory if args.export_graph and args.disable_history: logger.critical("Can not export graph if history is disabled") sys.exit(2) # Disable HDDTemp if sensors are disabled if args.disable_sensors: args.disable_hddtemp = True logger.debug("Sensors and HDDTemp are disabled") return args
def __catch_key(self, return_to_browser=False): # Catch the pressed key self.pressedkey = self.get_key(self.term_window) # Actions... if self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'): # 'ESC'|'q' > Quit if return_to_browser: logger.info("Stop Glances client and return to the browser") else: self.end() logger.info("Stop Glances") sys.exit(0) elif self.pressedkey == 10: # 'ENTER' > Edit the process filter self.edit_filter = not self.edit_filter elif self.pressedkey == ord('0'): # '0' > Switch between IRIX and Solaris mode self.args.disable_irix = not self.args.disable_irix elif self.pressedkey == ord('1'): # '1' > Switch between CPU and PerCPU information self.args.percpu = not self.args.percpu elif self.pressedkey == ord('2'): # '2' > Enable/disable left sidebar self.args.disable_left_sidebar = not self.args.disable_left_sidebar elif self.pressedkey == ord('3'): # '3' > Enable/disable quicklook self.args.disable_quicklook = not self.args.disable_quicklook elif self.pressedkey == ord('4'): # '4' > Enable/disable all but quick look and load self.args.full_quicklook = not self.args.full_quicklook if self.args.full_quicklook: self.args.disable_quicklook = False self.args.disable_cpu = True self.args.disable_mem = True self.args.disable_swap = True else: self.args.disable_quicklook = False self.args.disable_cpu = False self.args.disable_mem = False self.args.disable_swap = False elif self.pressedkey == ord('5'): # '5' > Enable/disable top menu logger.info(self.args.disable_top) self.args.disable_top = not self.args.disable_top if self.args.disable_top: self.args.disable_quicklook = True self.args.disable_cpu = True self.args.disable_mem = True self.args.disable_swap = True self.args.disable_load = True else: self.args.disable_quicklook = False self.args.disable_cpu = False self.args.disable_mem = False self.args.disable_swap = False self.args.disable_load = False elif self.pressedkey == ord('/'): # '/' > Switch between short/long name for processes self.args.process_short_name = not self.args.process_short_name elif self.pressedkey == ord('a'): # 'a' > Sort processes automatically and reset to 'cpu_percent' gl_processes.auto_sort = True gl_processes.sort_key = 'cpu_percent' elif self.pressedkey == ord('A'): # 'A' > enable/disable AMP module self.args.disable_amps = not self.args.disable_amps elif self.pressedkey == ord('b'): # 'b' > Switch between bit/s and Byte/s for network IO self.args.byte = not self.args.byte elif self.pressedkey == ord('B'): # 'B' > Switch between bit/s and IO/s for Disk IO self.args.diskio_iops = not self.args.diskio_iops elif self.pressedkey == ord('c'): # 'c' > Sort processes by CPU usage gl_processes.auto_sort = False gl_processes.sort_key = 'cpu_percent' elif self.pressedkey == ord('d'): # 'd' > Show/hide disk I/O stats self.args.disable_diskio = not self.args.disable_diskio elif self.pressedkey == ord('D'): # 'D' > Show/hide Docker stats self.args.disable_docker = not self.args.disable_docker elif self.pressedkey == ord('e'): # 'e' > Enable/Disable extended stats for top process self.args.enable_process_extended = not self.args.enable_process_extended if not self.args.enable_process_extended: gl_processes.disable_extended() else: gl_processes.enable_extended() elif self.pressedkey == ord('E'): # 'E' > Erase the process filter logger.info("Erase process filter") gl_processes.process_filter = None elif self.pressedkey == ord('F'): # 'F' > Switch between FS available and free space self.args.fs_free_space = not self.args.fs_free_space elif self.pressedkey == ord('f'): # 'f' > Show/hide fs / folder stats self.args.disable_fs = not self.args.disable_fs self.args.disable_folder = not self.args.disable_folder elif self.pressedkey == ord('g'): # 'g' > Export graphs to file self.graph_tag = not self.graph_tag elif self.pressedkey == ord('h'): # 'h' > Show/hide help self.args.help_tag = not self.args.help_tag elif self.pressedkey == ord('i'): # 'i' > Sort processes by IO rate (not available on OS X) gl_processes.auto_sort = False gl_processes.sort_key = 'io_counters' elif self.pressedkey == ord('I'): # 'I' > Show/hide IP module self.args.disable_ip = not self.args.disable_ip elif self.pressedkey == ord('l'): # 'l' > Show/hide log messages self.args.disable_log = not self.args.disable_log elif self.pressedkey == ord('m'): # 'm' > Sort processes by MEM usage gl_processes.auto_sort = False gl_processes.sort_key = 'memory_percent' elif self.pressedkey == ord('M'): # 'M' > Reset processes summary min/max self.args.reset_minmax_tag = not self.args.reset_minmax_tag elif self.pressedkey == ord('n'): # 'n' > Show/hide network stats self.args.disable_network = not self.args.disable_network elif self.pressedkey == ord('p'): # 'p' > Sort processes by name gl_processes.auto_sort = False gl_processes.sort_key = 'name' elif self.pressedkey == ord('P'): # 'P' > Disable ports scan plugins self.args.disable_ports = not self.args.disable_ports elif self.pressedkey == ord('Q'): self.args.disable_irq = not self.args.disable_irq elif self.pressedkey == ord('r'): # 'r' > Reset history self.reset_history_tag = not self.reset_history_tag elif self.pressedkey == ord('R'): # 'R' > Hide RAID plugins self.args.disable_raid = not self.args.disable_raid elif self.pressedkey == ord('s'): # 's' > Show/hide sensors stats (Linux-only) self.args.disable_sensors = not self.args.disable_sensors elif self.pressedkey == ord('t'): # 't' > Sort processes by TIME usage gl_processes.auto_sort = False gl_processes.sort_key = 'cpu_times' elif self.pressedkey == ord('T'): # 'T' > View network traffic as sum Rx+Tx self.args.network_sum = not self.args.network_sum elif self.pressedkey == ord('u'): # 'u' > Sort processes by USER gl_processes.auto_sort = False gl_processes.sort_key = 'username' elif self.pressedkey == ord('U'): # 'U' > View cumulative network I/O (instead of bitrate) self.args.network_cumul = not self.args.network_cumul elif self.pressedkey == ord('w'): # 'w' > Delete finished warning logs glances_logs.clean() elif self.pressedkey == ord('x'): # 'x' > Delete finished warning and critical logs glances_logs.clean(critical=True) elif self.pressedkey == ord('z'): # 'z' > Enable/Disable processes stats (count + list + AMPs) # Enable/Disable display self.args.disable_process = not self.args.disable_process # Enable/Disable update if self.args.disable_process: gl_processes.disable() else: gl_processes.enable() # Return the key code return self.pressedkey