new plugins commands added: load,reload and remove with parameters dynamically. Ahenk is loading plugins automatically which is installed while running ahenk

This commit is contained in:
Volkan Şahin 2016-07-18 18:21:03 +03:00
parent 1e35065b95
commit 0690e65264
3 changed files with 160 additions and 65 deletions

View file

@ -3,14 +3,17 @@
# Author: İsmail BAŞARAN <ismail.basaran@tubitak.gov.tr> <basaran.ismaill@gmail.com>
# Author: Volkan Şahin <volkansah.in> <bm.volkansahin@gmail.com>
import json
import os
import queue
import signal
import sys
import threading
import time
import json
from multiprocessing import Process
from base.Scope import Scope
from base.agreement.agreement import Agreement
from base.command.commander import Commander
from base.config.ConfigManager import ConfigManager
from base.database.AhenkDbService import AhenkDbService
@ -19,17 +22,14 @@ from base.event.EventManager import EventManager
from base.execution.ExecutionManager import ExecutionManager
from base.logger.AhenkLogger import Logger
from base.messaging.MessageResponseQueue import MessageResponseQueue
from base.messaging.Messenger import Messenger
from base.messaging.Messaging import Messaging
from base.messaging.Messenger import Messenger
from base.plugin.plugin_manager_factory import PluginManagerFactory
from base.plugin.Plugin import Plugin
from base.registration.Registration import Registration
from base.scheduler.scheduler_factory import SchedulerFactory
from base.system.system import System
from base.task.TaskManager import TaskManager
from base.agreement.agreement import Agreement
from base.util.util import Util
from multiprocessing import Process
ahenkdaemon = None
@ -81,8 +81,9 @@ class AhenkDeamon(BaseDaemon):
def init_plugin_manager(self):
pluginManager = PluginManagerFactory.get_instance()
pluginManager.loadPlugins()
Scope.getInstance().setPluginManager(pluginManager)
# order changed, problem?
pluginManager.load_plugins()
return pluginManager
def init_task_manager(self):
@ -136,11 +137,6 @@ class AhenkDeamon(BaseDaemon):
plugin_manager = scope.getPluginManager()
plugin_manager.process_mode('shutdown')
def init_mode(self):
scope = Scope().getInstance()
plugin_manager = scope.getPluginManager()
plugin_manager.process_mode('init')
def registration_failed(self):
self.logger.error('[AhenkDeamon] Registration failed. All registration attemps were failed. Ahenk is stopping...')
print('Registration failed. Ahenk is stopping..')
@ -206,9 +202,6 @@ class AhenkDeamon(BaseDaemon):
self.check_registration()
self.logger.info('[AhenkDeamon] Ahenk was registered')
self.init_mode()
self.logger.info('[AhenkDeamon] Plugins were initialized')
self.messenger = self.init_messenger()
self.logger.info('[AhenkDeamon] Messager was set')
@ -312,6 +305,9 @@ class AhenkDeamon(BaseDaemon):
if agreement_choice is True:
db_service.delete('session', 'username=\'{}\''.format(username))
self.logger.info('[AhenkDeamon] Display is {0}, desktop env is {1} for {2}'.format(display, desktop, username))
db_service.update('session', scope.getDbService().get_cols('session'), [username, display, desktop, Util.timestamp()])
get_policy_message = message_manager.policy_request_msg(username)
@ -335,6 +331,38 @@ class AhenkDeamon(BaseDaemon):
message = str(json.dumps(json_data['message']))
messenger.send_direct_message(message)
elif 'load' == str(json_data['event']):
plugin_name = str(json_data['plugins'])
if plugin_name == 'all':
self.logger.info('[AhenkDeamon] All plugins are loading to ahenk'.format(plugin_name))
plugin_manager.load_plugins()
else:
for p_name in plugin_name.split(','):
self.logger.info('[AhenkDeamon] {} plugin is loading to ahenk'.format(p_name))
plugin_manager.load_single_plugin(p_name)
elif 'reload' == str(json_data['event']):
plugin_name = str(json_data['plugins'])
self.logger.info('[AhenkDeamon] {} plugin/s is/are reloading to ahenk'.format(plugin_name))
if plugin_name == 'all':
plugin_manager.reload_plugins()
else:
for p_name in plugin_name.split(','):
plugin_manager.reload_single_plugin(p_name)
elif 'remove' == str(json_data['event']):
plugin_name = str(json_data['plugins'])
if plugin_name == 'all':
self.logger.info('[AhenkDeamon] All plugins are removing from ahenk'.format(plugin_name))
plugin_manager.remove_plugins()
else:
for p_name in plugin_name.split(','):
self.logger.info('[AhenkDeamon] {} plugin is removing from ahenk'.format(p_name))
plugin_manager.remove_single_plugin(p_name)
elif 'stop' == str(json_data['event']):
self.shutdown_mode()
self.logger.info('[AhenkDeamon] Shutdown mode activated.')
@ -394,7 +422,7 @@ if __name__ == '__main__':
except(KeyboardInterrupt, SystemExit):
if System.Ahenk.is_running() is True:
print('Ahenk stopping...')
result = Commander().set_event(['stop'])
result = Commander().set_event([None, 'stop'])
if result is True:
if System.Ahenk.is_running() is True:
os.kill(int(System.Ahenk.get_pid_number()), signal.SIGALRM)

