Пример #1
0
def end():
    """Stop Glances."""
    mode.end()
    logger.info("Glances stopped with CTRL-C")

    # The end...
    sys.exit(0)
Пример #2
0
    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
Пример #3
0
    def login(self):
        """Logon to the server."""

        if self.args.snmp_force:
            # Force SNMP instead of Glances server
            self.client_mode = 'snmp'
        else:
            # First of all, trying to connect to a Glances server
            if not self._login_glances():
                return False

        # Try SNMP mode
        if self.client_mode == 'snmp':
            if not self._login_snmp():
                return False

        # Load limits from the configuration file
        # Each client can choose its owns limits
        logger.debug("Load limits from the client configuration file")
        self.stats.load_limits(self.config)

        # Init screen
        if self.quiet:
            # In quiet mode, nothing is displayed
            logger.info("Quiet mode is ON: Nothing will be displayed")
        else:
            self.screen = GlancesCursesClient(config=self.config, args=self.args)

        # Return True: OK
        return True
Пример #4
0
    def check_snmp(self):
        """Chek if SNMP is available on the server."""
        # Import the SNMP client class
        from glances.snmp import GlancesSNMPClient

        # Create an instance of the SNMP client
        clientsnmp = GlancesSNMPClient(host=self.args.client,
                                       port=self.args.snmp_port,
                                       version=self.args.snmp_version,
                                       community=self.args.snmp_community,
                                       user=self.args.snmp_user,
                                       auth=self.args.snmp_auth)

        # If we cannot 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'])
                logger.info("SNMP system name detected: {}".format(self.system_name))
            except KeyError:
                self.system_name = None
                logger.warning("Cannot detect SNMP system name")

        return ret
Пример #5
0
    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 {} ({}) in keyspace {}".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 Exception:
            logger.debug("Cassandra table %s already exist" % self.table)

        return cluster, session
Пример #6
0
def start(config, args):
    """Start Glances"""

    # Load mode
    global mode

    if core.is_standalone():
        from glances.standalone import GlancesStandalone as GlancesMode
    elif core.is_client():
        if core.is_client_browser():
            from glances.client_browser import GlancesClientBrowser as GlancesMode
        else:
            from glances.client import GlancesClient as GlancesMode
    elif core.is_server():
        from glances.server import GlancesServer as GlancesMode
    elif core.is_webserver():
        from glances.webserver import GlancesWebServer as GlancesMode

    # Init the mode
    logger.info("Start {} mode".format(GlancesMode.__name__))
    mode = GlancesMode(config=config, args=args)

    # Start the main loop
    mode.serve_forever()

    # Shutdown
    mode.end()
Пример #7
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

    # Create the Glances main instance
    core = GlancesMain()
    config = core.get_config()
    args = core.get_args()

    # Catch the CTRL-C signal
    signal.signal(signal.SIGINT, __signal_handler)

    # Glances can be ran in standalone, client or server mode
    start(config=config, args=args)
Пример #8
0
    def __init__(self, requestHandler=GlancesXMLRPCHandler,
                 cached_time=1,
                 config=None,
                 args=None):
        # Args
        self.args = args

        # Init the XML RPC server
        try:
            self.server = GlancesXMLRPCServer(args.bind_address, args.port, requestHandler)
        except Exception as e:
            logger.critical("Cannot start Glances server: {}".format(e))
            sys.exit(2)

        # The users dict
        # username / password couple
        # By default, no auth is needed
        self.server.user_dict = {}
        self.server.isAuth = False

        # Register functions
        self.server.register_introspection_functions()
        self.server.register_instance(GlancesInstance(cached_time, config))

        if not self.args.disable_autodiscover:
            # Note: The Zeroconf service name will be based on the hostname
            # Correct issue: Zeroconf problem with zeroconf service name #889
            self.autodiscover_client = GlancesAutoDiscoverClient(socket.gethostname().split('.', 1)[0], args)
        else:
            logger.info("Glances autodiscover announce is disabled")
Пример #9
0
    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
Пример #10
0
    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
