mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'pretzel-fixes' into 'dev'
Pretzel fixes See merge request crafty-controller/crafty-commander!151
This commit is contained in:
commit
8a5a7cb13f
@ -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
|
||||
|
@ -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}")
|
||||
|
@ -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):
|
||||
|
@ -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")
|
||||
|
@ -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:
|
||||
|
@ -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']:
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
16
app/migrations/20210915205501_crash.py
Normal file
16
app/migrations/20210915205501_crash.py
Normal 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.
|
||||
"""
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user