View file

@ -5,7 +5,6 @@ import os
import queue as Queue
import threading
from base.Scope import Scope
from base.command.fifo import Fifo
from base.model.enum.ContentType import ContentType
from base.model.enum.MessageCode import MessageCode
@ -19,9 +18,14 @@ class Commander(object):
pass
def set_event(self, *args):
if args is None or len(args) < 1:
print('ERR')
params = args[0]
data = {}
if System.Ahenk.is_running() is True:
if len(params) > 1 and params[1] == 'clean':
@ -42,9 +46,21 @@ class Commander(object):
data['event'] = params[1]
data['username'] = params[2]
elif params[0] == 'stop':
elif len(params) == 2 and params[1] == 'stop':
data['event'] = 'stop'
elif len(params) == 4 and params[1] == 'load' and params[2] == '-p':
data['event'] = 'load'
data['plugins'] = params[3]
elif len(params) == 4 and params[1] == 'reload' and params[2] == '-p':
data['event'] = 'reload'
data['plugins'] = params[3]
elif len(params) == 4 and params[1] == 'remove' and params[2] == '-p':
data['event'] = 'remove'
data['plugins'] = params[3]
elif len(params) > 5 and params[1] == 'send':
data['event'] = params[1]
response = {}

View file

@ -4,6 +4,7 @@
# Author: Volkan Şahin <volkansah.in> <bm.volkansahin@gmail.com>
import imp
import os
from multiprocessing import Process
from base.Scope import Scope
from base.model.PluginBean import PluginBean
@ -15,60 +16,66 @@ from base.model.modes.safe_mode import SafeMode
from base.model.modes.shutdown_mode import ShutdownMode
from base.plugin.Plugin import Plugin
from base.plugin.PluginQueue import PluginQueue
from base.plugin.plugin_install_listener import PluginInstallListener
from base.system.system import System
# TODO create base abstract class
class PluginManager(object):
"""docstring for PluginManager"""
# implement logger
def __init__(self):
super(PluginManager, self).__init__()
self.scope = Scope.getInstance()
self.configManager = self.scope.getConfigurationManager()
self.db_service = self.scope.getDbService()
self.message_manager = self.scope.getMessageManager()
self.logger = self.scope.getLogger()
self.plugins = []
self.pluginQueueDict = dict()
self.logger = self.scope.getLogger()
self.message_manager = self.scope.getMessageManager()
self.listener = self.install_listener()
self.delayed_profiles = {}
self.delayed_tasks = {}
# TODO version?
def loadPlugins(self):
"""
This method loads plugins
"""
def load_plugins(self):
self.logger.info('[PluginManager] Loading plugins...')
self.plugins = []
self.logger.debug('[PluginManager] Lookup for possible plugins...')
try:
possible_plugins = os.listdir(self.configManager.get("PLUGIN", "pluginFolderPath"))
self.logger.debug('[PluginManager] Possible plugins: {} '.format(str(possible_plugins)))
for plugin_name in possible_plugins:
location = os.path.join(self.configManager.get("PLUGIN", "pluginFolderPath"), plugin_name)
if not os.path.isdir(location) or not self.configManager.get("PLUGIN", "mainModuleName") + ".py" in os.listdir(location):
self.logger.debug('It is not a plugin location ! There is no main module - {}'.format(str(location)))
continue
try:
self.loadSinglePlugin(plugin_name)
self.load_single_plugin(plugin_name)
except Exception as e:
self.logger.error('[PluginManager] Exception occurred when loading plugin ! Plugin name : {} .Error Message: {}'.format(str(plugin_name), str(e)))
self.logger.error('[PluginManager] Exception occurred while loading plugin ! Plugin name : {}. Error Message: {}'.format(str(plugin_name), str(e)))
self.logger.info('[PluginManager] Loaded plugins successfully.')
except Exception as e:
self.logger.warning('[PluginManager] Plugin folder path not found. Error Message: {}'.format(str(e)))
def loadSinglePlugin(self, plugin_name):
def load_single_plugin(self, plugin_name):
# TODO check already loaded plugin
location = os.path.join(self.configManager.get("PLUGIN", "pluginFolderPath"), plugin_name)
if not os.path.isdir(location) or not self.configManager.get("PLUGIN", "mainModuleName") + ".py" in os.listdir(location):
self.logger.debug('[PluginManager] It is not a plugin location ! There is no main module - {}'.format(str(location)))
else:
if self.is_plugin_loaded(plugin_name):
self.logger.debug('[PluginManager] {0} plugin was already loaded. Reloading {0} plugin'.format(plugin_name))
self.reload_single_plugin(plugin_name)
else:
self.pluginQueueDict[plugin_name] = PluginQueue()
plugin = Plugin(plugin_name, self.pluginQueueDict[plugin_name])
plugin.setDaemon(True)
plugin.start()
self.plugins.append(plugin)
self.logger.debug('[PluginManager] New plugin was loaded. Plugin Name: {}'.format(plugin_name))
# active init mode
mode = InitMode()
self.pluginQueueDict[plugin_name].put(mode, 1)
if len(self.delayed_profiles) > 0:
self.pluginQueueDict[plugin_name].put(self.delayed_profiles[plugin_name], 1)
self.logger.debug('[PluginManager] Delayed profile was found for this plugin. It will be run.')
@ -76,7 +83,58 @@ class PluginManager(object):
self.pluginQueueDict[plugin_name].put(self.delayed_tasks[plugin_name], 1)
self.logger.debug('[PluginManager] Delayed task was found for this plugin. It will be run.')
def findCommand(self, pluginName, commandId):
def reload_plugins(self):
try:
self.logger.info('[PluginManager] Reloading plugins...')
kill_signal = PluginKillSignal()
for p_queue in self.pluginQueueDict:
p_queue.put(kill_signal)
self.plugins = []
self.load_plugins()
self.logger.info('[PluginManager] Plugin reloaded successfully.')
except Exception as e:
self.logger.error('[PluginManager] Exception occurred when reloading plugins ' + str(e))
def reload_single_plugin(self, plugin_name):
try:
self.logger.info('[PluginManager] {} plugin is reloading'.format(plugin_name))
self.logger.debug('[PluginManager] {} plugin is killing (in reloading action)'.format(plugin_name))
self.remove_single_plugin(plugin_name)
self.logger.debug('[PluginManager] {} plugin is loading (in reloading action)'.format(plugin_name))
self.load_single_plugin(plugin_name)
except Exception as e:
self.logger.error('[PluginManager] A problem occurred while reloading {0} plugin. Error Message: {1}'.format(plugin_name, str(e)))
def remove_plugins(self):
try:
self.logger.debug('[PluginManager] Removing all plugins...')
for p_queue in self.pluginQueueDict:
p_queue.put(PluginKillSignal())
# todo check is running
self.plugins = []
self.pluginQueueDict = dict()
self.logger.debug('[PluginManager] All plugins were removed successfully.')
except Exception as e:
self.logger.debug('[PluginManager] A problem occurred while removing plugins. Error Message :{0}.'.format(str(e)))
def remove_single_plugin(self, plugin_name):
try:
self.logger.debug('[PluginManager] Trying to remove {} plugin...'.format(plugin_name))
if self.is_plugin_loaded(plugin_name):
self.logger.debug('[PluginManager] {} plugin is killing...'.format(plugin_name))
self.pluginQueueDict[plugin_name].put(PluginKillSignal(), 1)
del self.pluginQueueDict[plugin_name]
for plugin in self.plugins:
if plugin.name == plugin_name:
self.plugins.remove(plugin)
self.logger.debug('[PluginManager] {} plugin was removed.'.format(plugin_name))
else:
self.logger.warning('[PluginManager] {} plugin not found.'.format(plugin_name))
except Exception as e:
self.logger.error('[PluginManager] A problem occurred while removing {0} plugin. Error Message :{1}.'.format(plugin_name, str(e)))
def find_command(self, pluginName, commandId):
location = os.path.join(self.configManager.get("PLUGIN", "pluginFolderPath"), pluginName)
if os.path.isdir(location) and commandId + ".py" in os.listdir(location):
info = imp.find_module(commandId, [location])
@ -85,7 +143,7 @@ class PluginManager(object):
self.logger.warning('Command id -' + commandId + ' - not found')
return None
def processTask(self, task):
def process_task(self, task):
##
scope = Scope().getInstance()
@ -105,19 +163,7 @@ class PluginManager(object):
except Exception as e:
self.logger.error('[PluginManager] Exception occurred while processing task. Error Message: {}'.format(str(e)))
def reloadPlugins(self):
try:
self.logger.info('[PluginManager] Reloading plugins... ')
kill_sgnl = PluginKillSignal()
for p_queue in self.pluginQueueDict:
p_queue.put(kill_sgnl)
self.plugins = []
self.loadPlugins()
self.logger.info('[PluginManager] Plugin reloaded successfully.')
except Exception as e:
self.logger.error('[PluginManager] Exception occurred when reloading plugins ' + str(e))
def findPolicyModule(self, plugin_name):
def find_policy_module(self, plugin_name):
location = os.path.join(self.configManager.get("PLUGIN", "pluginFolderPath"), plugin_name)
if os.path.isdir(location) and "policy.py" in os.listdir(location):
info = imp.find_module("policy", [location])
@ -126,13 +172,7 @@ class PluginManager(object):
self.logger.warning('[PluginManager] policy.py not found Plugin Name : ' + str(plugin_name))
return None
def is_profile_overridable(self, profiles, plugin_name):
for profile in profiles:
if profile.plugin.name == plugin_name and profile.overridable.lower() == 'true':
return True
return False
def processPolicy(self, policy):
def process_policy(self, policy):
self.logger.info('[PluginManager] Processing policies...')
username = policy.username
@ -143,7 +183,7 @@ class PluginManager(object):
self.logger.info('[PluginManager] Working on Ahenk profiles...')
for agent_profile in ahenk_profiles:
if agent_profile.overridable.lower() != 'true' and self.is_profile_overridable(policy.user_profiles, agent_profile.plugin.name) is True:
if agent_profile.overridable.lower() != 'true':
temp_list = []
self.logger.debug('[PluginManager] User profile of {0} plugin will not executed because of profile override rules.'.format(agent_profile.plugin.name))
for usr_profile in user_profiles:
@ -183,7 +223,7 @@ class PluginManager(object):
except Exception as e:
self.logger.error('[PluginManager] Exception occurred while processing profile. Error Message: {}'.format(str(e)))
def checkPluginExists(self, plugin_name, version=None):
def check_plugin_exists(self, plugin_name, version=None):
criteria = ' name=\'' + plugin_name + '\''
if version is not None:
@ -211,6 +251,7 @@ class PluginManager(object):
self.logger.error('[PluginManager] Unknown mode type: {}'.format(mode_type))
if mode is not None:
self.logger.info('[PluginManager] {} mode is running'.format(mode_type))
for plugin_name in self.pluginQueueDict:
try:
self.pluginQueueDict[plugin_name].put(mode, 1)
@ -228,10 +269,20 @@ class PluginManager(object):
self.logger.warning('[PluginManager] safe.py not found Plugin Name : ' + str(plugin_name))
return None
def reloadSinglePlugin(self, pluginName):
# Not implemented yet
def install_listener(self):
listener = PluginInstallListener()
thread = Process(target=listener.listen, args=(System.Ahenk.plugins_path(),))
thread.start()
return thread
pass
def is_plugin_loaded(self, plugin_name):
try:
if self.pluginQueueDict[plugin_name] is not None:
return True
else:
return False
except Exception as e:
return False
def checkCommandExist(self, pluginName, commandId):
# Not implemented yet