crafty-4/app/classes/shared/tasks.py

218 lines
8.1 KiB
Python
Raw Normal View History

2020-08-12 00:36:09 +00:00
import os
import sys
import json
import time
import logging
import threading
import asyncio
2020-08-12 00:36:09 +00:00
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
from app.classes.web.tornado import Webserver
from app.classes.web.websocket_helper import websocket_helper
2020-08-23 22:43:28 +00:00
from app.classes.minecraft.serverjars import server_jar_obj
from app.classes.shared.models import db_helper
2020-08-12 00:36:09 +00:00
logger = logging.getLogger(__name__)
try:
import schedule
except ModuleNotFoundError as e:
logger.critical("Import Error: Unable to load {} module".format(e.name), exc_info=True)
console.critical("Import Error: Unable to load {} module".format(e.name), exc_info=True)
sys.exit(1)
2020-08-12 00:36:09 +00:00
scheduler_intervals = { 'seconds',
'minutes',
'hours',
'days',
'weeks',
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
'saturday',
'sunday'
}
2020-08-12 00:36:09 +00:00
class TasksManager:
def __init__(self, controller):
self.controller = controller
self.tornado = Webserver(controller, self)
2020-08-12 00:36:09 +00:00
self.webserver_thread = threading.Thread(target=self.tornado.run_tornado, daemon=True, name='tornado_thread')
self.main_kill_switch_thread = threading.Thread(target=self.main_kill_switch, daemon=True, name="main_loop")
self.main_thread_exiting = False
self.schedule_thread = threading.Thread(target=self.scheduler_thread, daemon=True, name="scheduler")
self.log_watcher_thread = threading.Thread(target=self.log_watcher, daemon=True, name="log_watcher")
self.command_thread = threading.Thread(target=self.command_watcher, daemon=True, name="command_watcher")
self.realtime_thread = threading.Thread(target=self.realtime, daemon=True, name="realtime")
self.reload_schedule_from_db()
2020-08-12 00:36:09 +00:00
def get_main_thread_run_status(self):
return self.main_thread_exiting
def start_main_kill_switch_watcher(self):
self.main_kill_switch_thread.start()
def main_kill_switch(self):
while True:
if os.path.exists(os.path.join(helper.root_dir, 'exit.txt')):
logger.info("Found Exit File, stopping everything")
self._main_graceful_exit()
time.sleep(5)
def reload_schedule_from_db(self):
jobs = db_helper.get_schedules_enabled()
schedule.clear(tag='backup')
schedule.clear(tag='db')
for j in jobs:
if j.interval_type in scheduler_intervals:
logger.info("Loading schedule ID#{i}: '{a}' every {n} {t} at {s}".format(
i=j.schedule_id, a=j.action, n=j.interval, t=j.interval_type, s=j.start_time))
try:
getattr(schedule.every(j.interval), j.interval_type).at(j.start_time).do(
db_helper.send_command, 0, j.server_id, "127.27.23.89", j.action)
except schedule.ScheduleValueError as e:
logger.critical("Scheduler value error occurred: {} on ID#{}".format(e, j.schedule_id))
else:
logger.critical("Unknown schedule job type '{}' at id {}, skipping".format(j.interval_type, j.schedule_id))
def command_watcher(self):
while True:
# select any commands waiting to be processed
commands = db_helper.get_unactioned_commands()
for c in commands:
svr = self.controller.get_server_obj(c['server_id']['server_id'])
command = c.get('command', None)
if command == 'start_server':
svr.run_threaded_server()
elif command == 'stop_server':
svr.stop_threaded_server()
elif command == "restart_server":
svr.restart_threaded_server()
elif command == "backup_server":
svr.backup_server()
db_helper.mark_command_complete(c.get('command_id', None))
time.sleep(1)
2020-08-12 00:36:09 +00:00
def _main_graceful_exit(self):
try:
os.remove(helper.session_file)
os.remove(os.path.join(helper.root_dir, 'exit.txt'))
os.remove(os.path.join(helper.root_dir, '.header'))
self.controller.stop_all_servers()
except:
logger.info("Caught error during shutdown", exc_info=True)
logger.info("***** Crafty Shutting Down *****\n\n")
console.info("***** Crafty Shutting Down *****\n\n")
2020-08-12 00:36:09 +00:00
self.main_thread_exiting = True
def start_webserver(self):
self.webserver_thread.start()
def reload_webserver(self):
self.tornado.stop_web_server()
console.info("Waiting 3 seconds")
time.sleep(3)
self.webserver_thread = threading.Thread(target=self.tornado.run_tornado, daemon=True, name='tornado_thread')
self.start_webserver()
def stop_webserver(self):
self.tornado.stop_web_server()
def start_scheduler(self):
logger.info("Launching Scheduler Thread...")
console.info("Launching Scheduler Thread...")
self.schedule_thread.start()
logger.info("Launching command thread...")
console.info("Launching command thread...")
self.command_thread.start()
logger.info("Launching log watcher...")
console.info("Launching log watcher...")
self.log_watcher_thread.start()
logger.info("Launching realtime thread...")
console.info("Launching realtime thread...")
self.realtime_thread.start()
@staticmethod
def scheduler_thread():
while True:
schedule.run_pending()
time.sleep(1)
2020-08-12 00:36:09 +00:00
def start_stats_recording(self):
stats_update_frequency = helper.get_setting('stats_update_frequency')
logger.info("Stats collection frequency set to {stats} seconds".format(stats=stats_update_frequency))
console.info("Stats collection frequency set to {stats} seconds".format(stats=stats_update_frequency))
2020-08-24 23:16:33 +00:00
# one for now,
self.controller.stats.record_stats()
# one for later
schedule.every(stats_update_frequency).seconds.do(self.controller.stats.record_stats).tag('stats-recording')
2020-08-12 00:36:09 +00:00
2020-08-23 22:43:28 +00:00
@staticmethod
def serverjar_cache_refresher():
logger.info("Refreshing serverjars.com cache on start")
server_jar_obj.refresh_cache()
logger.info("Scheduling Serverjars.com cache refresh service every 12 hours")
schedule.every(12).hours.do(server_jar_obj.refresh_cache).tag('serverjars')
2020-08-23 22:43:28 +00:00
@staticmethod
def realtime():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
host_stats = db_helper.get_latest_hosts_stats()
while True:
if host_stats.get('cpu_usage') != \
db_helper.get_latest_hosts_stats().get('cpu_usage') or \
host_stats.get('mem_percent') != \
db_helper.get_latest_hosts_stats().get('mem_percent'):
# Stats are different
host_stats = db_helper.get_latest_hosts_stats()
if len(websocket_helper.clients) > 0:
# There are clients
websocket_helper.broadcast('update_host_stats', {
'cpu_usage': host_stats.get('cpu_usage'),
'cpu_cores': host_stats.get('cpu_cores'),
'cpu_cur_freq': host_stats.get('cpu_cur_freq'),
'cpu_max_freq': host_stats.get('cpu_max_freq'),
'mem_percent': host_stats.get('mem_percent'),
'mem_usage': host_stats.get('mem_usage')
})
time.sleep(4)
else:
# Stats are same
time.sleep(8)
2021-03-05 09:35:05 +00:00
2021-03-05 09:30:18 +00:00
def log_watcher(self):
console.debug('in log_watcher')
helper.check_for_old_logs(db_helper)
schedule.every(6).hours.do(lambda: helper.check_for_old_logs(db_helper)).tag('log-mgmt')