mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'enhancement/bedrock-update-support' into 'dev'
Fix executable backups for Bedrock See merge request crafty-controller/crafty-4!441
This commit is contained in:
commit
cf5e4f61bf
@ -5,6 +5,7 @@
|
||||
### Bug fixes
|
||||
- Fix performance issues on server metrics panels (Temporarily setting to 24hr query) ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/440))
|
||||
- Fix no id on import3 servers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/442))
|
||||
- Fix functionality of bedrock update ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/441))
|
||||
### Tweaks
|
||||
TBD
|
||||
### Lang
|
||||
|
@ -64,6 +64,11 @@ class FileHelpers:
|
||||
FileHelpers.copy_dir(src_path, dest_path)
|
||||
FileHelpers.del_dirs(src_path)
|
||||
|
||||
@staticmethod
|
||||
def move_dir_exist(src_path, dest_path):
|
||||
FileHelpers.copy_dir(src_path, dest_path, True)
|
||||
FileHelpers.del_dirs(src_path)
|
||||
|
||||
@staticmethod
|
||||
def move_file(src_path, dest_path):
|
||||
FileHelpers.copy_file(src_path, dest_path)
|
||||
@ -290,7 +295,7 @@ class FileHelpers:
|
||||
for item in os.listdir(full_root_path):
|
||||
if os.path.isdir(os.path.join(full_root_path, item)):
|
||||
try:
|
||||
FileHelpers.move_dir(
|
||||
FileHelpers.move_dir_exist(
|
||||
os.path.join(full_root_path, item),
|
||||
os.path.join(new_dir, item),
|
||||
)
|
||||
|
@ -107,6 +107,42 @@ class Helpers:
|
||||
logger.error(f"Unable to check for new crafty version! \n{e}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_latest_bedrock_url():
|
||||
"""
|
||||
Get latest bedrock executable url \n\n
|
||||
returns url if successful, False if not
|
||||
"""
|
||||
url = "https://minecraft.net/en-us/download/server/bedrock/"
|
||||
headers = {
|
||||
"Accept-Encoding": "identity",
|
||||
"Accept-Language": "en",
|
||||
"User-Agent": (
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/104.0.0.0 Safari/537.36"
|
||||
),
|
||||
}
|
||||
target_win = 'https://minecraft.azureedge.net/bin-win/[^"]*'
|
||||
target_linux = 'https://minecraft.azureedge.net/bin-linux/[^"]*'
|
||||
|
||||
try:
|
||||
# Get minecraft server download page
|
||||
# (hopefully the don't change the structure)
|
||||
download_page = get(url, headers=headers)
|
||||
|
||||
# Search for our string targets
|
||||
win_download_url = re.search(target_win, download_page.text).group(0)
|
||||
linux_download_url = re.search(target_linux, download_page.text).group(0)
|
||||
|
||||
if os.name == "nt":
|
||||
return win_download_url
|
||||
|
||||
return linux_download_url
|
||||
except Exception as e:
|
||||
logger.error(f"Unable to resolve remote bedrock download url! \n{e}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def find_java_installs():
|
||||
# If we're windows return oracle java versions,
|
||||
|
@ -9,6 +9,7 @@ import threading
|
||||
import logging.config
|
||||
import subprocess
|
||||
import html
|
||||
import urllib.request
|
||||
|
||||
# TZLocal is set as a hidden import on win pipeline
|
||||
from tzlocal import get_localzone
|
||||
@ -1078,20 +1079,21 @@ class ServerInstance:
|
||||
)
|
||||
# checks if backup directory already exists
|
||||
if os.path.isdir(backup_dir):
|
||||
backup_executable = os.path.join(backup_dir, "old_server.jar")
|
||||
backup_executable = os.path.join(backup_dir, self.settings["executable"])
|
||||
else:
|
||||
logger.info(
|
||||
f"Executable backup directory not found for Server: {self.name}."
|
||||
f" Creating one."
|
||||
)
|
||||
os.mkdir(backup_dir)
|
||||
backup_executable = os.path.join(backup_dir, "old_server.jar")
|
||||
backup_executable = os.path.join(backup_dir, self.settings["executable"])
|
||||
|
||||
if os.path.isfile(backup_executable):
|
||||
if len(os.listdir(backup_dir)) > 0:
|
||||
# removes old backup
|
||||
logger.info(f"Old backup found for server: {self.name}. Removing...")
|
||||
os.remove(backup_executable)
|
||||
logger.info(f"Old backup removed for server: {self.name}.")
|
||||
logger.info(f"Old backups found for server: {self.name}. Removing...")
|
||||
for item in os.listdir(backup_dir):
|
||||
os.remove(os.path.join(backup_dir, item))
|
||||
logger.info(f"Old backups removed for server: {self.name}.")
|
||||
else:
|
||||
logger.info(f"No old backups found for server: {self.name}")
|
||||
|
||||
@ -1100,31 +1102,76 @@ class ServerInstance:
|
||||
self.settings["executable"],
|
||||
)
|
||||
|
||||
try:
|
||||
# copies to backup dir
|
||||
FileHelpers.copy_file(current_executable, backup_executable)
|
||||
except FileNotFoundError:
|
||||
logger.error("Could not create backup of jarfile. File not found.")
|
||||
|
||||
# wait for backup
|
||||
while self.is_backingup:
|
||||
time.sleep(10)
|
||||
|
||||
# check if backup was successful
|
||||
if self.last_backup_failed:
|
||||
server_users = PermissionsServers.get_server_user_list(self.server_id)
|
||||
for user in server_users:
|
||||
self.helper.websocket_helper.broadcast_user(
|
||||
user,
|
||||
"notification",
|
||||
"Backup failed for " + self.name + ". canceling update.",
|
||||
)
|
||||
return False
|
||||
|
||||
# lets download the files
|
||||
if HelperServers.get_server_type_by_id(self.server_id) != "minecraft-bedrock":
|
||||
# boolean returns true for false for success
|
||||
downloaded = Helpers.download_file(
|
||||
self.settings["executable_update_url"], current_executable
|
||||
)
|
||||
else:
|
||||
# downloads zip from remote url
|
||||
try:
|
||||
bedrock_url = Helpers.get_latest_bedrock_url()
|
||||
if bedrock_url.lower().startswith("https"):
|
||||
urllib.request.urlretrieve(
|
||||
bedrock_url,
|
||||
os.path.join(self.settings["path"], "bedrock_server.zip"),
|
||||
)
|
||||
|
||||
while self.stats_helper.get_server_stats()["updating"]:
|
||||
if downloaded and not self.is_backingup:
|
||||
unzip_path = os.path.join(self.settings["path"], "bedrock_server.zip")
|
||||
unzip_path = self.helper.wtol_path(unzip_path)
|
||||
# unzips archive that was downloaded.
|
||||
FileHelpers.unzip_file(unzip_path)
|
||||
# adjusts permissions for execution if os is not windows
|
||||
if not self.helper.is_os_windows():
|
||||
os.chmod(
|
||||
os.path.join(self.settings["path"], "bedrock_server"), 0o0744
|
||||
)
|
||||
|
||||
# we'll delete the zip we downloaded now
|
||||
os.remove(os.path.join(self.settings["path"], "bedrock_server.zip"))
|
||||
downloaded = True
|
||||
except Exception as e:
|
||||
logger.critical(
|
||||
f"Failed to download bedrock executable for update \n{e}"
|
||||
)
|
||||
|
||||
if downloaded:
|
||||
logger.info("Executable updated successfully. Starting Server")
|
||||
|
||||
self.stats_helper.set_update(False)
|
||||
if len(self.helper.websocket_helper.clients) > 0:
|
||||
# There are clients
|
||||
self.check_update()
|
||||
server_users = PermissionsServers.get_server_user_list(
|
||||
self.server_id
|
||||
)
|
||||
server_users = PermissionsServers.get_server_user_list(self.server_id)
|
||||
for user in server_users:
|
||||
self.helper.websocket_helper.broadcast_user(
|
||||
user,
|
||||
"notification",
|
||||
"Executable update finished for " + self.name,
|
||||
)
|
||||
# sleep so first notif can completely run
|
||||
time.sleep(3)
|
||||
self.helper.websocket_helper.broadcast_page(
|
||||
"/panel/server_detail",
|
||||
@ -1138,6 +1185,9 @@ class ServerInstance:
|
||||
self.helper.websocket_helper.broadcast_page(
|
||||
"/panel/dashboard", "send_start_reload", {}
|
||||
)
|
||||
self.helper.websocket_helper.broadcast_page(
|
||||
"/panel/server_detail", "remove_spinner", {}
|
||||
)
|
||||
server_users = PermissionsServers.get_server_user_list(self.server_id)
|
||||
for user in server_users:
|
||||
self.helper.websocket_helper.broadcast_user(
|
||||
@ -1155,8 +1205,7 @@ class ServerInstance:
|
||||
)
|
||||
if was_started:
|
||||
self.start_server()
|
||||
elif not downloaded and not self.is_backingup:
|
||||
time.sleep(5)
|
||||
else:
|
||||
server_users = PermissionsServers.get_server_user_list(self.server_id)
|
||||
for user in server_users:
|
||||
self.helper.websocket_helper.broadcast_user(
|
||||
|
@ -1500,7 +1500,8 @@ class PanelHandler(BaseHandler):
|
||||
if Helpers.is_os_windows():
|
||||
server_path.replace(" ", "^ ")
|
||||
server_path = Helpers.wtol_path(server_path)
|
||||
log_path = self.get_argument("log_path", None)
|
||||
log_path = self.get_argument("log_path", "")
|
||||
if log_path:
|
||||
if Helpers.is_os_windows():
|
||||
log_path.replace(" ", "^ ")
|
||||
log_path = Helpers.wtol_path(log_path)
|
||||
@ -1510,7 +1511,7 @@ class PanelHandler(BaseHandler):
|
||||
execution_command = self.get_argument("execution_command", None)
|
||||
server_ip = self.get_argument("server_ip", None)
|
||||
server_port = self.get_argument("server_port", None)
|
||||
executable_update_url = self.get_argument("executable_update_url", None)
|
||||
executable_update_url = self.get_argument("executable_update_url", "")
|
||||
show_status = int(float(self.get_argument("show_status", "0")))
|
||||
else:
|
||||
execution_command = server_obj.execution_command
|
||||
|
@ -186,7 +186,8 @@
|
||||
|
||||
{% elif server['stats']['updating']%}
|
||||
<!-- WHAT HAPPENED HERE -->
|
||||
<a data-id="{{server['server_data']['server_id']}}" class="">{{ translate('serverTerm', 'updating',
|
||||
<a data-id="{{server['server_data']['server_id']}}" class=""><i
|
||||
class="fa fa-spinner fa-spin"></i> {{ translate('serverTerm', 'updating',
|
||||
data['lang']) }}</i></a>
|
||||
{% elif server['stats']['waiting_start']%}
|
||||
<!-- WHAT HAPPENED HERE -->
|
||||
|
@ -67,7 +67,7 @@
|
||||
placeholder="{{ translate('serverConfig', 'serverPath', data['lang']) }}" required>
|
||||
|
||||
</div>
|
||||
|
||||
{% if data['server_stats']['server_type'] != "minecraft-bedrock" %}
|
||||
<div class="form-group">
|
||||
<label for="log_path">{{ translate('serverConfig', 'serverLogLocation', data['lang']) }} <small
|
||||
class="text-muted ml-1"> - {{ translate('serverConfig', 'serverLogLocationDesc', data['lang'])
|
||||
@ -76,6 +76,7 @@
|
||||
value="{{ data['server_stats']['server_id']['log_path'] }}"
|
||||
placeholder="{{ translate('serverConfig', 'serverLogLocation', data['lang']) }}" required>
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<div class="form-group">
|
||||
<label for="executable">{{ translate('serverConfig', 'serverExecutable', data['lang']) }} <small
|
||||
@ -138,6 +139,7 @@
|
||||
</div>
|
||||
|
||||
{% if data['super_user'] %}
|
||||
{% if data['server_stats']['server_type'] != "minecraft-bedrock" %}
|
||||
<div class="form-group">
|
||||
<label for="executable_update_url">{{ translate('serverConfig', 'exeUpdateURL', data['lang']) }}
|
||||
<small class="text-muted ml-1"> - {{ translate('serverConfig', 'exeUpdateURLDesc', data['lang'])
|
||||
@ -146,6 +148,7 @@
|
||||
value="{{ data['server_stats']['server_id']['executable_update_url'] }}"
|
||||
placeholder="{{ translate('serverConfig', 'exeUpdateURL', data['lang']) }}">
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<div class="form-group">
|
||||
<label for="server_ip">{{ translate('serverConfig', 'serverIP', data['lang']) }} <small
|
||||
@ -250,14 +253,31 @@
|
||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverConfig',
|
||||
'update', data['lang']) }}</button>
|
||||
{% if data['server_stats']['updating'] %}
|
||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverConfig',
|
||||
'update', data['lang']) }} <i id="update-spinner" class="fa fa-spinner fa-spin"></i></button>
|
||||
{% else %}
|
||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverConfig',
|
||||
'update', data['lang']) }} <i style="visibility: hidden;" id="update-spinner"
|
||||
class="fa fa-spinner fa-spin"></i></button>
|
||||
{% end %}
|
||||
<a class="btn btn-sm btn-danger disabled">{{ translate('serverConfig', 'deleteServer', data['lang'])
|
||||
}}</a><br />
|
||||
<small>{{ translate('serverConfig', 'stopBeforeDeleting', data['lang']) }}</small>
|
||||
{% else %}
|
||||
{% if not data['failed'] %}
|
||||
{% if data['server_stats']['updating'] %}
|
||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1">{{ translate('serverConfig',
|
||||
'update', data['lang']) }}</button>
|
||||
'update', data['lang']) }} <i id="update-spinner" class="fa fa-spinner fa-spin"></i></button>
|
||||
{% else %}
|
||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1">{{ translate('serverConfig',
|
||||
'update', data['lang']) }} <i style="visibility: hidden;" id="update-spinner"
|
||||
class="fa fa-spinner fa-spin"></i></button>
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% if not data['failed'] %}
|
||||
<button onclick="deleteConfirm()" class="btn btn-sm btn-danger">{{ translate('serverConfig',
|
||||
@ -353,6 +373,9 @@
|
||||
function send_command(serverId, command) {
|
||||
//<!-- this getCookie function is in base.html-->
|
||||
var token = getCookie("_xsrf");
|
||||
if (command == "update_executable") {
|
||||
document.getElementById("update-spinner").style.visibility = "visible";
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
@ -505,6 +528,12 @@
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
webSocket.on('remove_spinner', function () {
|
||||
document.getElementById("update-spinner").style.visibility = "hidden";
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
{% end %}
|
@ -55,7 +55,8 @@
|
||||
{% if data['permissions']['Commands'] in data['user_permissions'] %}
|
||||
{% if data['server_stats']['updating']%}
|
||||
<div id="update_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: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'updating', data['lang']) }}</button>
|
||||
<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled"><i
|
||||
class="fa fa-spinner fa-spin"></i> {{ translate('serverTerm', 'updating', 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>
|
||||
|
Loading…
Reference in New Issue
Block a user