Merge branch 'dew-features' into 'dev'

Adds port/internet connection checks. Adds kill button to dashboard.

See merge request crafty-controller/crafty-commander!68
This commit is contained in:
Andrew 2021-09-13 19:10:19 +00:00
commit 65295604a3
9 changed files with 139 additions and 10 deletions

View File

@ -14,6 +14,7 @@ import html
import zipfile
import pathlib
import shutil
from requests import get
from datetime import datetime
from socket import gethostname
@ -76,6 +77,26 @@ class Helpers:
logger.error("{} does not exist".format(file))
return True
@staticmethod
def check_internet():
try:
requests.get('https://google.com', timeout=1)
return True
except Exception as err:
return False
@staticmethod
def check_port(server_port):
host_public = get('https://api.ipify.org').text
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((host_public ,server_port))
sock.close()
if result == 0:
return True
else:
return False
def check_for_old_logs(self, db_helper):
servers = db_helper.get_all_defined_servers()
for server in servers:

View File

@ -191,8 +191,20 @@ class Server:
'error': msg
})
return False
websocket_helper.broadcast('send_start_reload', {
})
if helper.check_internet():
loc_server_port = db_helper.get_server_stats_by_id(self.server_id)['server_port']
if helper.check_port(loc_server_port):
websocket_helper.broadcast('send_start_reload', {
})
else:
websocket_helper.broadcast('send_start_error', {
'error': "We have detected port {} may not be open on the host network or a firewall is blocking it. Remote client connections to the server may be limited.".format(loc_server_port)
})
else:
websocket_helper.broadcast('send_start_error', {
'error': "We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited."
})
self.process = pexpect.spawn(self.server_command, cwd=self.server_path, timeout=None, encoding='utf-8')
out_buf = ServerOutBuf(self.process, self.server_id)
@ -350,6 +362,9 @@ class Server:
else:
return False
def get_pid(self):
return self.PID
def detect_crash(self):
logger.info("Detecting possible crash for server: {} ".format(self.name))

View File

@ -2,6 +2,7 @@ import json
import logging
import tempfile
import threading
from typing import Container
import zipfile
import tornado.web
@ -197,6 +198,18 @@ class AjaxHandler(BaseHandler):
self.redirect("/panel/server_detail?id={}&subpage=files".format(server_id))
return
elif page == "kill":
server_id = self.get_argument('id', None)
svr = self.controller.get_server_obj(server_id)
if svr.get_pid():
try:
svr.killpid(svr.get_pid())
except Exception as e:
logger.error("Could not find PID for requested termsig. Full error: {}".format(e))
else:
logger.error("Could not find PID for requested termsig. Full error: {}".format(e))
return
@tornado.web.authenticated
def delete(self, page):
if page == "del_file":

View File

@ -228,7 +228,12 @@ if (webSocket) {
var x = document.querySelector('.modal-backdrop');
if(x){
x.remove()}
bootbox.alert(start_error.error);
bootbox.alert({
message: start_error.error,
callback: function () {
location.reload();
}
})
});
}

View File

