Added loading of additional plugins feature

pull/2590/head
Christoph Zimmermann 2023-10-26 14:43:58 +02:00
parent 0dc0200375
commit f4c35ed56d
3 changed files with 46 additions and 1 deletions

View File

@ -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_path', help='path to additional plugin directory')
# Disable plugin
parser.add_argument(
'--modules-list',

View File

@ -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))

View File

@ -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)
@ -141,7 +145,46 @@ 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
# Skip section check as implied by has_option
if config and config.parser.has_option('global', 'plugin_dir'):
path = config.parser['global']['plugin_dir']
# 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(1, 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()