Merge branch 'pretzel-fixes' into 'dev'

Pretzel fixes

See merge request crafty-controller/crafty-commander!151
This commit is contained in:
Andrew 2022-01-28 02:25:59 +00:00
commit 8a5a7cb13f
10 changed files with 97 additions and 29 deletions

View File

@ -146,6 +146,10 @@ class Servers_Controller:
return True
return False
@staticmethod
def is_crashed(server_id):
return servers_helper.is_crashed(server_id)
@staticmethod
def server_id_authorized_api_key(server_id: str, api_key: ApiKeys) -> bool:
# TODO

View File

@ -260,6 +260,8 @@ class Stats:
server_stats = {}
server = self.controller.get_server_obj(server_id)
server_dt = servers_helper.get_server_data_by_id(server_id)
logger.debug(f'Getting stats for server: {server_id}')
@ -279,8 +281,8 @@ class Stats:
# TODO: search server properties file for possible override of 127.0.0.1
#internal_ip = server['server_ip']
#server_port = server['server_port']
internal_ip = server_data.get('server_ip', "127.0.0.1")
server_port = server_settings.get('server-port', "25565")
internal_ip = server_dt['server_ip']
server_port = server_dt['server_port']
logger.debug(f"Pinging server '{server.name}' on {internal_ip}:{server_port}")

View File

@ -73,6 +73,7 @@ class Server_Stats(Model):
updating = BooleanField(default=False)
waiting_start = BooleanField(default=False)
first_run = BooleanField(default=True)
crashed = BooleanField(default=False)
class Meta:
@ -178,6 +179,25 @@ class helper_servers:
return False
return True
@staticmethod
def sever_crashed(server_id):
with database.atomic():
Server_Stats.update(crashed=True).where(Server_Stats.server_id == server_id).execute()
@staticmethod
def server_crash_reset(server_id):
with database.atomic():
Server_Stats.update(crashed=False).where(Server_Stats.server_id == server_id).execute()
@staticmethod
def is_crashed(server_id):
svr = Server_Stats.select().where(Server_Stats.server_id == server_id).get()
#pylint: disable=singleton-comparison
if svr.crashed == True:
return True
else:
return False
@staticmethod
def set_update(server_id, value):
try:
@ -190,8 +210,8 @@ class helper_servers:
@staticmethod
def get_update_status(server_id):
waiting_start = Server_Stats.select().where(Server_Stats.server_id == server_id).get()
return waiting_start.waiting_start
update_status = Server_Stats.select().where(Server_Stats.server_id == server_id).get()
return update_status.updating
@staticmethod
def set_first_run(server_id):

View File