@ -126,13 +126,15 @@
<td id="controls{{server['server_data']['server_id']}}" class="actions_serverlist">
{% if server['user_command_permission'] %}
{% if server['stats']['running'] %}
<a class="stop_button" data-id="{{server['server_data']['server_id']}}"> <i class="fas fa-stop"></i></a> &nbsp;
<a class="restart_button" data-id="{{server['server_data']['server_id']}}"> <i class="fas fa-sync"></i></a> &nbsp;
<a class="stop_button" data-id="{{server['server_data']['server_id']}}" data-toggle="tooltip" title={{ translate('dashboard', 'stop') }}> <i class="fas fa-stop"></i></a> &nbsp;
<a class="restart_button" data-id="{{server['server_data']['server_id']}}" data-toggle="tooltip" title={{ translate('dashboard', 'restart') }}> <i class="fas fa-sync"></i></a> &nbsp;
<a class="kill_button" data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title={{ translate('dashboard', 'kill') }}> <i class="fas fa-skull"></i></a> &nbsp;
{% elif server['stats']['updating']%}
<a data-id="{{server['server_data']['server_id']}}" class=""> UPDATING...</i></a>
{% else %}
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play"></i></a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="clone_button"> <i class="fas fa-clone"></i></a>&nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="play_button"><i class="fas fa-play" data-toggle="tooltip" title={{ translate('dashboard', 'start') }}></i></a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="clone_button"> <i class="fas fa-clone" data-toggle="tooltip" title={{ translate('dashboard', 'clone') }}></i></a>&nbsp;
<a class="kill_button" data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title={{ translate('dashboard', 'kill') }}> <i class="fas fa-skull"></i></a> &nbsp;
{% end %}
{% end %}
</td>
@ -240,6 +242,25 @@ function send_command (server_id, command){
});
}
function send_kill (server_id){
/* this getCookie function is in base.html */
var token = getCookie("_xsrf");
$.ajax({
type: "POST",
headers: {'X-XSRFToken': token},
url: '/ajax/kill?id=' + server_id,
success: function(data){
console.log("got response:");
console.log(data);
setTimeout(function(){
location.reload();
}, 10000);
}
});
}
$( document ).ready(function() {
console.log('ready for JS!')
@ -272,6 +293,37 @@ $( document ).ready(function() {
title: '{% raw translate("dashboard", "sendingCommand") %}',
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("dashboard", "bePatientRestart") %} </div>'
});
});
$( ".kill_button" ).click(function() {
server_id = $(this).attr("data-id");
bootbox.confirm({
message: "This will kill the server process and all it's subprocesses. Killing a process can potentially corrupt files. Only do this in extreme circumstances. Are you sure you would like to continue?",
buttons: {
confirm: {
label: '{% raw translate("dashboard", "kill") %}',
className: 'btn-danger'
},
cancel: {
label: '{% raw translate("panelConfig", "cancel") %}',
className: 'btn-secondary'
}
},
callback: function (result) {
if(result){
send_kill(server_id);
var dialog = bootbox.dialog({
title: '{% raw translate("dashboard", "killing") %}',
message: '<p><i class="fa fa-spin fa-spinner"></i> Loading...</p>'
});
dialog.init(function(){
setTimeout(function(){
location.reload();
}, 15000);
});
}
}
});
});
if (webSocket) {
cpu_data = document.getElementById('cpu_data');

View File

@ -89,7 +89,13 @@
"sendingCommand": "Sending your command",
"cpuCurFreq": "CPU Current Clock",
"cpuMaxFreq": "CPU Maximum Clock",
"cpuCores": "CPU Cores"
"cpuCores": "CPU Cores",
"start": "Start",
"stop": "Stop",
"clone": "Clone",
"kill": "Kill Process",
"restart": "Restart",
"killing": "Killing process..."
},
"accessDenied": {
"accessDenied": "Access Denied",

View File

@ -89,7 +89,13 @@
"sendingCommand": "Lähetämme komentoasi",
"cpuCurFreq": "Nykyinen kellotaajuus",
"cpuMaxFreq": "Maksimi kellotaajuus",
"cpuCores": "Suorittimen ytimet"
"cpuCores": "Suorittimen ytimet",
"start": "Start",
"stop": "Stop",
"clone": "Clone",
"kill": "Kill Process",
"restart": "Restart",
"killing": "Killing process..."
},
"accessDenied": {
"accessDenied": "Käyttö estetty",

View File

@ -89,7 +89,13 @@
"sendingCommand": "Envoi de votre commande",
"cpuCurFreq": "Fréquence CPU actuelle",
"cpuMaxFreq": "Fréquence CPU Maximum",
"cpuCores": "Coeurs CPU"
"cpuCores": "Coeurs CPU",
"start": "Start",
"stop": "Stop",
"clone": "Clone",
"kill": "Kill Process",
"restart": "Restart",
"killing": "Killing process..."
},
"accessDenied": {
"accessDenied": "Accès Interdit",

View File

@ -131,6 +131,11 @@ if __name__ == '__main__':
# this should always be last
tasks_manager.start_main_kill_switch_watcher()
if not helper.check_internet():
console.error("We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited.")
elif not helper.check_port(helper.get_setting('https_port')):
console.error("We have detected Crafty's port, {} may not be open on the host network or a firewall is blocking it. Remote client connections to Crafty may be limited.".format(helper.get_setting('https_port')))
Crafty = MainPrompt(tasks_manager, migration_manager)
def sigterm_handler(signum, current_stack_frame):