2016-04-06 17:40:25 +03:00
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Author: İsmail BAŞARAN <ismail.basaran@tubitak.gov.tr> <basaran.ismaill@gmail.com>
2016-05-06 16:40:06 +03:00
# Author: Volkan Şahin <volkansah.in> <bm.volkansahin@gmail.com>
2016-04-06 17:40:25 +03:00
import imp
import os
2016-07-18 18:21:03 +03:00
from multiprocessing import Process
2016-04-06 17:40:25 +03:00
from base . Scope import Scope
2016-07-13 17:37:03 +03:00
from base . model . PluginBean import PluginBean
from base . model . PluginKillSignal import PluginKillSignal
from base . model . modes . init_mode import InitMode
from base . model . modes . login_mode import LoginMode
from base . model . modes . logout_mode import LogoutMode
from base . model . modes . safe_mode import SafeMode
from base . model . modes . shutdown_mode import ShutdownMode
2016-04-06 17:40:25 +03:00
from base . plugin . Plugin import Plugin
from base . plugin . PluginQueue import PluginQueue
2016-07-18 18:21:03 +03:00
from base . plugin . plugin_install_listener import PluginInstallListener
from base . system . system import System
2016-05-06 16:40:06 +03:00
2016-04-06 17:40:25 +03:00
# TODO create base abstract class
class PluginManager ( object ) :
""" docstring for PluginManager """
def __init__ ( self ) :
super ( PluginManager , self ) . __init__ ( )
self . scope = Scope . getInstance ( )
self . configManager = self . scope . getConfigurationManager ( )
self . db_service = self . scope . getDbService ( )
2016-07-18 18:21:03 +03:00
self . message_manager = self . scope . getMessageManager ( )
self . logger = self . scope . getLogger ( )
2016-04-06 17:40:25 +03:00
self . plugins = [ ]
self . pluginQueueDict = dict ( )
2016-07-18 18:21:03 +03:00
self . listener = self . install_listener ( )
2016-05-06 16:40:06 +03:00
self . delayed_profiles = { }
self . delayed_tasks = { }
2016-04-06 17:40:25 +03:00
2016-05-06 16:40:06 +03:00
# TODO version?
2016-07-18 18:21:03 +03:00
def load_plugins ( self ) :
2016-04-06 17:40:25 +03:00
self . logger . info ( ' [PluginManager] Loading plugins... ' )
self . plugins = [ ]
self . logger . debug ( ' [PluginManager] Lookup for possible plugins... ' )
2016-05-17 12:32:48 +03:00
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 :
try :
2016-07-18 18:21:03 +03:00
self . load_single_plugin ( plugin_name )
2016-05-17 12:32:48 +03:00
except Exception as e :
2016-07-18 18:21:03 +03:00
self . logger . error ( ' [PluginManager] Exception occurred while loading plugin ! Plugin name : {} . Error Message: {} ' . format ( str ( plugin_name ) , str ( e ) ) )
2016-05-17 12:32:48 +03:00
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 ) ) )
2016-04-06 17:40:25 +03:00
2016-07-18 18:21:03 +03:00
def load_single_plugin ( self , plugin_name ) :
2016-04-06 17:40:25 +03:00
# TODO check already loaded plugin
2016-07-18 18:21:03 +03:00
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 ) )
2016-04-06 17:40:25 +03:00
2016-07-18 18:21:03 +03:00
# active init mode
mode = InitMode ( )
self . pluginQueueDict [ plugin_name ] . put ( mode , 1 )
2016-05-06 16:40:06 +03:00
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. ' )
if len ( self . delayed_tasks ) > 0 :
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. ' )
2016-07-18 18:21:03 +03:00
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 ) :
2016-04-06 17:40:25 +03:00
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 ] )
return imp . load_module ( commandId , * info )
else :
self . logger . warning ( ' Command id - ' + commandId + ' - not found ' )
return None
2016-07-18 18:21:03 +03:00
def process_task ( self , task ) :
2016-04-11 19:32:05 +03:00
2016-05-06 16:40:06 +03:00
##
scope = Scope ( ) . getInstance ( )
2016-06-20 17:35:59 +03:00
self . messenger = scope . getMessenger ( )
2016-05-06 16:40:06 +03:00
##
2016-04-06 17:40:25 +03:00
try :
2016-05-06 16:40:06 +03:00
plugin_name = task . get_plugin ( ) . get_name ( ) . lower ( )
plugin_ver = task . get_plugin ( ) . get_version ( )
if plugin_name in self . pluginQueueDict :
self . pluginQueueDict [ plugin_name ] . put ( task , 1 )
else :
self . logger . warning ( ' [PluginManager] {} plugin not found. Task was delayed. Ahenk will request plugin from Lider if distribution available ' . format ( plugin_name ) )
self . delayed_tasks [ plugin_name ] = task
msg = self . message_manager . missing_plugin_message ( PluginBean ( name = plugin_name , version = plugin_ver ) )
self . messenger . send_direct_message ( msg )
2016-04-06 17:40:25 +03:00
except Exception as e :
2016-05-06 16:40:06 +03:00
self . logger . error ( ' [PluginManager] Exception occurred while processing task. Error Message: {} ' . format ( str ( e ) ) )
2016-04-06 17:40:25 +03:00
2016-07-18 18:21:03 +03:00
def find_policy_module ( self , plugin_name ) :
2016-04-06 17:40:25 +03:00
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 ] )
return imp . load_module ( " policy " , * info )
else :
self . logger . warning ( ' [PluginManager] policy.py not found Plugin Name : ' + str ( plugin_name ) )
return None
2016-07-18 18:21:03 +03:00
def process_policy ( self , policy ) :
2016-04-06 17:40:25 +03:00
2016-05-06 16:40:06 +03:00
self . logger . info ( ' [PluginManager] Processing policies... ' )
2016-04-06 17:40:25 +03:00
username = policy . username
ahenk_profiles = policy . ahenk_profiles
user_profiles = policy . user_profiles
if ahenk_profiles is not None :
2016-05-06 16:40:06 +03:00
self . logger . info ( ' [PluginManager] Working on Ahenk profiles... ' )
2016-07-14 16:26:39 +03:00
for agent_profile in ahenk_profiles :
2016-07-18 18:21:03 +03:00
if agent_profile . overridable . lower ( ) != ' true ' :
2016-07-14 16:26:39 +03:00
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 :
if usr_profile . plugin . name != agent_profile . plugin . name :
temp_list . append ( usr_profile )
user_profiles = temp_list
else :
self . logger . debug ( ' [PluginManager] Agent profile of {0} plugin will not executed because of profile override rules. ' . format ( agent_profile . plugin . name ) )
continue
agent_profile . set_username ( None )
self . process_profile ( agent_profile )
2016-04-06 17:40:25 +03:00
if user_profiles is not None :
2016-05-06 16:40:06 +03:00
self . logger . info ( ' [PluginManager] Working on User profiles... ' )
2016-07-14 16:26:39 +03:00
for user_profile in user_profiles :
user_profile . set_username ( username )
self . process_profile ( user_profile )
2016-04-06 17:40:25 +03:00
def process_profile ( self , profile ) :
2016-05-06 16:40:06 +03:00
##
scope = Scope ( ) . getInstance ( )
2016-06-20 17:35:59 +03:00
self . messenger = scope . getMessenger ( )
2016-05-06 16:40:06 +03:00
##
2016-04-06 17:40:25 +03:00
try :
plugin = profile . get_plugin ( )
2016-04-07 19:18:22 +03:00
plugin_name = plugin . get_name ( )
2016-05-06 16:40:06 +03:00
plugin_ver = plugin . get_version ( )
2016-04-06 17:40:25 +03:00
if plugin_name in self . pluginQueueDict :
self . pluginQueueDict [ plugin_name ] . put ( profile , 1 )
2016-05-06 16:40:06 +03:00
else :
self . logger . warning ( ' [PluginManager] {} plugin not found. Profile was delayed. Ahenk will request plugin from Lider if distribution available ' . format ( plugin_name ) )
self . delayed_profiles [ plugin_name ] = profile
msg = self . message_manager . missing_plugin_message ( PluginBean ( name = plugin_name , version = plugin_ver ) )
self . messenger . send_direct_message ( msg )
2016-04-06 17:40:25 +03:00
except Exception as e :
2016-05-06 16:40:06 +03:00
self . logger . error ( ' [PluginManager] Exception occurred while processing profile. Error Message: {} ' . format ( str ( e ) ) )
2016-04-06 17:40:25 +03:00
2016-07-18 18:21:03 +03:00
def check_plugin_exists ( self , plugin_name , version = None ) :
2016-04-06 17:40:25 +03:00
2016-05-06 16:40:06 +03:00
criteria = ' name= \' ' + plugin_name + ' \' '
2016-04-06 17:40:25 +03:00
if version is not None :
criteria + = ' and version= \' ' + str ( version ) + ' \' '
result = self . db_service . select ( ' plugin ' , ' name ' , criteria )
if result is None :
return False
else :
return True
2016-07-13 17:37:03 +03:00
def process_mode ( self , mode_type , username = None ) :
mode = None
if mode_type == ' init ' :
mode = InitMode ( )
elif mode_type == ' shutdown ' :
mode = ShutdownMode ( )
elif mode_type == ' login ' :
mode = LoginMode ( username )
elif mode_type == ' logout ' :
mode = LogoutMode ( username )
elif mode_type == ' safe ' :
mode = SafeMode ( username )
else :
self . logger . error ( ' [PluginManager] Unknown mode type: {} ' . format ( mode_type ) )
if mode is not None :
2016-07-18 18:21:03 +03:00
self . logger . info ( ' [PluginManager] {} mode is running ' . format ( mode_type ) )
2016-07-13 17:37:03 +03:00
for plugin_name in self . pluginQueueDict :
try :
self . pluginQueueDict [ plugin_name ] . put ( mode , 1 )
except Exception as e :
self . logger . error ( ' [PluginManager] Exception occurred while switching safe mode. Error Message : {} ' . format ( str ( e ) ) )
def find_module ( self , mode , plugin_name ) :
mode = mode . lower ( ) . replace ( ' _mode ' , ' ' )
2016-05-09 17:50:39 +03:00
location = os . path . join ( self . configManager . get ( " PLUGIN " , " pluginFolderPath " ) , plugin_name )
2016-07-13 17:37:03 +03:00
if os . path . isdir ( location ) and ( mode + " .py " ) in os . listdir ( location ) :
info = imp . find_module ( mode , [ location ] )
return imp . load_module ( mode , * info )
2016-05-09 17:50:39 +03:00
else :
self . logger . warning ( ' [PluginManager] safe.py not found Plugin Name : ' + str ( plugin_name ) )
return None
2016-07-18 18:21:03 +03:00
def install_listener ( self ) :
listener = PluginInstallListener ( )
thread = Process ( target = listener . listen , args = ( System . Ahenk . plugins_path ( ) , ) )
thread . start ( )
return thread
2016-04-06 17:40:25 +03:00
2016-07-18 18:21:03 +03:00
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
2016-04-06 17:40:25 +03:00
def checkCommandExist ( self , pluginName , commandId ) :
# Not implemented yet
pass
def printQueueSize ( self ) :
print ( " size " + str ( len ( self . pluginQueueDict ) ) )