Пример #11
0
    def init(self):
        """Init the connection to the CouchDB server."""
        if not self.export_enable:
            return None

        if self.user is None:
            server_uri = 'http://{}:{}/'.format(self.host,
                                                self.port)
        else:
            server_uri = 'http://{}:{}@{}:{}/'.format(self.user,
                                                      self.password,
                                                      self.host,
                                                      self.port)

        try:
            s = couchdb.Server(server_uri)
        except Exception as e:
            logger.critical("Cannot connect to CouchDB server %s (%s)" % (server_uri, e))
            sys.exit(2)
        else:
            logger.info("Connected to the CouchDB server %s" % server_uri)

        try:
            s[self.db]
        except Exception as e:
            # Database did not exist
            # Create it...
            s.create(self.db)
        else:
            logger.info("There is already a %s database" % self.db)

        return s
Пример #12
0
    def __catch_key(self, stats):
        # Catch the browser pressed key
        self.pressedkey = self.get_key(self.term_window)

        if self.pressedkey != -1:
            logger.debug("Key pressed. Code=%s" % self.pressedkey)

        # 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
            self.active_server = self.cursor
            logger.debug("Server {}/{} selected".format(self.cursor + 1, len(stats)))
        elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65:
            # 'UP' > Up in the server list
            self.cursor_up(stats)
            logger.debug("Server {}/{} selected".format(self.cursor + 1, len(stats)))
        elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66:
            # 'DOWN' > Down in the server list
            self.cursor_down(stats)
            logger.debug("Server {}/{} selected".format(self.cursor + 1, len(stats)))

        # Return the key code
        return self.pressedkey
Пример #13
0
 def init(self):
     """Init the Prometheus Exporter"""
     try:
         start_http_server(port=int(self.port), addr=self.host)
     except Exception as e:
         logger.critical("Can not start Prometheus exporter on {}:{} ({})".format(self.host, self.port, e))
         sys.exit(2)
     else:
         logger.info("Start Prometheus exporter on {}:{}".format(self.host, self.port))
Пример #14
0
 def init(self):
     """Init the connection to the Statsd server."""
     if not self.export_enable:
         return None
     logger.info(
         "Stats will be exported to StatsD server: {}:{}".format(self.host,
                                                                 self.port))
     return StatsClient(self.host,
                        int(self.port),
                        prefix=self.prefix)
Пример #15
0
    def __init__(self, config=None, args=None):
        self.config = config
        self.args = args

        # Quiet mode
        self._quiet = args.quiet
        self.refresh_time = args.time

        # Init stats
        self.stats = GlancesStats(config=config, args=args)

        # Modules (plugins and exporters) are loaded at this point
        # Glances can display the list if asked...
        if args.modules_list:
            self.display_modules_list()
            sys.exit(0)

        # If process extended stats is disabled by user
        if not args.enable_process_extended:
            logger.debug("Extended stats for top process are disabled")
            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.process_filter = args.process_filter

        if (not WINDOWS) and args.no_kernel_threads:
            # Ignore kernel threads in process list
            glances_processes.disable_kernel_threads()

        # 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
            glances_processes.max_processes = 0
        elif args.stdout:
            logger.info("Stdout mode is ON, following stats will be displayed: {}".format(args.stdout))
            # Init screen
            self.screen = GlancesStdout(config=config, args=args)
        else:
            # Default number of processes to displayed is set to 50
            glances_processes.max_processes = 50

            # Init screen
            self.screen = GlancesCursesStandalone(config=config, args=args)

        # Check the latest Glances version
        self.outdated = Outdated(config=config, args=args)
Пример #16
0
 def init(self):
     """Init the connection to the restful server."""
     if not self.export_enable:
         return None
     # Build the Restful URL where the stats will be posted
     url = '{}://{}:{}{}'.format(self.protocol,
                                 self.host,
                                 self.port,
                                 self.path)
     logger.info(
         "Stats will be exported to the restful endpoint {}".format(url))
     return url
Пример #17
0
    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 glances.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')
Пример #18
0
def end():
    """Stop Glances."""
    try:
        mode.end()
    except NameError:
        # NameError: name 'mode' is not defined in case of interrupt shortly...
        # ...after starting the server mode (issue #1175)
        pass

    logger.info("Glances stopped (keypressed: CTRL-C)")

    # The end...
    sys.exit(0)
