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

View file

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

View file

@ -4,6 +4,7 @@
# Author: Volkan Şahin <volkansah.in> <bm.volkansahin@gmail.com> # Author: Volkan Şahin <volkansah.in> <bm.volkansahin@gmail.com>
import imp import imp
import os import os
from multiprocessing import Process
from base.Scope import Scope from base.Scope import Scope
from base.model.PluginBean import PluginBean from base.model.PluginBean import PluginBean
@ -15,59 +16,65 @@ from base.model.modes.safe_mode import SafeMode
from base.model.modes.shutdown_mode import ShutdownMode from base.model.modes.shutdown_mode import ShutdownMode
from base.plugin.Plugin import Plugin from base.plugin.Plugin import Plugin
from base.plugin.PluginQueue import PluginQueue 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 # TODO create base abstract class
class PluginManager(object): class PluginManager(object):
"""docstring for PluginManager""" """docstring for PluginManager"""
# implement logger
def __init__(self): def __init__(self):
super(PluginManager, self).__init__() super(PluginManager, self).__init__()
self.scope = Scope.getInstance() self.scope = Scope.getInstance()
self.configManager = self.scope.getConfigurationManager() self.configManager = self.scope.getConfigurationManager()
self.db_service = self.scope.getDbService() self.db_service = self.scope.getDbService()
self.message_manager = self.scope.getMessageManager()
self.logger = self.scope.getLogger()
self.plugins = [] self.plugins = []
self.pluginQueueDict = dict() self.pluginQueueDict = dict()
self.logger = self.scope.getLogger()
self.message_manager = self.scope.getMessageManager() self.listener = self.install_listener()
self.delayed_profiles = {} self.delayed_profiles = {}
self.delayed_tasks = {} self.delayed_tasks = {}
# TODO version? # TODO version?
def loadPlugins(self): def load_plugins(self):
"""
This method loads plugins
"""
self.logger.info('[PluginManager] Loading plugins...') self.logger.info('[PluginManager] Loading plugins...')
self.plugins = [] self.plugins = []
self.logger.debug('[PluginManager] Lookup for possible plugins...') self.logger.debug('[PluginManager] Lookup for possible plugins...')
try: try:
possible_plugins = os.listdir(self.configManager.get("PLUGIN", "pluginFolderPath")) possible_plugins = os.listdir(self.configManager.get("PLUGIN", "pluginFolderPath"))
self.logger.debug('[PluginManager] Possible plugins: {} '.format(str(possible_plugins))) self.logger.debug('[PluginManager] Possible plugins: {} '.format(str(possible_plugins)))
for plugin_name in 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: try:
self.loadSinglePlugin(plugin_name) self.load_single_plugin(plugin_name)
except Exception as e: 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.') self.logger.info('[PluginManager] Loaded plugins successfully.')
except Exception as e: except Exception as e:
self.logger.warning('[PluginManager] Plugin folder path not found. Error Message: {}'.format(str(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 # TODO check already loaded plugin
self.pluginQueueDict[plugin_name] = PluginQueue() location = os.path.join(self.configManager.get("PLUGIN", "pluginFolderPath"), plugin_name)
plugin = Plugin(plugin_name, self.pluginQueueDict[plugin_name]) if not os.path.isdir(location) or not self.configManager.get("PLUGIN", "mainModuleName") + ".py" in os.listdir(location):
plugin.setDaemon(True) self.logger.debug('[PluginManager] It is not a plugin location ! There is no main module - {}'.format(str(location)))
plugin.start() else:
self.plugins.append(plugin) 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))
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: if len(self.delayed_profiles) > 0:
self.pluginQueueDict[plugin_name].put(self.delayed_profiles[plugin_name], 1) self.pluginQueueDict[plugin_name].put(self.delayed_profiles[plugin_name], 1)
@ -76,7 +83,58 @@ class PluginManager(object):
self.pluginQueueDict[plugin_name].put(self.delayed_tasks[plugin_name], 1) 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.') 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) location = os.path.join(self.configManager.get("PLUGIN", "pluginFolderPath"), pluginName)
if os.path.isdir(location) and commandId + ".py" in os.listdir(location): if os.path.isdir(location) and commandId + ".py" in os.listdir(location):
info = imp.find_module(commandId, [location]) info = imp.find_module(commandId, [location])
@ -85,7 +143,7 @@ class PluginManager(object):
self.logger.warning('Command id -' + commandId + ' - not found') self.logger.warning('Command id -' + commandId + ' - not found')
return None return None
def processTask(self, task): def process_task(self, task):
## ##
scope = Scope().getInstance() scope = Scope().getInstance()
@ -105,19 +163,7 @@ class PluginManager(object):
except Exception as e: except Exception as e:
self.logger.error('[PluginManager] Exception occurred while processing task. Error Message: {}'.format(str(e))) self.logger.error('[PluginManager] Exception occurred while processing task. Error Message: {}'.format(str(e)))
def reloadPlugins(self): def find_policy_module(self, plugin_name):
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):
location = os.path.join(self.configManager.get("PLUGIN", "pluginFolderPath"), 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): if os.path.isdir(location) and "policy.py" in os.listdir(location):
info = imp.find_module("policy", [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)) self.logger.warning('[PluginManager] policy.py not found Plugin Name : ' + str(plugin_name))
return None return None
def is_profile_overridable(self, profiles, plugin_name): def process_policy(self, policy):
for profile in profiles:
if profile.plugin.name == plugin_name and profile.overridable.lower() == 'true':
return True
return False
def processPolicy(self, policy):
self.logger.info('[PluginManager] Processing policies...') self.logger.info('[PluginManager] Processing policies...')
username = policy.username username = policy.username
@ -143,7 +183,7 @@ class PluginManager(object):
self.logger.info('[PluginManager] Working on Ahenk profiles...') self.logger.info('[PluginManager] Working on Ahenk profiles...')
for agent_profile in 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 = [] temp_list = []
self.logger.debug('[PluginManager] User profile of {0} plugin will not executed because of profile override rules.'.format(agent_profile.plugin.name)) 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: for usr_profile in user_profiles:
@ -183,7 +223,7 @@ class PluginManager(object):
except Exception as e: except Exception as e:
self.logger.error('[PluginManager] Exception occurred while processing profile. Error Message: {}'.format(str(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 + '\'' criteria = ' name=\'' + plugin_name + '\''
if version is not None: if version is not None:
@ -211,6 +251,7 @@ class PluginManager(object):
self.logger.error('[PluginManager] Unknown mode type: {}'.format(mode_type)) self.logger.error('[PluginManager] Unknown mode type: {}'.format(mode_type))
if mode is not None: if mode is not None:
self.logger.info('[PluginManager] {} mode is running'.format(mode_type))
for plugin_name in self.pluginQueueDict: for plugin_name in self.pluginQueueDict:
try: try:
self.pluginQueueDict[plugin_name].put(mode, 1) 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)) self.logger.warning('[PluginManager] safe.py not found Plugin Name : ' + str(plugin_name))
return None return None
def reloadSinglePlugin(self, pluginName): def install_listener(self):
# Not implemented yet 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): def checkCommandExist(self, pluginName, commandId):
# Not implemented yet # Not implemented yet