@ -115,8 +115,12 @@ class Server:
self.stats = stats
tz = get_localzone()
self.server_scheduler = BackgroundScheduler(timezone=str(tz))
self.server_scheduler.start()
self.backup_thread = threading.Thread(target=self.a_backup_server, daemon=True, name=f"backup_{self.name}")
self.is_backingup = False
#Reset crash and update at initialization
servers_helper.server_crash_reset(self.server_id)
servers_helper.set_update(self.server_id, False)
def reload_server_settings(self):
server_data = servers_helper.get_server_data_by_id(self.server_id)
@ -141,7 +145,6 @@ class Server:
console.info(f"Scheduling server {self.name} to start in {delay} seconds")
self.server_scheduler.add_job(self.run_scheduled_server, 'interval', seconds=delay, id=str(self.server_id))
self.server_scheduler.start()
def run_scheduled_server(self):
console.info(f"Starting server ID: {self.server_id} - {self.name}")
@ -262,6 +265,7 @@ class Server:
threading.Thread(target=out_buf.check, daemon=True, name=f'{self.server_id}_virtual_terminal').start()
self.is_crashed = False
servers_helper.server_crash_reset(self.server_id)
self.start_time = str(datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'))
@ -269,6 +273,7 @@ class Server:
logger.info(f"Server {self.name} running with PID {self.process.pid}")
console.info(f"Server {self.name} running with PID {self.process.pid}")
self.is_crashed = False
servers_helper.server_crash_reset(self.server_id)
self.stats.record_stats()
check_internet_thread = threading.Thread(
target=self.check_internet_thread, daemon=True, args=(user_id, user_lang, ), name=f"{self.name}_Internet")
@ -299,7 +304,7 @@ class Server:
logger.info(f"Server {self.name} has crash detection enabled - starting watcher task")
console.info(f"Server {self.name} has crash detection enabled - starting watcher task")
self.server_scheduler.add_job(self.detect_crash, 'interval', seconds=30, id="c_{self.server_id}")
self.server_scheduler.add_job(self.detect_crash, 'interval', seconds=30, id=f"c_{self.server_id}")
def check_internet_thread(self, user_id, user_lang):
if user_id:
@ -317,6 +322,9 @@ class Server:
def stop_server(self):
if self.settings['stop_command']:
self.send_command(self.settings['stop_command'])
#remove crash detection watcher
logger.info(f"Removing crash watcher for server {self.name}")
self.server_scheduler.remove_job('c_' + str(self.server_id))
else:
#windows will need to be handled separately for Ctrl+C
self.process.terminate()
@ -398,8 +406,9 @@ class Server:
def crash_detected(self, name):
print("crash detected")
# clear the old scheduled watcher task
self.remove_watcher_thread()
self.server_scheduler.remove_job("c_"+str(self.server_id))
# the server crashed, or isn't found - so let's reset things.
logger.warning(f"The server {name} seems to have vanished unexpectedly, did it crash?")
@ -449,6 +458,7 @@ class Server:
if running:
return
servers_helper.sever_crashed(self.server_id)
# if we haven't tried to restart more 3 or more times
if self.restart_count <= 3:
@ -464,12 +474,12 @@ class Server:
logger.critical(f"Server {self.name} has been restarted {self.restart_count} times. It has crashed, not restarting.")
console.critical(f"Server {self.name} has been restarted {self.restart_count} times. It has crashed, not restarting.")
# set to 99 restart attempts so this elif is skipped next time. (no double logging)
self.restart_count = 99
self.restart_count = 0
self.is_crashed = True
servers_helper.sever_crashed(self.server_id)
# cancel the watcher task
self.remove_watcher_thread()
self.server_scheduler.remove_job("c_"+str(self.server_id))
def remove_watcher_thread(self):
logger.info("Removing old crash detection watcher thread")

View File

@ -16,6 +16,7 @@ from app.classes.minecraft.serverjars import server_jar_obj
from app.classes.models.management import management_helper
from app.classes.controllers.users_controller import Users_Controller
from app.classes.controllers.servers_controller import Servers_Controller
from app.classes.models.servers import servers_helper
logger = logging.getLogger('apscheduler')
@ -425,7 +426,10 @@ class TasksManager:
})
for user in Users_Controller.get_all_users():
total_players = 0
max_players = 0
servers_ping = []
players_ping = {}
if user.superuser:
servers = Servers_Controller.get_all_servers_stats()
else:
@ -434,8 +438,6 @@ class TasksManager:
if srv:
server_id = srv['server_data']['server_id']
srv['raw_ping_result'] = self.controller.stats.get_raw_server_stats(server_id)
if f"{srv['raw_ping_result'].get('icon')}" == "b''":
srv['raw_ping_result']['icon'] = False
servers_ping.append({
'id': srv['raw_ping_result'].get('id'),
@ -453,7 +455,7 @@ class TasksManager:
'players': srv['raw_ping_result'].get('players'),
'desc': srv['raw_ping_result'].get('desc'),
'version': srv['raw_ping_result'].get('version'),
'icon': None
'crashed': servers_helper.is_crashed(server_id),
})
if len(websocket_helper.clients) > 0:
websocket_helper.broadcast_user_page_params(
@ -478,9 +480,16 @@ class TasksManager:
'players': srv['raw_ping_result'].get('players'),
'desc': srv['raw_ping_result'].get('desc'),
'version': srv['raw_ping_result'].get('version'),
'icon': None
'crashed': servers_helper.is_crashed(server_id),
}
)
total_players += int(srv['raw_ping_result'].get('online'))
max_players += int(srv['raw_ping_result'].get('max'))
players_ping = {
'total_players': total_players,
'max_players': max_players
}
websocket_helper.broadcast_user_page('/panel/dashboard', user.user_id, 'update_player_status', players_ping)
if (len(servers_ping) > 0) & (len(websocket_helper.clients) > 0):
try:

View File

