summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicolargo <nicolas@nicolargo.com>2023-10-29 10:27:32 +0100
committernicolargo <nicolas@nicolargo.com>2023-10-29 10:27:32 +0100
commit51330ca8e7ad240f24a5545738c24b129ec06fa9 (patch)
tree2d7e5e48ff80458afeb0ba9d63f115e46327296c
parent091e4975caeddb332f71dd8ed6db3860394dd4fc (diff)
parenteb72dbe35d3480df4dc7dbd553aa3d9c9dbb5b12 (diff)
Merge branch 'develop' of https://github.com/monochromec/glances into monochromec-develop
-rw-r--r--docs/Makefile2
-rw-r--r--docs/cmds.rst4
-rw-r--r--docs/config.rst4
-rw-r--r--docs/man/glances.15
-rw-r--r--glances/main.py1
-rw-r--r--glances/plugins/plugin/model.py3
-rw-r--r--glances/stats.py51
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()