Пример #19
0
    def start(self, stats):
        """Start the bottle."""
        # Init stats
        self.stats = stats

        # Init plugin list
        self.plugins_list = self.stats.getAllPlugins()

        # Bind the Bottle TCP address/port
        bindmsg = 'Glances web server started on http://{0}:{1}/'.format(self.args.bind_address, self.args.port)
        logger.info(bindmsg)
        print(bindmsg)
        self._app.run(host=self.args.bind_address, port=self.args.port, quiet=not self.args.debug)
Пример #20
0
 def 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.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
Пример #21
0
def end():
    """Stop Glances."""
    try:
        mode.end()
    except NameError:
        # NameError: name 'mode' is not defined in case of interrupt shortly...
        # ...after starting the server mode (issue #1175)
        pass

    logger.info("Glances stopped (keypressed: CTRL-C)")

    # The end...
    sys.exit(0)
Пример #22
0
    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 glances.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')
Пример #23
0
    def __init__(self, config=None, args=None):
        # Quiet mode
        self._quiet = args.quiet
        self.refresh_time = args.time

        # Init stats
        self.stats = GlancesStats(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")
            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.process_filter = args.process_filter

        if (not WINDOWS) and args.no_kernel_threads:
            # Ignore kernel threads in process list
            glances_processes.disable_kernel_threads()

        try:
            if args.process_tree:
                # Enable process tree view
                glances_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
            glances_processes.max_processes = 0
        else:
            # Default number of processes to displayed is set to 50
            glances_processes.max_processes = 50

            # Init screen
            self.screen = GlancesCursesStandalone(config=config, args=args)

        # Check the latest Glances version
        self.outdated = Outdated(config=config, args=args)

        # Create the schedule instance
        self.schedule = sched.scheduler(timefunc=time.time,
                                        delayfunc=time.sleep)
Пример #24
0
    def __init__(self, config=None, args=None):
        # Quiet mode
        self._quiet = args.quiet
        self.refresh_time = args.time

        # Init stats
        self.stats = GlancesStats(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")
            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.process_filter = args.process_filter

        if (not WINDOWS) and args.no_kernel_threads:
            # Ignore kernel threads in process list
            glances_processes.disable_kernel_threads()

        try:
            if args.process_tree:
                # Enable process tree view
                glances_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
            glances_processes.max_processes = 0
        else:
            # Default number of processes to displayed is set to 50
            glances_processes.max_processes = 50

            # Init screen
            self.screen = GlancesCursesStandalone(config=config, args=args)

        # Check the latest Glances version
        self.outdated = Outdated(config=config, args=args)

        # Create the schedule instance
        self.schedule = sched.scheduler(
            timefunc=time.time, delayfunc=time.sleep)
Пример #25
0
    def _init_history(self):
        '''Init the history option'''

        self.reset_history_tag = False
        self.history_tag = False
        if self.args.enable_history:
            logger.info('Stats history enabled with output path %s' %
                        self.args.path_history)
            from glances.exports.glances_history import GlancesHistory
            self.glances_history = GlancesHistory(self.args.path_history)
            if not self.glances_history.graph_enabled():
                self.args.enable_history = False
                logger.error(
                    'Stats history disabled because MatPlotLib is not installed')
Пример #26
0
    def _login_snmp(self):
        """Login to a SNMP server"""
        logger.info("Trying to grab stats by SNMP...")

        from glances.stats_client_snmp import GlancesStatsClientSNMP

        # Init stats
        self.stats = GlancesStatsClientSNMP(config=self.config, args=self.args)

        if not self.stats.check_snmp():
            self.log_and_exit("Connection to SNMP server failed")
            return False

        return True
Пример #27
0
    def _login_snmp(self):
        """Login to a SNMP server"""
        logger.info("Trying to grab stats by SNMP...")

        from glances.stats_client_snmp import GlancesStatsClientSNMP

        # Init stats
        self.stats = GlancesStatsClientSNMP(config=self.config, args=self.args)

        if not self.stats.check_snmp():
            self.log_and_exit("Connection to SNMP server failed")
            return False

        return True
Пример #28
0
 def 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.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
Пример #29
0
def start_webserver(config, args):
    """Start the Web server mode"""
    logger.info("Start web server mode")

    # Share global var
    global webserver

    # Import the Glances web server module
    from glances.webserver import GlancesWebServer

    # Init the web server mode
    webserver = GlancesWebServer(config=config, args=args)

    # Start the web server loop
    webserver.serve_forever()
Пример #30
0
    def _init_history(self):
        '''Init the history option'''

        self.reset_history_tag = False
        self.history_tag = False
        if self.args.enable_history:
            logger.info('Stats history enabled with output path %s' %
                        self.args.path_history)
            from glances.exports.glances_history import GlancesHistory
            self.glances_history = GlancesHistory(self.args.path_history)
            if not self.glances_history.graph_enabled():
                self.args.enable_history = False
                logger.error(
                    'Stats history disabled because MatPlotLib is not installed'
                )
Пример #31
0
def start_standalone(config, args):
    """Start the standalone mode"""
    logger.info("Start standalone mode")

    # Share global var
    global standalone

    # Import the Glances standalone module
    from glances.standalone import GlancesStandalone

    # Init the standalone mode
    standalone = GlancesStandalone(config=config, args=args)

    # Start the standalone (CLI) loop
    standalone.serve_forever()
Пример #32
0
 def __init__(self, args=None):
     if zeroconf_tag:
         logger.info("Init autodiscover mode (Zeroconf protocol)")
         try:
             self.zeroconf = Zeroconf()
         except socket.error as e:
             logger.error("Cannot start Zeroconf (%s)" % e)
             self.zeroconf_enable_tag = False
         else:
             self.listener = GlancesAutoDiscoverListener()
             self.browser = ServiceBrowser(
                 self.zeroconf, zeroconf_type, self.listener)
             self.zeroconf_enable_tag = True
     else:
         logger.error("Cannot start autodiscover mode (Zeroconf lib is not installed)")
         self.zeroconf_enable_tag = False
Пример #33
0
    def start(self, stats):
        """Start the bottle."""
        # Init stats
        self.stats = stats

        # Init plugin list
        self.plugins_list = self.stats.getAllPlugins()

        # Bind the Bottle TCP address/port
        bindmsg = 'Glances web server started on http://{0}:{1}/'.format(
            self.args.bind_address, self.args.port)
        logger.info(bindmsg)
        print(bindmsg)
        self._app.run(host=self.args.bind_address,
                      port=self.args.port,
                      quiet=not self.args.debug)
Пример #34
0
 def __init__(self, args=None):
     if zeroconf_tag:
         logger.info("Init autodiscover mode (Zeroconf protocol)")
         try:
             self.zeroconf = Zeroconf()
         except socket.error as e:
             logger.error("Cannot start Zeroconf (%s)" % e)
             self.zeroconf_enable_tag = False
         else:
             self.listener = GlancesAutoDiscoverListener()
             self.browser = ServiceBrowser(
                 self.zeroconf, zeroconf_type, self.listener)
             self.zeroconf_enable_tag = True
     else:
         logger.error("Cannot start autodiscover mode (Zeroconf lib is not installed)")
         self.zeroconf_enable_tag = False
Пример #35
0
    def init(self):
        """Init the connection to the Cassandra server."""
        if not self.export_enable:
            return None

        # if username and/or password are not set the connection will try to connect with no auth
        auth_provider = PlainTextAuthProvider(username=self.username,
                                              password=self.password)

        # Cluster
        try:
            cluster = Cluster([self.host],
                              port=int(self.port),
                              protocol_version=int(self.protocol_version),
                              auth_provider=auth_provider)
            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 {} ({}) in keyspace {}"
            .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 Exception:
            logger.debug("Cassandra table %s already exist" % self.table)

        return cluster, session
Пример #36
0
    def get_password(self, description='', confirm=False, clear=False):
        """Get the password from a Glances client or server.

        For Glances server, get the password (confirm=True, clear=False):
            1) from the password file (if it exists)
            2) from the CLI
        Optionally: save the password to a file (hashed with salt + SHA-256)

        For Glances client, get the password (confirm=False, clear=True):
            1) from the CLI
            2) the password is hashed with SHA-256 (only SHA string transit
               through the network)
        """
        if os.path.exists(self.password_file) and not clear:
            # If the password file exist then use it
            logger.info("Read password from file {}".format(
                self.password_file))
            password = self.load_password()
        else:
            # password_sha256 is the plain SHA-256 password
            # password_hashed is the salt + SHA-256 password
            password_sha256 = self.sha256_hash(getpass.getpass(description))
            password_hashed = self.hash_password(password_sha256)
            if confirm:
                # password_confirm is the clear password (only used to compare)
                password_confirm = self.sha256_hash(
                    getpass.getpass('Password (confirm): '))

                if not self.check_password(password_hashed, password_confirm):
                    logger.critical("Sorry, passwords do not match. Exit.")
                    sys.exit(1)

            # Return the plain SHA-256 or the salted password
            if clear:
                password = password_sha256
            else:
                password = password_hashed

            # Save the hashed password to the password file
            if not clear:
                save_input = input(
                    'Do you want to save the password? [Yes/No]: ')
                if len(save_input) > 0 and save_input[0].upper() == 'Y':
                    self.save_password(password_hashed)

        return password
Пример #37
0
    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))

        return es
