diff options
author | nicolargo <nicolas@nicolargo.com> | 2023-10-29 10:27:32 +0100 |
---|---|---|
committer | nicolargo <nicolas@nicolargo.com> | 2023-10-29 10:27:32 +0100 |
commit | 51330ca8e7ad240f24a5545738c24b129ec06fa9 (patch) | |
tree | 2d7e5e48ff80458afeb0ba9d63f115e46327296c | |
parent | 091e4975caeddb332f71dd8ed6db3860394dd4fc (diff) | |
parent | eb72dbe35d3480df4dc7dbd553aa3d9c9dbb5b12 (diff) |
Merge branch 'develop' of https://github.com/monochromec/glances into monochromec-develop
-rw-r--r-- | docs/Makefile | 2 | ||||
-rw-r--r-- | docs/cmds.rst | 4 | ||||
-rw-r--r-- | docs/config.rst | 4 | ||||
-rw-r--r-- | docs/man/glances.1 | 5 | ||||
-rw-r--r-- | glances/main.py | 1 | ||||
-rw-r--r-- | glances/plugins/plugin/model.py | 3 | ||||
-rw-r--r-- | glances/stats.py | 51 |
7 files changed, 67 insertions, 3 deletions
diff --git a/docs/Makefile b/docs/Makefile index 75bae57f..30485295 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -3,7 +3,7 @@ # You can set these variables from the command line. SPHINXOPTS = -SPHINXBUILD = ../venv/bin/sphinx-build +SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build diff --git a/docs/cmds.rst b/docs/cmds.rst index 7ab1ef49..cffeb153 100644 --- a/docs/cmds.rst +++ b/docs/cmds.rst @@ -22,6 +22,10 @@ Command-Line Options path to the configuration file +.. option:: -P plugin directory, --plugins plugin directory + + path to a directory containing additional plugins + .. option:: --modules-list display modules (plugins & exports) list and exit diff --git a/docs/config.rst b/docs/config.rst index 38c0cd18..f1c76e16 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -48,6 +48,10 @@ A first section (called global) is available: # History size (maximum number of values) # Default is 28800: 1 day with 1 point every 3 seconds history_size=28800 + # Define directory external to glances hierarchy for loading additional plugins + # The layout follows the glances standard for plugin definitions + # (see <install-dir>glances/plugins for details) + # plugin_dir=/home/user/dev/plugins Each plugin, export module and application monitoring process (AMP) can have a section. Below an example for the CPU plugin: diff --git a/docs/man/glances.1 b/docs/man/glances.1 index d6451f25..66a23e95 100644 --- a/docs/man/glances.1 +++ b/docs/man/glances.1 @@ -68,6 +68,11 @@ path to the configuration file .UNINDENT .INDENT 0.0 .TP +.B \-C PLUGIN_DIR, \-\-plugins CONF_FILE +path to the directory containing additional plugins +.UNINDENT +.INDENT 0.0 +.TP .B \-\-modules\-list display modules (plugins & exports) list and exit .UNINDENT diff --git a/glances/main.py b/glances/main.py index aa7c58d6..03acfd7a 100644 --- a/glances/main.py +++ b/glances/main.py @@ -111,6 +111,7 @@ Examples of use: parser.add_argument('-V', '--version', action='version', version=version) parser.add_argument('-d', '--debug', action='store_true', default=False, dest='debug', help='enable debug mode') parser.add_argument('-C', '--config', dest='conf_file', help='path to the configuration file') + parser.add_argument('-P', '--plugins', dest='plugin_dir', help='path to additional plugin directory') # Disable plugin parser.add_argument( '--modules-list', diff --git a/glances/plugins/plugin/model.py b/glances/plugins/plugin/model.py index 3c2eb4b4..d36ddbfb 100644 --- a/glances/plugins/plugin/model.py +++ b/glances/plugins/plugin/model.py @@ -70,7 +70,8 @@ class GlancesPluginModel(object): :stats_init_value: Default value for a stats item """ # Build the plugin name - self.plugin_name = self.__class__.__module__.split('.')[2] + # Get second-last entry as the last one will always be 'model' + self.plugin_name = self.__class__.__module__.split('.')[-2] if self.plugin_name.startswith('glances_'): self.plugin_name = self.plugin_name.split('glances_')[1] logger.debug("Init {} plugin".format(self.plugin_name)) diff --git a/glances/stats.py b/glances/stats.py index 30ffb421..31b88d2b 100644 --- a/glances/stats.py +++ b/glances/stats.py @@ -15,6 +15,7 @@ import sys import threading import traceback from importlib import import_module +import pkgutil from glances.logger import logger from glances.globals import exports_path, plugins_path, sys_path @@ -82,6 +83,9 @@ class GlancesStats(object): # Load the plugins self.load_plugins(args=args) + # Load addititional plugins + self.load_additional_plugins(args=args, config=self.config) + # Init the export modules dict # Active exporters dictionary self._exports = collections.defaultdict(dict) @@ -132,7 +136,52 @@ class GlancesStats(object): # Log plugins list logger.debug("Active plugins list: {}".format(self.getPluginsList())) - + + def load_additional_plugins(self, args=None, config=None): + """ Load additional plugins if defined """ + def get_addl_plugins(self, plugin_path): + """ Get list of additonal plugins """ + _plugin_list = [] + for plugin in pkgutil.walk_packages([plugin_path]): + # Make sure we only include top-level packages in that directory + if plugin.ispkg and not plugin.name.startswith('__') and plugin.module_finder.path == plugin_path: + _plugin_list.append(plugin.name) + + return _plugin_list + + path = None + # Skip section check as implied by has_option + if config and config.parser.has_option('global', 'plugin_dir'): + path = config.parser['global']['plugin_dir'] + + if args and 'plugin_dir' in args: + path = args.plugin_path + + if path: + # Get list before starting the counter + _sys_path = sys.path + start_duration = Counter() + # Ensure that plugins can be found in plugin_dir + sys.path.insert(0, path) + for plugin in get_addl_plugins(self, path): + start_duration.reset() + try: + _mod_loaded = import_module(plugin+'.model') + self._plugins[plugin] = _mod_loaded.PluginModel(args=args, config=config) + logger.debug("Plugin {} started in {} seconds".format(plugin, start_duration.get())) + except Exception as e: + # If a plugin can not be loaded, display a critical message + # on the console but do not crash + logger.critical("Error while initializing the {} plugin ({})".format(plugin, e)) + logger.error(traceback.format_exc()) + # An error occurred, disable the plugin + if args: + setattr(args, 'disable_' + plugin, False) + + sys.path = _sys_path + # Log plugins list + logger.debug("Active additional plugins list: {}".format(self.getPluginsList())) + def load_exports(self, args=None): """Load all exporters in the 'exports' folder.""" start_duration = Counter() |