@ -295,13 +295,15 @@ class PanelHandler(BaseHandler):
list(filter(lambda x: x['stats']['running'], page_data['servers'])))
page_data['server_stats']['stopped'] = len(page_data['servers']) - page_data['server_stats']['running']
for data in page_data['servers']:
try:
data['stats']['waiting_start'] = self.controller.servers.get_waiting_start(
str(data['stats']['server_id']['server_id']))
except Exception as e:
logger.error(f"Failed to get server waiting to start: {e}")
data['stats']['waiting_start'] = False
for data in page_data['servers']:
data['stats']['crashed'] = self.controller.servers.is_crashed(
str(data['stats']['server_id']['server_id']))
try:
data['stats']['waiting_start'] = self.controller.servers.get_waiting_start(
str(data['stats']['server_id']['server_id']))
except Exception as e:
logger.error(f"Failed to get server waiting to start: {e}")
data['stats']['waiting_start'] = False
try:
self.fetch_server_data(page_data)
@ -348,6 +350,7 @@ class PanelHandler(BaseHandler):
'Players': Enum_Permissions_Server.Players,
}
page_data['user_permissions'] = self.controller.server_perms.get_user_id_permissions_list(exec_user["user_id"], server_id)
page_data['server_stats']['crashed'] = self.controller.servers.is_crashed(server_id)
if subpage == 'term':
if not page_data['permissions']['Terminal'] in page_data['user_permissions']:

View File

@ -68,12 +68,11 @@
<div class="wrapper">
<h5 class="mb-1 font-weight-medium text-primary">{{ translate('dashboard', 'players', data['lang']) }}
</h5>
<h3 class="mb-0 font-weight-semibold">{{ data['num_players'] }}</h3>
<h3 class="mb-0 font-weight-semibold" id="total_players">{{ data['num_players'] }}</h3>
</div>
<div class="wrapper my-auto ml-auto ml-lg-4">
<p class="mb-0 text-success">35 {{ translate('dashboard', 'max', data['lang']) }}</p>
<p class="mb-0 text-warning">10 {{ translate('dashboard', 'avg', data['lang']) }}</p>
<p class="mb-0 text-warning"><span id="max_players">0</span> {{ translate('dashboard', 'max', data['lang']) }}</p>
</div>
</div>
</div>
@ -224,7 +223,7 @@
<span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online',
data['lang']) }}</span>
{% else %}
<span class="text-danger"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline',
<span class="text-warning"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline',
data['lang']) }}</span>
{% end %}
</td>
@ -412,7 +411,7 @@
online_status = `<span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online', data['lang'])}}</span>`;
}
else {
online_status = `<span class="text-danger"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline', data['lang'])}}</span>`;
online_status = `<span class="text-warning"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline', data['lang'])}}</span>`;
}
server_online_status.innerHTML = online_status;
}
@ -494,6 +493,8 @@
cpu_usage = document.getElementById('cpu_usage');
mem_usage = document.getElementById('mem_usage');
mem_percent = document.getElementById('mem_percent');
total_players = document.getElementById('total_players');
max_players = document.getElementById('max_players');
webSocket.on('update_host_stats', function (hostStats) {
var cpuDataTitle = `{% raw translate('dashboard', 'cpuCores', data['lang']) %}: ${hostStats.cpu_cores} <br /> {% raw translate("dashboard", "cpuCurFreq", data['lang']) %}: ${hostStats.cpu_cur_freq} <br /> {% raw translate("dashboard", "cpuMaxFreq", data['lang']) %}: ${hostStats.cpu_max_freq}`;
@ -502,6 +503,10 @@
mem_usage.setAttribute('data-original-title', `{% raw translate("dashboard", "memUsage", data['lang']) %}: ${hostStats.mem_usage}`);
mem_percent.textContent = hostStats.mem_percent + '%';
});
webSocket.on('update_player_status', function (playerStats) {
total_players.innerHTML = playerStats.total_players;
max_players.innerHTML = playerStats.max_players;
});
}
if (webSocket) {

View File

@ -146,12 +146,10 @@
for (server of data) {
update_one_server_status(server);
}
display_motd();
}
$(document).ready(function () {
console.log("ready!");
display_motd()
if (webSocket)
{

View File

@ -0,0 +1,16 @@
# Generated by database migrator
import peewee
def migrate(migrator, database, **kwargs):
migrator.add_columns('server_stats', crashed=peewee.BooleanField(default=False))
"""
Write your migrations here.
"""
def rollback(migrator, database, **kwargs):
migrator.drop_columns('server_stats', ['crashed'])
"""
Write your rollback migrations here.
"""

View File

@ -118,7 +118,8 @@
"starting": "Delayed-Start",
"delay-explained": "The service/agent has recently started and is delaying the start of the minecraft server instance",
"no-servers": "There are currently no servers. To get started, click",
"welcome": "Welcome to Crafty Controller"
"welcome": "Welcome to Crafty Controller",
"crashed": "Crashed"
},
"accessDenied": {
"accessDenied": "Access Denied",