Пример #38
0
    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
Пример #39
0
    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_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
Пример #40
0
    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_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
Пример #41
0
    def update(self, stats):
        """Generate Graph file in the output folder."""

        if self.generate_every != 0 and self._timer.finished():
            self.args.generate_graph = True
            self._timer.reset()

        if not self.args.generate_graph:
            return

        plugins = stats.getPluginsList()
        for plugin_name in plugins:
            plugin = stats._plugins[plugin_name]
            if plugin_name in self.plugins_to_export():
                self.export(plugin_name, plugin.get_export_history())

        logger.info("Graphs created in the folder {}".format(self.path))
        self.args.generate_graph = False
Пример #42
0
def start_clientbrowser(config, args):
    """Start the browser client mode"""
    logger.info("Start client mode (browser)")

    # Share global var
    global client

    # Import the Glances client browser module
    from glances.client_browser import GlancesClientBrowser

    # Init the client
    client = GlancesClientBrowser(config=config, args=args)

    # Start the client loop
    client.serve_forever()

    # Shutdown the client
    client.end()
Пример #43
0
    def init(self):
        """Init the connection to the CouchDB server."""
        if not self.export_enable:
            return None

        server_uri = 'tcp://{}:{}'.format(self.host, self.port)

        try:
            self.context = zmq.Context()
            publisher = self.context.socket(zmq.PUB)
            publisher.bind(server_uri)
        except Exception as e:
            logger.critical("Cannot connect to ZeroMQ server %s (%s)" % (server_uri, e))
            sys.exit(2)
        else:
            logger.info("Connected to the ZeroMQ server %s" % server_uri)

        return publisher
