Ahenk/opt/ahenk/ahenkd.py

403 lines
16 KiB
Python
Raw Normal View History

2016-02-29 10:48:00 +02:00
#!/usr/bin/python3
2016-02-01 17:49:17 +02:00
# -*- coding: utf-8 -*-
# Author: İsmail BAŞARAN <ismail.basaran@tubitak.gov.tr> <basaran.ismaill@gmail.com>
2016-03-08 18:09:26 +02:00
# Author: Volkan Şahin <volkansah.in> <bm.volkansahin@gmail.com>
2016-02-01 17:49:17 +02:00
import os
import queue
import signal
import sys
import threading
import time
import json
from base.Scope import Scope
from base.command.commander import Commander
2016-02-08 19:03:38 +02:00
from base.config.ConfigManager import ConfigManager
from base.database.AhenkDbService import AhenkDbService
2016-02-25 17:24:07 +02:00
from base.deamon.BaseDeamon import BaseDaemon
from base.event.EventManager import EventManager
2016-03-08 18:09:26 +02:00
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
2016-04-13 11:55:45 +03:00
from base.plugin.plugin_manager_factory import PluginManagerFactory
from base.plugin.Plugin import Plugin
from base.registration.Registration import Registration
2016-04-05 17:55:15 +03:00
from base.scheduler.scheduler_factory import SchedulerFactory
from base.system.system import System
2016-04-13 11:55:45 +03:00
from base.task.TaskManager import TaskManager
from base.agreement.agreement import Agreement
from base.util.util import Util
from multiprocessing import Process
2016-02-01 17:49:17 +02:00
ahenkdaemon = None
2016-02-08 19:03:38 +02:00
2016-02-25 17:24:07 +02:00
class AhenkDeamon(BaseDaemon):
"""docstring for AhenkDeamon"""
2016-02-21 03:56:08 +02:00
2016-04-05 17:55:15 +03:00
def reload(self):
# reload service here
pass
2016-03-04 18:01:47 +02:00
2016-04-05 17:55:15 +03:00
def init_logger(self):
logger = Logger()
logger.info('[AhenkDeamon] Log was set')
Scope.getInstance().setLogger(logger)
return logger
def init_config_manager(self, configFilePath, configfileFolderPath):
configManager = ConfigManager(configFilePath, configfileFolderPath)
config = configManager.read()
Scope.getInstance().setConfigurationManager(config)
return config
def init_scheduler(self):
scheduler_ins = SchedulerFactory.get_intstance()
scheduler_ins.initialize()
Scope.getInstance().set_scheduler(scheduler_ins)
sc_thread = threading.Thread(target=scheduler_ins.run)
sc_thread.setDaemon(True)
sc_thread.start()
return scheduler_ins
2016-04-05 17:55:15 +03:00
def init_event_manager(self):
eventManager = EventManager()
Scope.getInstance().setEventManager(eventManager)
return eventManager
def init_ahenk_db(self):
db_service = AhenkDbService()
db_service.connect()
db_service.initialize_table()
Scope.getInstance().setDbService(db_service)
return db_service
def init_messaging(self):
messageManager = Messaging()
Scope.getInstance().setMessageManager(messageManager)
return messageManager
def init_plugin_manager(self):
2016-04-06 17:40:25 +03:00
pluginManager = PluginManagerFactory.get_instance()
2016-04-05 17:55:15 +03:00
pluginManager.loadPlugins()
Scope.getInstance().setPluginManager(pluginManager)
return pluginManager
def init_task_manager(self):
taskManager = TaskManager()
Scope.getInstance().setTaskManager(taskManager)
return taskManager
def init_registration(self):
registration = Registration()
Scope.getInstance().setRegistration(registration)
return registration
def init_execution_manager(self):
execution_manager = ExecutionManager()
Scope.getInstance().setExecutionManager(execution_manager)
return execution_manager
def init_messenger(self):
messenger = Messenger()
messenger.connect_to_server()
Scope.getInstance().setMessenger(messenger)
return messenger
2016-04-05 17:55:15 +03:00
def init_message_response_queue(self):
responseQueue = queue.Queue()
messageResponseQueue = MessageResponseQueue(responseQueue)
messageResponseQueue.setDaemon(True)
messageResponseQueue.start()
Scope.getInstance().setResponseQueue(responseQueue)
return responseQueue
def check_registration(self):
max_attemp_number = int(System.Hardware.Network.interface_size()) * 3
logger = Scope.getInstance().getLogger()
2016-06-21 17:47:25 +03:00
2016-04-08 15:54:26 +03:00
try:
while Scope.getInstance().getRegistration().is_registered() is False:
max_attemp_number -= 1
logger.debug('[AhenkDeamon] Ahenk is not registered. Attempting for registration')
2016-06-21 17:47:25 +03:00
# TODO 'Could not reach Registration response from Lider. Be sure Lider is running and it is connected to XMPP server!'
Scope.getInstance().getRegistration().registration_request()
if max_attemp_number < 0:
logger.warning('[AhenkDeamon] Number of Attempting for registration is over')
self.registration_failed()
break
2016-04-08 15:54:26 +03:00
except Exception as e:
logger.error('[AhenkDeamon] Registration failed. Error message: {}'.format(str(e)))
def shutdown_mode(self):
scope = Scope().getInstance()
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):
2016-06-21 17:47:25 +03:00
self.logger.error('[AhenkDeamon] Registration failed. All registration attemps were failed. Ahenk is stopping...')
print('Registration failed. Ahenk is stopping..')
ahenkdaemon.stop()
2016-04-08 15:54:26 +03:00
2016-04-06 17:40:25 +03:00
def reload_plugins(self):
Scope.getInstance().getPluginManager().reloadPlugins()
def reload_configuration(self):
# Not implemented yet
pass
def reload_messaging(self):
2016-04-11 19:27:26 +03:00
# Not implemented yet
2016-04-06 17:40:25 +03:00
pass
def reload_logger(self):
2016-04-11 19:27:26 +03:00
# Not implemented yet
2016-04-06 17:40:25 +03:00
pass
def update_plugin_manager(self):
2016-04-11 19:27:26 +03:00
# TODO destroy plugin manager here
2016-04-06 17:40:25 +03:00
self.init_plugin_manager()
def run(self):
print('Ahenk running...')
globalscope = Scope()
globalscope.setInstance(globalscope)
2016-02-25 01:46:27 +02:00
configfileFolderPath = '/etc/ahenk/config.d/'
2016-02-21 03:56:08 +02:00
# configuration manager must be first load
self.init_config_manager(System.Ahenk.config_path(), configfileFolderPath)
2016-02-21 03:56:08 +02:00
# Logger must be second
self.logger = self.init_logger()
2016-02-08 19:03:38 +02:00
2016-04-05 17:55:15 +03:00
self.init_event_manager()
self.logger.info('[AhenkDeamon] Event Manager was set')
2016-03-04 18:01:47 +02:00
2016-04-05 17:55:15 +03:00
self.init_ahenk_db()
self.logger.info('[AhenkDeamon] DataBase Service was set')
2016-04-05 17:55:15 +03:00
self.init_messaging()
self.logger.info('[AhenkDeamon] Message Manager was set')
2016-04-05 17:55:15 +03:00
self.init_plugin_manager()
self.logger.info('[AhenkDeamon] Plugin Manager was set')
2016-02-21 03:56:08 +02:00
2016-06-22 18:20:25 +03:00
self.init_scheduler()
self.logger.info('[AhenkDeamon] Scheduler was set')
2016-04-05 17:55:15 +03:00
self.init_task_manager()
self.logger.info('[AhenkDeamon] Task Manager was set')
2016-03-01 12:41:55 +02:00
2016-04-08 15:54:26 +03:00
self.init_registration()
self.logger.info('[AhenkDeamon] Registration was set')
2016-04-05 17:55:15 +03:00
self.init_execution_manager()
self.logger.info('[AhenkDeamon] Execution Manager was set')
2016-03-08 18:09:26 +02:00
2016-04-08 15:54:26 +03:00
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')
Agreement().agreement_contract_update()
2016-04-05 17:55:15 +03:00
self.init_message_response_queue()
# if registration.is_ldap_registered() is False:
2016-03-23 10:04:31 +02:00
# logger.debug('[AhenkDeamon] Attempting to registering ldap')
# registration.ldap_registration_request() #TODO work on message
self.logger.info('[AhenkDeamon] LDAP registration of Ahenk is completed')
with open(System.Ahenk.pid_path(), 'w+') as config_file:
config_file.write(str(os.getpid()))
try:
signal.signal(signal.SIGALRM, self.run_command_from_fifo)
self.logger.info('[AhenkDeamon] Signal handler is set up')
except Exception as e:
self.logger.error('[AhenkDeamon] Signal handler could not set up. Error Message: {} '.format(str(e)))
self.messenger.send_direct_message('test')
while True:
# if messager.is_connected() is False:
# self.logger.debug('reconnecting')
# Scope.getInstance().getLogger().warning('[AhenkDeamon] Connection is lost. Ahenk is trying for reconnection')
# messager = self.init_messager()
time.sleep(1)
def running_plugin(self):
scope = Scope().getInstance()
plugin_manager = scope.getPluginManager()
for plugin in plugin_manager.plugins:
if plugin.keep_run is True:
return False
return True
def run_command_from_fifo(self, num, stack):
json_data = json.loads(Commander().get_event())
if json_data is not None:
scope = Scope().getInstance()
plugin_manager = scope.getPluginManager()
message_manager = scope.getMessageManager()
messenger = scope.getMessenger()
2016-06-27 18:13:43 +03:00
conf_manager = scope.getConfigurationManager()
db_service = scope.getDbService()
self.logger.debug('[AhenkDeamon] Signal handled')
self.logger.debug('[AhenkDeamon] Signal is :{}'.format(str(json_data['event'])))
if 'login' == str(json_data['event']):
username = json_data['username']
display = json_data['display']
desktop = json_data['desktop']
self.logger.info('[AhenkDeamon] login event is handled for user: {}'.format(username))
login_message = message_manager.login_msg(username)
messenger.send_direct_message(login_message)
agreement = Agreement()
2016-06-28 12:24:02 +03:00
agreement_choice = None
2016-06-28 12:24:02 +03:00
if agreement.check_agreement(username) is not True:
self.logger.debug('[AhenkDeamon] User {} has not accepted agreement.'.format(username))
thread_ask = Process(target=agreement.ask, args=(username, display,))
thread_ask.start()
2016-06-27 18:13:43 +03:00
agreement_timeout = conf_manager.get('SESSION', 'agreement_timeout')
timeout = int(agreement_timeout) # sec
timer = time.time()
while 1:
if thread_ask.is_alive() is False:
self.logger.warning('[AhenkDeamon] {} was answered the question '.format(username))
2016-06-28 12:24:02 +03:00
if Agreement().check_agreement(username) is True:
self.logger.warning('[AhenkDeamon] Choice of {} is YES'.format(username))
agreement_choice = True
break
2016-06-28 12:24:02 +03:00
elif Agreement().check_agreement(username) is False:
self.logger.warning('[AhenkDeamon] Choice of {} is NO'.format(username))
agreement_choice = False
2016-06-28 12:24:02 +03:00
Util.execute('pkill -9 -u {}'.format(username))
break
if (time.time() - timer) > timeout:
if thread_ask.is_alive():
thread_ask.terminate()
Util.execute('pkill -9 -u {}'.format(username))
self.logger.warning('[AhenkDeamon] Session of {} was ended because of timeout of contract agreement'.format(username))
break
2016-06-28 12:24:02 +03:00
time.sleep(1)
if agreement_choice is not None:
2016-06-30 17:05:46 +03:00
messenger.send_direct_message(message_manager.agreement_answer_msg(username, agreement_choice))
else:
agreement_choice = True
if agreement_choice is True:
2016-06-27 18:13:43 +03:00
db_service.delete('session', 'username=\'{}\''.format(username))
db_service.update('session', scope.getDbService().get_cols('session'), [username, display, desktop, Util.timestamp()])
get_policy_message = message_manager.policy_request_msg(username)
2016-06-29 12:17:19 +03:00
plugin_manager.process_mode('safe', username)
plugin_manager.process_mode('login', username)
messenger.send_direct_message(get_policy_message)
elif 'logout' == str(json_data['event']):
username = json_data['username']
2016-06-27 18:13:43 +03:00
db_service.delete('session', 'username=\'{}\''.format(username))
self.logger.info('[AhenkDeamon] logout event is handled for user: {}'.format(username))
logout_message = message_manager.logout_msg(username)
messenger.send_direct_message(logout_message)
plugin_manager.process_mode('logout', username)
plugin_manager.process_mode('safe', username)
elif 'send' == str(json_data['event']):
self.logger.info('[AhenkDeamon] Sending message over ahenkd command. Response Message: {}'.format(str(json_data['message'])))
message = str(json.dumps(json_data['message']))
messenger.send_direct_message(message)
elif 'stop' == str(json_data['event']):
self.shutdown_mode()
self.logger.info('[AhenkDeamon] Shutdown mode activated.')
# TODO timeout
while self.running_plugin() is False:
self.logger.debug('[AhenkDeamon] Waiting for progress of plugins...')
time.sleep(0.5)
ahenkdaemon.stop()
else:
self.logger.error('[AhenkDeamon] Unknown command error. Command:' + json_data['event'])
self.logger.debug('[AhenkDeamon] Processing of handled event is completed')
return True
else:
return False
if __name__ == '__main__':
ahenkdaemon = AhenkDeamon(System.Ahenk.pid_path())
try:
if len(sys.argv) == 2 and (sys.argv[1] in ('start', 'stop', 'restart', 'status')):
if sys.argv[1] == 'start':
if System.Ahenk.is_running() is True:
print('There is already running Ahenk service. It will be killed.[{}]'.format(str(System.Ahenk.get_pid_number())))
System.Process.kill_by_pid(int(System.Ahenk.get_pid_number()))
else:
print('Ahenk starting...')
ahenkdaemon.run()
elif sys.argv[1] == 'stop':
if System.Ahenk.is_running() is True:
raise SystemExit
else:
print('Ahenk not working!')
elif sys.argv[1] == 'restart':
if System.Ahenk.is_running() is True:
print('Ahenk restarting...')
ahenkdaemon.restart()
else:
print('Ahenk starting...')
ahenkdaemon.run()
elif sys.argv[1] == 'status':
print(Commander().status())
else:
print('Unknown command. Usage : %s start|stop|restart|status|clean' % sys.argv[0])
sys.exit(2)
else:
result = Commander().set_event(sys.argv)
if result is None:
print('Usage : {0} start|stop|restart|status|clean'.format(sys.argv[0]))
sys.exit(2)
elif result is True:
if System.Ahenk.is_running() is True:
os.kill(int(System.Ahenk.get_pid_number()), signal.SIGALRM)
except(KeyboardInterrupt, SystemExit):
if System.Ahenk.is_running() is True:
print('Ahenk stopping...')
result = Commander().set_event(['stop'])
if result is True:
if System.Ahenk.is_running() is True:
os.kill(int(System.Ahenk.get_pid_number()), signal.SIGALRM)
else:
ahenkdaemon.stop()