mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add server download status indicator
This commit is contained in:
parent
6bc5e5b51f
commit
d73316119b
@ -50,6 +50,18 @@ class Servers_Controller:
|
|||||||
def update_server(server_obj):
|
def update_server(server_obj):
|
||||||
return servers_helper.update_server(server_obj)
|
return servers_helper.update_server(server_obj)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_download(server_id):
|
||||||
|
return servers_helper.set_download(server_id)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def finish_download(server_id):
|
||||||
|
return servers_helper.finish_download(server_id)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_download_status(server_id):
|
||||||
|
return servers_helper.get_download_status(server_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_server(server_id):
|
def remove_server(server_id):
|
||||||
roles_list = server_permissions.get_roles_from_server(server_id)
|
roles_list = server_permissions.get_roles_from_server(server_id)
|
||||||
|
@ -8,6 +8,9 @@ from datetime import datetime
|
|||||||
|
|
||||||
from app.classes.shared.helpers import helper
|
from app.classes.shared.helpers import helper
|
||||||
from app.classes.shared.console import console
|
from app.classes.shared.console import console
|
||||||
|
from app.classes.controllers.servers_controller import Servers_Controller
|
||||||
|
from app.classes.web.websocket_helper import websocket_helper
|
||||||
|
from app.classes.models.server_permissions import server_permissions
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -170,23 +173,53 @@ class ServerJars:
|
|||||||
response = self._get_api_result(url)
|
response = self._get_api_result(url)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def download_jar(self, server, version, path):
|
def download_jar(self, server, version, path, server_id):
|
||||||
update_thread = threading.Thread(target=self.a_download_jar, daemon=True, args=(server, version, path))
|
update_thread = threading.Thread(target=self.a_download_jar, daemon=True, args=(server, version, path, server_id))
|
||||||
update_thread.start()
|
update_thread.start()
|
||||||
|
|
||||||
def a_download_jar(self, server, version, path):
|
def a_download_jar(self, server, version, path, server_id):
|
||||||
|
#delaying download for server register to finish
|
||||||
|
time.sleep(3)
|
||||||
fetch_url = f"{self.base_url}/api/fetchJar/{server}/{version}"
|
fetch_url = f"{self.base_url}/api/fetchJar/{server}/{version}"
|
||||||
|
server_users = server_permissions.get_server_user_list(server_id)
|
||||||
|
|
||||||
|
|
||||||
|
#We need to make sure the server is registered before we submit a db update for it's stats.
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
Servers_Controller.set_download(server_id)
|
||||||
|
for user in server_users:
|
||||||
|
websocket_helper.broadcast_user(user, 'send_start_reload', {
|
||||||
|
})
|
||||||
|
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
logger.debug("server not registered yet. Delaying download.")
|
||||||
|
|
||||||
# open a file stream
|
# open a file stream
|
||||||
with requests.get(fetch_url, timeout=2, stream=True) as r:
|
with requests.get(fetch_url, timeout=2, stream=True) as r:
|
||||||
try:
|
try:
|
||||||
with open(path, 'wb') as output:
|
with open(path, 'wb') as output:
|
||||||
shutil.copyfileobj(r.raw, output)
|
shutil.copyfileobj(r.raw, output)
|
||||||
|
Servers_Controller.finish_download(server_id)
|
||||||
|
|
||||||
|
for user in server_users:
|
||||||
|
websocket_helper.broadcast_user(user, 'notification', "Executable download finished")
|
||||||
|
time.sleep(3)
|
||||||
|
websocket_helper.broadcast_user(user, 'send_start_reload', {
|
||||||
|
})
|
||||||
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Unable to save jar to {path} due to error:{e}")
|
logger.error(f"Unable to save jar to {path} due to error:{e}")
|
||||||
|
Servers_Controller.finish_download(server_id)
|
||||||
|
server_users = server_permissions.get_server_user_list(server_id)
|
||||||
|
for user in server_users:
|
||||||
|
websocket_helper.broadcast_user(user, 'notification', "Executable download finished")
|
||||||
|
time.sleep(3)
|
||||||
|
websocket_helper.broadcast_user(user, 'send_start_reload', {
|
||||||
|
})
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
server_jar_obj = ServerJars()
|
server_jar_obj = ServerJars()
|
||||||
|
@ -75,6 +75,7 @@ class Server_Stats(Model):
|
|||||||
waiting_start = BooleanField(default=False)
|
waiting_start = BooleanField(default=False)
|
||||||
first_run = BooleanField(default=True)
|
first_run = BooleanField(default=True)
|
||||||
crashed = BooleanField(default=False)
|
crashed = BooleanField(default=False)
|
||||||
|
downloading = BooleanField(default=False)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -194,6 +195,22 @@ class helper_servers:
|
|||||||
with database.atomic():
|
with database.atomic():
|
||||||
Server_Stats.update(crashed=True).where(Server_Stats.server_id == server_id).execute()
|
Server_Stats.update(crashed=True).where(Server_Stats.server_id == server_id).execute()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_download(server_id):
|
||||||
|
with database.atomic():
|
||||||
|
Server_Stats.update(downloading=True).where(Server_Stats.server_id == server_id).execute()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def finish_download(server_id):
|
||||||
|
with database.atomic():
|
||||||
|
Server_Stats.update(downloading=False).where(Server_Stats.server_id == server_id).execute()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_download_status(server_id):
|
||||||
|
download_status = Server_Stats.select().where(Server_Stats.server_id == server_id).get()
|
||||||
|
return download_status.downloading
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def server_crash_reset(server_id):
|
def server_crash_reset(server_id):
|
||||||
with database.atomic():
|
with database.atomic():
|
||||||
|
@ -292,11 +292,12 @@ class Controller:
|
|||||||
server_log_file = f"{server_dir}/logs/latest.log"
|
server_log_file = f"{server_dir}/logs/latest.log"
|
||||||
server_stop = "stop"
|
server_stop = "stop"
|
||||||
|
|
||||||
# download the jar
|
|
||||||
server_jar_obj.download_jar(server, version, full_jar_path)
|
|
||||||
|
|
||||||
new_id = self.register_server(name, server_id, server_dir, backup_path, server_command, server_file, server_log_file, server_stop,
|
new_id = self.register_server(name, server_id, server_dir, backup_path, server_command, server_file, server_log_file, server_stop,
|
||||||
port, server_type='minecraft-java')
|
port, server_type='minecraft-java')
|
||||||
|
|
||||||
|
# download the jar
|
||||||
|
server_jar_obj.download_jar(server, version, full_jar_path, new_id)
|
||||||
|
|
||||||
return new_id
|
return new_id
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -188,6 +188,13 @@ class Server:
|
|||||||
else:
|
else:
|
||||||
user_lang = users_helper.get_user_lang_by_id(user_id)
|
user_lang = users_helper.get_user_lang_by_id(user_id)
|
||||||
|
|
||||||
|
if servers_helper.get_download_status(self.server_id):
|
||||||
|
if user_id:
|
||||||
|
websocket_helper.broadcast_user(user_id, 'send_start_error',{
|
||||||
|
'error': translation.translate('error', 'not-downloaded', user_lang)
|
||||||
|
})
|
||||||
|
return False
|
||||||
|
|
||||||
logger.info(f"Start command detected. Reloading settings from DB for server {self.name}")
|
logger.info(f"Start command detected. Reloading settings from DB for server {self.name}")
|
||||||
self.setup_server_run_command()
|
self.setup_server_run_command()
|
||||||
# fail safe in case we try to start something already running
|
# fail safe in case we try to start something already running
|
||||||
|
@ -150,7 +150,7 @@ class PanelHandler(BaseHandler):
|
|||||||
else:
|
else:
|
||||||
if not self.controller.servers.server_id_authorized(server_id, exec_user["user_id"]):
|
if not self.controller.servers.server_id_authorized(server_id, exec_user["user_id"]):
|
||||||
print(f'User {exec_user["user_id"]} does not have permission')
|
print(f'User {exec_user["user_id"]} does not have permission')
|
||||||
self.redirect("/panel/error?error=Invalid Server ID")
|
self.redirect("/pandel/error?error=Invalid Server ID")
|
||||||
return None
|
return None
|
||||||
return server_id
|
return server_id
|
||||||
|
|
||||||
@ -209,14 +209,17 @@ class PanelHandler(BaseHandler):
|
|||||||
user_order = user_order['server_order'].split(',')
|
user_order = user_order['server_order'].split(',')
|
||||||
page_servers = []
|
page_servers = []
|
||||||
server_ids = []
|
server_ids = []
|
||||||
|
un_used_servers = defined_servers
|
||||||
|
|
||||||
for server_id in user_order:
|
for server_id in user_order:
|
||||||
for server in defined_servers:
|
for server in un_used_servers:
|
||||||
if str(server['server_id']) == str(server_id):
|
if str(server['server_id']) == str(server_id):
|
||||||
page_servers.append(server)
|
page_servers.append(server)
|
||||||
|
un_used_servers.remove(server)
|
||||||
|
user_order.remove(server_id)
|
||||||
|
|
||||||
|
|
||||||
for server in defined_servers:
|
for server in un_used_servers:
|
||||||
server_ids.append(str(server['server_id']))
|
server_ids.append(str(server['server_id']))
|
||||||
if server not in page_servers:
|
if server not in page_servers:
|
||||||
page_servers.append(server)
|
page_servers.append(server)
|
||||||
@ -335,14 +338,33 @@ class PanelHandler(BaseHandler):
|
|||||||
user_order = user_order['server_order'].split(',')
|
user_order = user_order['server_order'].split(',')
|
||||||
page_servers = []
|
page_servers = []
|
||||||
server_ids = []
|
server_ids = []
|
||||||
|
un_used_servers = page_data['servers']
|
||||||
|
flag = 0
|
||||||
|
|
||||||
for server_id in user_order:
|
for server_id in user_order:
|
||||||
for server in page_data['servers']:
|
for server in un_used_servers:
|
||||||
|
if flag == 0:
|
||||||
|
server['stats']['downloading'] = self.controller.servers.get_download_status(
|
||||||
|
str(server['stats']['server_id']['server_id']))
|
||||||
|
server['stats']['crashed'] = self.controller.servers.is_crashed(
|
||||||
|
str(server['stats']['server_id']['server_id']))
|
||||||
|
try:
|
||||||
|
server['stats']['waiting_start'] = self.controller.servers.get_waiting_start(
|
||||||
|
str(server['stats']['server_id']['server_id']))
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to get server waiting to start: {e}")
|
||||||
|
server['stats']['waiting_start'] = False
|
||||||
|
|
||||||
if str(server['server_data']['server_id']) == str(server_id):
|
if str(server['server_data']['server_id']) == str(server_id):
|
||||||
page_servers.append(server)
|
page_servers.append(server)
|
||||||
|
un_used_servers.remove(server)
|
||||||
|
user_order.remove(server_id)
|
||||||
|
#we only want to set these server stats values once. We need to update the flag so it only hits that if once.
|
||||||
|
flag += 1
|
||||||
|
|
||||||
|
|
||||||
for server in page_data['servers']:
|
|
||||||
|
for server in un_used_servers:
|
||||||
server_ids.append(str(server['server_data']['server_id']))
|
server_ids.append(str(server['server_data']['server_id']))
|
||||||
if server not in page_servers:
|
if server not in page_servers:
|
||||||
page_servers.append(server)
|
page_servers.append(server)
|
||||||
@ -352,17 +374,6 @@ class PanelHandler(BaseHandler):
|
|||||||
user_order.remove(server_id)
|
user_order.remove(server_id)
|
||||||
page_data['servers'] = page_servers
|
page_data['servers'] = page_servers
|
||||||
|
|
||||||
|
|
||||||
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:
|
try:
|
||||||
self.fetch_server_data(page_data)
|
self.fetch_server_data(page_data)
|
||||||
except:
|
except:
|
||||||
@ -390,6 +401,8 @@ class PanelHandler(BaseHandler):
|
|||||||
# server_data isn't needed since the server_stats also pulls server data
|
# server_data isn't needed since the server_stats also pulls server data
|
||||||
page_data['server_data'] = self.controller.servers.get_server_data_by_id(server_id)
|
page_data['server_data'] = self.controller.servers.get_server_data_by_id(server_id)
|
||||||
page_data['server_stats'] = self.controller.servers.get_server_stats_by_id(server_id)
|
page_data['server_stats'] = self.controller.servers.get_server_stats_by_id(server_id)
|
||||||
|
page_data['downloading'] = self.controller.servers.get_download_status(
|
||||||
|
server_id)
|
||||||
try:
|
try:
|
||||||
page_data['waiting_start'] = self.controller.servers.get_waiting_start(server_id)
|
page_data['waiting_start'] = self.controller.servers.get_waiting_start(server_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -158,6 +158,9 @@
|
|||||||
<a data-id="{{server['server_data']['server_id']}}" class="" title={{
|
<a data-id="{{server['server_data']['server_id']}}" class="" title={{
|
||||||
translate('dashboard', 'delay-explained' , data['lang'])}}>{{ translate('dashboard', 'starting',
|
translate('dashboard', 'delay-explained' , data['lang'])}}>{{ translate('dashboard', 'starting',
|
||||||
data['lang']) }}</i></a>
|
data['lang']) }}</i></a>
|
||||||
|
{% elif server['stats']['downloading']%}
|
||||||
|
<a data-id="{{server['server_data']['server_id']}}" class=""><i class="fa fa-spinner fa-spin"></i> {{ translate('serverTerm', 'downloading',
|
||||||
|
data['lang']) }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a data-id="{{server['server_data']['server_id']}}" class="play_button"
|
<a data-id="{{server['server_data']['server_id']}}" class="play_button"
|
||||||
data-toggle="tooltip" title="{{ translate('dashboard', 'start' , data['lang']) }}">
|
data-toggle="tooltip" title="{{ translate('dashboard', 'start' , data['lang']) }}">
|
||||||
|
@ -59,6 +59,13 @@
|
|||||||
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
|
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
|
||||||
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
|
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
{% elif data['downloading'] %}
|
||||||
|
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
|
||||||
|
<button onclick="" id="start-btn" style="max-width: 12rem; white-space: nowrap;" class="btn btn-secondary m-1 flex-grow-1 disabled"><i class="fa fa-spinner fa-spin"></i> {{ translate('serverTerm', 'downloading',
|
||||||
|
data['lang']) }}</button>
|
||||||
|
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
|
||||||
|
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
|
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
|
||||||
<button onclick="send_command(serverId, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start', data['lang']) }}</button>
|
<button onclick="send_command(serverId, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start', data['lang']) }}</button>
|
||||||
@ -153,6 +160,12 @@
|
|||||||
restartBtn.setAttribute('disabled', 'disabled');
|
restartBtn.setAttribute('disabled', 'disabled');
|
||||||
stopBtn.setAttribute('disabled', 'disabled');
|
stopBtn.setAttribute('disabled', 'disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (webSocket) {
|
||||||
|
webSocket.on('send_start_reload', function () {
|
||||||
|
location.reload()
|
||||||
|
});
|
||||||
|
}
|
||||||
//{% end %}
|
//{% end %}
|
||||||
|
|
||||||
function get_server_log() {
|
function get_server_log() {
|
||||||
|
16
app/migrations/20220303_downloading.py
Normal file
16
app/migrations/20220303_downloading.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Generated by database migrator
|
||||||
|
import peewee
|
||||||
|
|
||||||
|
def migrate(migrator, database, **kwargs):
|
||||||
|
migrator.add_columns('server_stats', downloading=peewee.BooleanField(default=False))
|
||||||
|
"""
|
||||||
|
Write your migrations here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def rollback(migrator, database, **kwargs):
|
||||||
|
migrator.drop_columns('server_stats', ['downloading'])
|
||||||
|
"""
|
||||||
|
Write your rollback migrations here.
|
||||||
|
"""
|
@ -165,7 +165,8 @@
|
|||||||
"stop": "Stop",
|
"stop": "Stop",
|
||||||
"updating": "Updating...",
|
"updating": "Updating...",
|
||||||
"starting": "Delayed-Start",
|
"starting": "Delayed-Start",
|
||||||
"delay-explained": "The service/agent has recently started and is delaying the start of the minecraft server instance"
|
"delay-explained": "The service/agent has recently started and is delaying the start of the minecraft server instance",
|
||||||
|
"downloading": "Downloading..."
|
||||||
},
|
},
|
||||||
"serverPlayerManagement": {
|
"serverPlayerManagement": {
|
||||||
"players": "Players",
|
"players": "Players",
|
||||||
|
Loading…
Reference in New Issue
Block a user