Пример #44
0
    def update(self, stats):
        """Generate Graph file in the output folder."""

        if self.generate_every != 0 and self._timer.finished():
            self.args.generate_graph = True
            self._timer.reset()

        if not self.args.generate_graph:
            return

        plugins = stats.getPluginsList()
        for plugin_name in plugins:
            plugin = stats._plugins[plugin_name]
            if plugin_name in self.plugins_to_export():
                self.export(plugin_name, plugin.get_export_history())

        logger.info("Graphs created in the folder {}".format(self.path))
        self.args.generate_graph = False
Пример #45
0
    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
Пример #46
0
    def load(self, config):
        """Load the password from the configuration file."""
        password_dict = {}

        if config is None:
            logger.warning("No configuration file available. Cannot load password list.")
        elif not config.has_section(self._section):
            logger.warning("No [%s] section in the configuration file. Cannot load password list." % self._section)
        else:
            logger.info("Start reading the [%s] section in the configuration file" % self._section)

            password_dict = dict(config.items(self._section))

            # Password list loaded
            logger.info("%s password(s) loaded from the configuration file" % len(password_dict))
            logger.debug("Password dictionary: %s" % password_dict)

        return password_dict
Пример #47
0
    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
Пример #48
0
    def init(self):
        """Init the connection to the mongodb server."""
        if not self.export_enable:
            return None

        try:
            client = MongoClient(host=self.host, port=self.port)
            db = client[self.db]
            if not self.username and self.password:
                db.authenticate(self.username, self.password, source='source_database')
            collection = db[self.collection]

        except Exception as e:
            logger.critical("Cannot connect to Mongodb server %s:%s (%s)" % (self.host, self.port, e))
            sys.exit(2)
        else:
            logger.info("Connected to the Mongodb server %s:%s" % (self.host, self.port))

        return collection
