mirror of
https://github.com/arcan1s/queued.git
synced 2025-04-24 15:37:19 +00:00
integrate plugin engine
This commit is contained in:
parent
d177aa81af
commit
2d8d501f02
@ -106,12 +106,14 @@ public:
|
||||
signals:
|
||||
/**
|
||||
* @brief emits on each value update
|
||||
* @param _id
|
||||
* internal key id
|
||||
* @param _key
|
||||
* changed key
|
||||
* @param _value
|
||||
* changed value
|
||||
*/
|
||||
void valueUpdated(const QueuedCfg::QueuedSettings _key,
|
||||
void valueUpdated(const QueuedCfg::QueuedSettings _id, const QString &_key,
|
||||
const QVariant &_value);
|
||||
|
||||
private:
|
||||
|
@ -97,6 +97,8 @@ typedef struct {
|
||||
* internal field to control current database version
|
||||
* @var QueuedSettings::ProcessCommandLine
|
||||
* control process command line
|
||||
* @var QueuedSettings::Plugins
|
||||
* plugin list
|
||||
*/
|
||||
enum class QueuedSettings {
|
||||
Invalid = 1 << 0,
|
||||
@ -108,6 +110,7 @@ enum class QueuedSettings {
|
||||
TokenExpiration = 1 << 6,
|
||||
DatabaseVersion = 1 << 7,
|
||||
ProcessCommandLine = 1 << 8,
|
||||
Plugins = 1 << 9,
|
||||
};
|
||||
/**
|
||||
* @ingroup QueuedCfg
|
||||
@ -148,7 +151,8 @@ const QueuedSettingsDefaultMap QueuedSettingsDefaults = {
|
||||
{QueuedSettings::ProcessCommandLine,
|
||||
"systemd-run\x01--scope\x01--unit={name}\x01--uid={uid}\x01--gid={gid}"
|
||||
"\x01-p\x01CPUQuota={cpu}%\x01-p\x01MemoryHigh={memory}\x01{"
|
||||
"application}"}}};
|
||||
"application}"}},
|
||||
{"Plugins", {QueuedSettings::Plugins, ""}}};
|
||||
};
|
||||
|
||||
#endif /* QUEUEDCONFIGURATION_H */
|
||||
|
@ -35,6 +35,7 @@
|
||||
class QueuedAdvancedSettings;
|
||||
class QueuedDatabase;
|
||||
class QueuedDatabaseManager;
|
||||
class QueuedPluginManager;
|
||||
class QueuedProcess;
|
||||
class QueuedProcessManager;
|
||||
class QueuedReportManager;
|
||||
@ -58,6 +59,16 @@ public:
|
||||
* @brief QueuedCore class destructor
|
||||
*/
|
||||
virtual ~QueuedCore();
|
||||
/**
|
||||
* @brief add plugin to autoload and load it now
|
||||
* @param _plugin
|
||||
* plugin name
|
||||
* @param _auth
|
||||
* user auth structure
|
||||
* @return true on successfully addition
|
||||
*/
|
||||
bool addPlugin(const QString &_plugin,
|
||||
const QueuedUserManager::QueuedUserAuthorization &_auth);
|
||||
/**
|
||||
* @brief add new task
|
||||
* @param _command
|
||||
@ -175,6 +186,23 @@ public:
|
||||
* @return option value or empty QVariant
|
||||
*/
|
||||
QVariant option(const QString &_key);
|
||||
/**
|
||||
* @brief get plugin settings
|
||||
* @param _plugin
|
||||
* plugin name
|
||||
* @return hash of plugin settings
|
||||
*/
|
||||
QVariantHash pluginSettings(const QString &_plugin);
|
||||
/**
|
||||
* @brief remove plugin from autoload and unload it now
|
||||
* @param _plugin
|
||||
* plugin name
|
||||
* @param _auth
|
||||
* user auth structure
|
||||
* @return true on successful plugin removal
|
||||
*/
|
||||
bool removePlugin(const QString &_plugin,
|
||||
const QueuedUserManager::QueuedUserAuthorization &_auth);
|
||||
/**
|
||||
* @brief force start task
|
||||
* @param _id
|
||||
@ -226,13 +254,15 @@ public:
|
||||
private slots:
|
||||
/**
|
||||
* @brief notify clients about settings update
|
||||
* @param _id
|
||||
* updated key id
|
||||
* @param _key
|
||||
* updated key
|
||||
* @param _value
|
||||
* new value
|
||||
*/
|
||||
void updateSettings(const QueuedCfg::QueuedSettings _key,
|
||||
const QVariant &_value);
|
||||
void updateSettings(const QueuedCfg::QueuedSettings _id,
|
||||
const QString &_key, const QVariant &_value);
|
||||
/**
|
||||
* @brief update process time
|
||||
* @param _id
|
||||
@ -266,6 +296,10 @@ private:
|
||||
* @brief pointer to database manager object
|
||||
*/
|
||||
QueuedDatabaseManager *m_databaseManager = nullptr;
|
||||
/**
|
||||
* @brief pointer to plugin manager
|
||||
*/
|
||||
QueuedPluginManager *m_plugins = nullptr;
|
||||
/**
|
||||
* @brief pointer to process manager
|
||||
*/
|
||||
@ -302,6 +336,10 @@ private:
|
||||
* @throw QueuedDBusException
|
||||
*/
|
||||
void initDBus();
|
||||
/**
|
||||
* @brief init plugins
|
||||
*/
|
||||
void initPlugins();
|
||||
/**
|
||||
* @brief init processes
|
||||
*/
|
||||
@ -364,6 +402,15 @@ private:
|
||||
* @return true on successful option edition
|
||||
*/
|
||||
bool editOptionPrivate(const QString &_key, const QVariant &_value);
|
||||
/**
|
||||
* @brief edit plugin list
|
||||
* @param _plugin
|
||||
* plugin name
|
||||
* @param add
|
||||
* true if it requires add plugin
|
||||
* @return true on successful action
|
||||
*/
|
||||
bool editPluginPrivate(const QString &_plugin, const bool _add);
|
||||
/**
|
||||
* @brief edit task
|
||||
* @param _id
|
||||
|
@ -76,6 +76,30 @@ public slots:
|
||||
*/
|
||||
bool OptionEdit(const QString &key, const QDBusVariant &value,
|
||||
const QString &whoAmI, const QString &token);
|
||||
/**
|
||||
* @brief add plugin
|
||||
* @param plugin
|
||||
* plugin name
|
||||
* @param whoAmI
|
||||
* auth user name
|
||||
* @param token
|
||||
* auth user token
|
||||
* @return true on successful plugin addition
|
||||
*/
|
||||
bool PluginAdd(const QString &plugin, const QString &whoAmI,
|
||||
const QString &token);
|
||||
/**
|
||||
* @brief remove plugin
|
||||
* @param plugin
|
||||
* plugin name
|
||||
* @param whoAmI
|
||||
* auth user name
|
||||
* @param token
|
||||
* auth user token
|
||||
* @return true on successful plugin removal
|
||||
*/
|
||||
bool PluginRemove(const QString &plugin, const QString &whoAmI,
|
||||
const QString &token);
|
||||
/**
|
||||
* @brief add new task
|
||||
* @param command
|
||||
|
@ -54,6 +54,14 @@ public:
|
||||
* @remark plugin settings will be stored as "plugin.name.Key"
|
||||
*/
|
||||
virtual void init(const QVariantHash &_settings) = 0;
|
||||
/**
|
||||
* @brief method which will be called on option update
|
||||
* @param _key
|
||||
* option key
|
||||
* @param _value
|
||||
* option value
|
||||
*/
|
||||
virtual void updateSettings(const QString &_key, const QVariant &_value);
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(QueuedPluginInterface, PLUGIN_INTERFACE_NAME)
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
|
||||
|
||||
class QueuedPluginInterface;
|
||||
@ -55,6 +56,13 @@ public:
|
||||
* @brief QueuedPluginManager class destructor
|
||||
*/
|
||||
virtual ~QueuedPluginManager();
|
||||
/**
|
||||
* @brief get option name from database format
|
||||
* @param _key
|
||||
* option key
|
||||
* @return plugin name and option key in plugin format
|
||||
*/
|
||||
static QPair<QString, QString> convertOptionName(const QString &_key);
|
||||
/**
|
||||
* @brief plugin manager interface
|
||||
* @return pointer to plugin manager interface
|
||||
@ -82,6 +90,16 @@ public:
|
||||
*/
|
||||
bool unloadPlugin(const QString &_name);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief notifies plugin about option changes
|
||||
* @param _key
|
||||
* database option key
|
||||
* @param _value
|
||||
* option value
|
||||
*/
|
||||
void optionChanged(const QString &_key, const QVariant &_value);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief loaded plugins
|
||||
|
@ -37,11 +37,9 @@ class QueuedPluginManagerInterface : public QObject
|
||||
public:
|
||||
/**
|
||||
* @brief QueuedPluginManagerInterface class constructor
|
||||
* @param parent
|
||||
* pointer to parent object
|
||||
*/
|
||||
explicit QueuedPluginManagerInterface(QObject *parent)
|
||||
: QObject(parent){};
|
||||
explicit QueuedPluginManagerInterface()
|
||||
: QObject(nullptr){};
|
||||
/**
|
||||
* @brief QueuedPluginManagerInterface class destructor
|
||||
*/
|
||||
|
@ -148,7 +148,7 @@ void QueuedAdvancedSettings::set(const QString &_key, const QVariant &_value)
|
||||
|
||||
m_values[_key.toLower()] = _value;
|
||||
auto id = QueuedCfg::QueuedSettingsDefaults[internalId(_key)].id;
|
||||
emit(valueUpdated(id, _value));
|
||||
emit(valueUpdated(id, _key, _value));
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,6 +53,25 @@ QueuedCore::~QueuedCore()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn addPlugin
|
||||
*/
|
||||
bool QueuedCore::addPlugin(
|
||||
const QString &_plugin,
|
||||
const QueuedUserManager::QueuedUserAuthorization &_auth)
|
||||
{
|
||||
qCDebug(LOG_LIB) << "Add plugin" << _plugin;
|
||||
|
||||
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
|
||||
if (!isAdmin) {
|
||||
qCInfo(LOG_LIB) << "User" << _auth.user << "not allowed to add plugin";
|
||||
return false;
|
||||
}
|
||||
|
||||
return editPluginPrivate(_plugin, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @addTask
|
||||
*/
|
||||
@ -309,6 +328,46 @@ QVariant QueuedCore::option(const QString &_key)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn pluginSettings
|
||||
*/
|
||||
QVariantHash QueuedCore::pluginSettings(const QString &_plugin)
|
||||
{
|
||||
qCDebug(LOG_LIB) << "Get plugin settings for" << _plugin;
|
||||
|
||||
auto dbSettings
|
||||
= m_database->get(QueuedDB::SETTINGS_TABLE,
|
||||
QString("WHERE key LIKE 'Plugin.%1.%'").arg(_plugin));
|
||||
QVariantHash settings;
|
||||
std::for_each(dbSettings.cbegin(), dbSettings.cend(),
|
||||
[&settings](const QVariantHash &value) {
|
||||
settings[value["key"].toString()] = value["value"];
|
||||
});
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn removePlugin
|
||||
*/
|
||||
bool QueuedCore::removePlugin(
|
||||
const QString &_plugin,
|
||||
const QueuedUserManager::QueuedUserAuthorization &_auth)
|
||||
{
|
||||
qCDebug(LOG_LIB) << "Remove plugin" << _plugin;
|
||||
|
||||
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
|
||||
if (!isAdmin) {
|
||||
qCInfo(LOG_LIB) << "User" << _auth.user
|
||||
<< "not allowed to remove plugin";
|
||||
return false;
|
||||
}
|
||||
|
||||
return editPluginPrivate(_plugin, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn startTask
|
||||
*/
|
||||
@ -430,6 +489,8 @@ void QueuedCore::deinit()
|
||||
delete m_databaseManager;
|
||||
if (m_reports)
|
||||
delete m_reports;
|
||||
if (m_plugins)
|
||||
delete m_plugins;
|
||||
if (m_processes)
|
||||
delete m_processes;
|
||||
if (m_users)
|
||||
@ -455,15 +516,17 @@ void QueuedCore::init(const QString &_configuration)
|
||||
|
||||
// init parts
|
||||
initSettings(_configuration);
|
||||
initPlugins();
|
||||
initUsers();
|
||||
initProcesses();
|
||||
|
||||
// settings update notifier
|
||||
m_connections += connect(
|
||||
m_advancedSettings,
|
||||
SIGNAL(valueUpdated(const QueuedCfg::QueuedSettings, const QVariant &)),
|
||||
SIGNAL(valueUpdated(const QueuedCfg::QueuedSettings, const QString &,
|
||||
const QVariant &)),
|
||||
this, SLOT(updateSettings(const QueuedCfg::QueuedSettings,
|
||||
const QVariant &)));
|
||||
const QString &, const QVariant &)));
|
||||
|
||||
// dbus session
|
||||
initDBus();
|
||||
@ -473,15 +536,19 @@ void QueuedCore::init(const QString &_configuration)
|
||||
/**
|
||||
* @fn updateSettings
|
||||
*/
|
||||
void QueuedCore::updateSettings(const QueuedCfg::QueuedSettings _key,
|
||||
const QVariant &_value)
|
||||
void QueuedCore::updateSettings(const QueuedCfg::QueuedSettings _id,
|
||||
const QString &_key, const QVariant &_value)
|
||||
{
|
||||
qCDebug(LOG_LIB) << "Received update for" << static_cast<int>(_key)
|
||||
qCDebug(LOG_LIB) << "Received update for" << static_cast<int>(_id) << _key
|
||||
<< "with value" << _value;
|
||||
|
||||
// FIXME propbably there is a better way to change settings
|
||||
switch (_key) {
|
||||
switch (_id) {
|
||||
case QueuedCfg::QueuedSettings::Invalid:
|
||||
// check if it is plugin settings
|
||||
if (_key.startsWith("Plugin."))
|
||||
m_plugins->optionChanged(_key, _value);
|
||||
// do nothing otherwise
|
||||
break;
|
||||
case QueuedCfg::QueuedSettings::DatabaseInterval:
|
||||
m_databaseManager->setInterval(_value.toLongLong());
|
||||
@ -500,6 +567,9 @@ void QueuedCore::updateSettings(const QueuedCfg::QueuedSettings _key,
|
||||
m_processes->setOnExitAction(
|
||||
static_cast<QueuedProcessManager::OnExitAction>(_value.toInt()));
|
||||
break;
|
||||
case QueuedCfg::QueuedSettings::Plugins:
|
||||
// do nothing here
|
||||
break;
|
||||
case QueuedCfg::QueuedSettings::ProcessCommandLine:
|
||||
m_processes->setProcessLine(_value.toString());
|
||||
break;
|
||||
@ -601,6 +671,22 @@ void QueuedCore::initDBus()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn initPlugins
|
||||
*/
|
||||
void QueuedCore::initPlugins()
|
||||
{
|
||||
QStringList pluginList
|
||||
= m_advancedSettings->get(QueuedCfg::QueuedSettings::Plugins)
|
||||
.toString()
|
||||
.split('\x01');
|
||||
|
||||
m_plugins = new QueuedPluginManager(this);
|
||||
for (auto &plugin : pluginList)
|
||||
m_plugins->loadPlugin(plugin, pluginSettings(plugin));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn initProcesses
|
||||
*/
|
||||
@ -796,8 +882,35 @@ bool QueuedCore::editOptionPrivate(const QString &_key, const QVariant &_value)
|
||||
}
|
||||
|
||||
// add to child object
|
||||
if (status)
|
||||
if (status) {
|
||||
m_advancedSettings->set(_key, _value);
|
||||
// notify plugin if required
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn editPluginPrivate
|
||||
*/
|
||||
bool QueuedCore::editPluginPrivate(const QString &_plugin, const bool _add)
|
||||
{
|
||||
qCDebug(LOG_LIB) << "Edit plugin" << _plugin << "add" << _add;
|
||||
|
||||
QStringList pluginList
|
||||
= m_advancedSettings->get(QueuedCfg::QueuedSettings::Plugins)
|
||||
.toString()
|
||||
.split('\x01');
|
||||
|
||||
bool status = false;
|
||||
if (_add && !pluginList.contains(_plugin))
|
||||
status = m_plugins->loadPlugin(_plugin, pluginSettings(_plugin));
|
||||
else if (!_add && pluginList.contains(_plugin))
|
||||
status = m_plugins->unloadPlugin(_plugin);
|
||||
else
|
||||
qCDebug(LOG_LIB) << "Plugin" << _plugin
|
||||
<< "not loaded or already loaded";
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,31 @@ bool QueuedCoreInterface::OptionEdit(const QString &key,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn PluginAdd
|
||||
*/
|
||||
bool QueuedCoreInterface::PluginAdd(const QString &plugin,
|
||||
const QString &whoAmI, const QString &token)
|
||||
{
|
||||
qCDebug(LOG_DBUS) << "Add plugin" << plugin << "auth by" << whoAmI;
|
||||
|
||||
return m_core->addPlugin(plugin, QueuedUserManager::auth(whoAmI, token));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn PluginRemove
|
||||
*/
|
||||
bool QueuedCoreInterface::PluginRemove(const QString &plugin,
|
||||
const QString &whoAmI,
|
||||
const QString &token)
|
||||
{
|
||||
qCDebug(LOG_DBUS) << "Remove plugin" << plugin << "auth by" << whoAmI;
|
||||
|
||||
return m_core->removePlugin(plugin, QueuedUserManager::auth(whoAmI, token));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn TaskAdd
|
||||
*/
|
||||
|
@ -39,7 +39,7 @@ QueuedPluginManager::QueuedPluginManager(QObject *parent)
|
||||
{
|
||||
qCDebug(LOG_PL) << __PRETTY_FUNCTION__;
|
||||
|
||||
m_interface = new QueuedPluginManagerInterface(this);
|
||||
m_interface = new QueuedPluginManagerInterface();
|
||||
}
|
||||
|
||||
|
||||
@ -58,6 +58,25 @@ QueuedPluginManager::~QueuedPluginManager()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn convertOptionName
|
||||
*/
|
||||
QPair<QString, QString>
|
||||
QueuedPluginManager::convertOptionName(const QString &_key)
|
||||
{
|
||||
qCDebug(LOG_PL) << "Convert option name" << _key;
|
||||
|
||||
QStringList fields = _key.split('.');
|
||||
// Plugin.
|
||||
fields.takeFirst();
|
||||
// plugin name
|
||||
QString plugin = fields.takeFirst();
|
||||
QString option = fields.join('.');
|
||||
|
||||
return {plugin, option};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn interface
|
||||
*/
|
||||
@ -76,6 +95,10 @@ bool QueuedPluginManager::loadPlugin(const QString &_name,
|
||||
qCDebug(LOG_PL) << "Load plugin" << _name << "with settings" << _settings;
|
||||
|
||||
QString libraryName = QString("lib%2.so").arg(_name);
|
||||
// init plugin settings with valid keys
|
||||
QVariantHash pluginSettings;
|
||||
for (auto &key : _settings.keys())
|
||||
pluginSettings[convertOptionName(key).first] = _settings[key];
|
||||
|
||||
for (auto &dir : pluginLocations()) {
|
||||
if (!QDir(dir).entryList(QDir::Files).contains(libraryName))
|
||||
@ -93,7 +116,7 @@ bool QueuedPluginManager::loadPlugin(const QString &_name,
|
||||
<< "error" << loader.errorString();
|
||||
if (item) {
|
||||
m_plugins[_name] = item;
|
||||
item->init(_settings);
|
||||
item->init(pluginSettings);
|
||||
item->connect(interface());
|
||||
} else {
|
||||
qCCritical(LOG_PL) << "Could not cast plugin" << _name;
|
||||
@ -140,3 +163,22 @@ bool QueuedPluginManager::unloadPlugin(const QString &_name)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @fn optionChanged
|
||||
*/
|
||||
void QueuedPluginManager::optionChanged(const QString &_key,
|
||||
const QVariant &_value)
|
||||
{
|
||||
qCDebug(LOG_PL) << "Option" << _key << "changed to" << _value;
|
||||
|
||||
auto option = convertOptionName(_key);
|
||||
if (!m_plugins.contains(option.first)) {
|
||||
qCWarning(LOG_PL) << "Plugin" << option.first << "not found for"
|
||||
<< _key;
|
||||
return;
|
||||
}
|
||||
|
||||
return m_plugins[option.first]->updateSettings(option.second, _value);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user