Пример #49
0
    def _login_glances(self):
        """Login to a Glances server"""
        client_version = None
        try:
            client_version = self.client.init()
        except socket.error as err:
            # Fallback to SNMP
            self.client_mode = 'snmp'
            logger.error("Connection to Glances server failed ({} {})".format(
                err.errno, err.strerror))
            fallbackmsg = 'No Glances server found on {}. Trying fallback to SNMP...'.format(
                self.uri)
            if not self.return_to_browser:
                print(fallbackmsg)
            else:
                logger.info(fallbackmsg)
        except ProtocolError as err:
            # Other errors
            msg = "Connection to server {} failed".format(self.uri)
            if err.errcode == 401:
                msg += " (Bad username/password)"
            else:
                msg += " ({} {})".format(err.errcode, err.errmsg)
            self.log_and_exit(msg)
            return False

        if self.client_mode == 'glances':
            # Check that both client and server are in the same major version
            if __version__.split('.')[0] == client_version.split('.')[0]:
                # Init stats
                self.stats = GlancesStatsClient(config=self.config,
                                                args=self.args)
                self.stats.set_plugins(json.loads(self.client.getAllPlugins()))
                logger.debug("Client version: {} / Server version: {}".format(
                    __version__, client_version))
            else:
                self.log_and_exit(
                    ('Client and server not compatible: '
                     'Client version: {} / Server version: {}'.format(
                         __version__, client_version)))
                return False

        return True
Пример #50
0
    def run(self, stat_name, criticity, commands, repeat, 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}}
        - If True, then repeat the action
        - mustache_dict: Plugin stats (can be use within {{mustache}})

        Return True if the commands have been ran.
        """
        if (self.get(stat_name) == criticity and not repeat) or \
           not self.start_timer.finished():
            # Action already executed => Exit
            return False

        logger.debug("{} action {} for {} ({}) with stats {}".format(
            "Repeat" if repeat else "Run", 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 chevron_tag:
                cmd_full = chevron.render(cmd, mustache_dict)
            else:
                cmd_full = cmd
            # Execute the action
            logger.info("Action triggered for {} ({}): {}".format(
                stat_name, criticity, cmd_full))
            try:
                ret = secure_popen(cmd_full)
            except OSError as e:
                logger.error("Action error for {} ({}): {}".format(
                    stat_name, criticity, e))
            else:
                logger.debug("Action result for {} ({}): {}".format(
                    stat_name, criticity, ret))

        self.set(stat_name, criticity)

        return True
Пример #51
0
    def __catch_key(self, stats):
        # Catch the browser pressed key
        self.pressedkey = self.get_key(self.term_window)

        if self.pressedkey != -1:
            logger.debug("Key pressed. Code=%s" % self.pressedkey)

        # 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)
            self.is_end = True
        elif self.pressedkey == 10:
            # 'ENTER' > Run Glances on the selected server
            self.active_server = self._current_page * self._page_max_lines + self.cursor_position
            logger.debug("Server {}/{} selected".format(
                self.active_server, len(stats)))
        elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65:
            # 'UP' > Up in the server list
            self.cursor_up(stats)
            logger.debug("Server {}/{} selected".format(
                self.cursor + 1, len(stats)))
        elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66:
            # 'DOWN' > Down in the server list
            self.cursor_down(stats)
            logger.debug("Server {}/{} selected".format(
                self.cursor + 1, len(stats)))
        elif self.pressedkey == curses.KEY_PPAGE:
            # 'Page UP' > Prev page in the server list
            self.cursor_pageup(stats)
            logger.debug("PageUP: Server ({}/{}) pages.".format(
                self._current_page + 1, self._page_max))
        elif self.pressedkey == curses.KEY_NPAGE:
            # 'Page Down' > Next page in the server list
            self.cursor_pagedown(stats)
            logger.debug("PageDown: Server {}/{} pages".format(
                self._current_page + 1, self._page_max))

        # Return the key code
        return self.pressedkey
Пример #52
0
    def init(self):
        """Init the connection to the Kafka server."""
        if not self.export_enable:
            return None

        # Build the server URI with host and port
        server_uri = '{}:{}'.format(self.host, self.port)

        try:
            s = KafkaProducer(
                bootstrap_servers=server_uri,
                value_serializer=lambda v: json.dumps(v).encode('utf-8'),
                compression_type=self.compression)
        except Exception as e:
            logger.critical("Cannot connect to Kafka server %s (%s)" %
                            (server_uri, e))
            sys.exit(2)
        else:
            logger.info("Connected to the Kafka server %s" % server_uri)

        return s
Пример #53
0
    def msg_curse(self, args=None):
        """Return the string to display in the curse interface."""
        # Init the return message
        ret = []

        if not self.stats or self.stats == {} or self.is_disable():
            return ret

        # Generate the output
        if 'ami-id' in self.stats and 'region' in self.stats:
            msg = 'AWS EC2'
            ret.append(self.curse_add_line(msg, "TITLE"))
            msg = ' {} instance {} ({})'.format(
                to_ascii(self.stats['instance-type']),
                to_ascii(self.stats['instance-id']),
                to_ascii(self.stats['region']))
            ret.append(self.curse_add_line(msg))

        # Return the message with decoration
        logger.info(ret)
        return ret
Пример #54
0
    def start(self, stats):
        """Start the bottle."""
        # Init stats
        self.stats = stats

        # Init plugin list
        self.plugins_list = self.stats.getAllPlugins()

        # Bind the Bottle TCP address/port
        bindurl = 'http://{}:{}/'.format(self.args.bind_address,
                                         self.args.port)
        bindmsg = 'Glances web server started on {}'.format(bindurl)
        logger.info(bindmsg)
        print(bindmsg)
        if self.args.open_web_browser:
            # Implementation of the issue #946
            # Try to open the Glances Web UI in the default Web browser if:
            # 1) --open-web-browser option is used
            # 2) Glances standalone mode is running on Windows OS
            webbrowser.open(bindurl, new=2, autoraise=1)
        self._app.run(host=self.args.bind_address, port=self.args.port, quiet=not self.args.debug)
Пример #55
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

    # Create the Glances main instance
    core = GlancesMain()
    config = core.get_config()
    args = core.get_args()

    # Catch the CTRL-C signal
    signal.signal(signal.SIGINT, __signal_handler)

    # Glances can be ran in standalone, client or server mode
    if core.is_standalone() and not WINDOWS:
        start_standalone(config=config, args=args)
    elif core.is_client() and not WINDOWS:
        if core.is_client_browser():
            start_clientbrowser(config=config, args=args)
        else:
            start_client(config=config, args=args)
    elif core.is_server():
        start_server(config=config, args=args)
    elif core.is_webserver() or (core.is_standalone() and WINDOWS):
        # Web server mode replace the standalone mode on Windows OS
        # In this case, try to start the web browser mode automaticaly
        if core.is_standalone() and WINDOWS:
            args.open_web_browser = True
        start_webserver(config=config, args=args)
Пример #56
0
    def read(self):
        """Read the config file, if it exists. Using defaults otherwise."""
        for config_file in self.config_file_paths():
            logger.info('Search glances.conf file in {}'.format(config_file))
            if os.path.exists(config_file):
                try:
                    with open(config_file, encoding='utf-8') as f:
                        self.parser.read_file(f)
                        self.parser.read(f)
                    logger.info(
                        "Read configuration file '{}'".format(config_file))
                except UnicodeDecodeError as err:
                    logger.error(
                        "Can not read configuration file '{}': {}".format(
                            config_file, err))
                    sys.exit(1)
                # Save the loaded configuration file path (issue #374)
                self._loaded_config_file = config_file
                break

        # Set the default values for section not configured
        self.sections_set_default()
Пример #57
0
    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: {0}".format(
                    db._baseurl))
        else:
            logger.critical(
                "InfluxDB database '%s' did not exist. Please create it" %
                self.db)
            sys.exit(2)

        return db
Пример #58
0
    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_file

        # Set the CSV output file
        # (see https://github.com/nicolargo/glances/issues/1525)
        if not os.path.isfile(self.csv_filename) or args.export_csv_overwrite:
            # File did not exist, create it
            file_mode = 'w'
            self.old_header = None
        else:
            # A CSV file already exit, append new data
            file_mode = 'a'
            # Header will be check later
            # Get the existing one
            try:
                self.csv_file = open_csv_file(self.csv_filename, 'r')
                reader = csv.reader(self.csv_file)
            except IOError as e:
                logger.critical("Cannot open existing CSV file: {}".format(e))
                sys.exit(2)
            self.old_header = next(reader, None)
            self.csv_file.close()

        try:
            self.csv_file = open_csv_file(self.csv_filename, file_mode)
            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
Пример #59
0
    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