8b8ef4f2d6
Shows all CPU core usage as well.
465 lines
18 KiB
PHP
465 lines
18 KiB
PHP
@extends('layouts.master')
|
|
|
|
@section('title')
|
|
Viewing Server: {{ $server->name }}
|
|
@endsection
|
|
|
|
@section('scripts')
|
|
@parent
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/highcharts/4.2.1/highcharts.js"></script>
|
|
<script src="{{ asset('js/chartjs/chart.bar.js') }}"></script>
|
|
@endsection
|
|
|
|
@section('content')
|
|
<div class="col-md-9">
|
|
@foreach (Alert::getMessages() as $type => $messages)
|
|
@foreach ($messages as $message)
|
|
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
|
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
{{ $message }}
|
|
</div>
|
|
@endforeach
|
|
@endforeach
|
|
<ul class="nav nav-tabs" id="config_tabs">
|
|
<li class="active"><a href="#stats" data-toggle="tab">{{ trans('server.index.info_use') }}</a></li>
|
|
<li id="triggerConsoleView"><a href="#console" data-toggle="tab">{{ trans('server.index.control') }}</a></li>
|
|
</ul><br />
|
|
<div class="tab-content">
|
|
<div class="tab-pane active" id="stats">
|
|
<div class="row">
|
|
<div class="col-md-12" id="chart_memory" style="height:250px;"></div>
|
|
<div class="col-md-12" id="chart_cpu" style="height:250px;"></div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-12" id="stats_players">
|
|
<h3 class="nopad">Active Players</h3><hr />
|
|
<div id="players_notice" class="alert alert-info">
|
|
<i class="fa fa-spinner fa-spin"></i> Waiting for response from server...
|
|
</div>
|
|
<span id="toggle_players" style="display:none;">
|
|
<p class="text-muted">No players are online.</p>
|
|
</span>
|
|
</div>
|
|
<div class="col-md-12">
|
|
<h3>{{ trans('server.index.server_info') }}</h3><hr />
|
|
<table class="table table-striped table-bordered table-hover">
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>{{ trans('server.index.connection') }}</strong></td>
|
|
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>{{ trans('strings.node') }}</strong></td>
|
|
<td>{{ $node->name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>{{ trans('server.index.mem_limit') }}</strong></td>
|
|
<td>{{ $server->memory }} MB</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>{{ trans('server.index.disk_space') }}</strong></td>
|
|
<td>{{ $server->disk }} MB</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane" id="console">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<textarea id="live_console" class="form-control console" readonly="readonly">Loading Previous Content...</textarea>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<hr />
|
|
<form action="#" method="post" id="console_command" style="display:none;">
|
|
<fieldset>
|
|
<div class="input-group">
|
|
<input type="text" class="form-control" name="command" id="ccmd" placeholder="{{ trans('server.index.command') }}" />
|
|
<span class="input-group-btn">
|
|
<button id="sending_command" class="btn btn-primary btn-sm">→</button>
|
|
</span>
|
|
</div>
|
|
</fieldset>
|
|
</form>
|
|
<div class="alert alert-danger" id="sc_resp" style="display:none;margin-top: 15px;"></div>
|
|
</div>
|
|
<div class="col-md-6" style="text-align:center;">
|
|
<hr />
|
|
<button class="btn btn-success btn-sm disabled" data-attr="power" data-action="start">Start</button>
|
|
<button class="btn btn-primary btn-sm disabled" data-attr="power" data-action="restart">Restart</button>
|
|
<button class="btn btn-danger btn-sm disabled" data-attr="power" data-action="stop">Stop</button>
|
|
<button class="btn btn-danger btn-sm disabled" data-attr="power" data-action="kill"><i class="fa fa-ban" data-toggle="tooltip" data-placement="top" title="Kill Running Process"></i></button>
|
|
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#pauseConsole" id="pause_console"><small><i class="fa fa-pause fa-fw"></i></small></button>
|
|
<div id="pw_resp" style="display:none;margin-top: 15px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal fade" id="pauseConsole" tabindex="-1" role="dialog" aria-labelledby="PauseConsole" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
<h4 class="modal-title" id="PauseConsole">{{ trans('server.index.scrollstop') }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<textarea id="paused_console" class="form-control console" readonly="readonly"></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('strings.close') }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
$(window).load(function () {
|
|
$('[data-toggle="tooltip"]').tooltip();
|
|
|
|
// -----------------+
|
|
// Charting Methods |
|
|
// -----------------+
|
|
$('#chart_memory').highcharts({
|
|
chart: {
|
|
type: 'area',
|
|
animation: Highcharts.svg,
|
|
marginRight: 10,
|
|
},
|
|
colors: [
|
|
'#113F8C',
|
|
'#00A1CB',
|
|
'#01A4A4',
|
|
'#61AE24',
|
|
'#D0D102',
|
|
'#D70060',
|
|
'#E54028',
|
|
'#F18D05',
|
|
'#616161',
|
|
'#32742C',
|
|
],
|
|
credits: {
|
|
enabled: false,
|
|
},
|
|
title: {
|
|
text: 'Live Memory Usage',
|
|
},
|
|
tooltip: {
|
|
shared: true,
|
|
crosshairs: true,
|
|
formatter: function () {
|
|
var s = '<b>Memory Usage</b>';
|
|
|
|
$.each(this.points, function () {
|
|
s += '<br/>' + this.series.name + ': ' +
|
|
this.y + 'MB';
|
|
});
|
|
|
|
return s;
|
|
},
|
|
},
|
|
xAxis: {
|
|
visible: false,
|
|
},
|
|
yAxis: {
|
|
title: {
|
|
text: 'Memory Usage (MB)',
|
|
},
|
|
plotLines: [{
|
|
value: 0,
|
|
width: 1,
|
|
}],
|
|
},
|
|
plotOptions: {
|
|
area: {
|
|
fillOpacity: 0.10,
|
|
marker: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
},
|
|
legend: {
|
|
enabled: false
|
|
},
|
|
series: [{
|
|
name: 'Total Memory',
|
|
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
}]
|
|
});
|
|
|
|
$('#chart_cpu').highcharts({
|
|
chart: {
|
|
type: 'area',
|
|
animation: Highcharts.svg,
|
|
marginRight: 10,
|
|
},
|
|
colors: [
|
|
'#113F8C',
|
|
'#00A1CB',
|
|
'#01A4A4',
|
|
'#61AE24',
|
|
'#D0D102',
|
|
'#D70060',
|
|
'#E54028',
|
|
'#F18D05',
|
|
'#616161',
|
|
'#32742C',
|
|
],
|
|
credits: {
|
|
enabled: false,
|
|
},
|
|
title: {
|
|
text: 'Live CPU Usage',
|
|
},
|
|
tooltip: {
|
|
shared: true,
|
|
crosshairs: true,
|
|
formatter: function () {
|
|
var s = '<b>CPU Usage</b>';
|
|
|
|
$.each(this.points, function () {
|
|
s += '<br/>' + this.series.name + ': ' +
|
|
this.y + '%';
|
|
});
|
|
|
|
return s;
|
|
},
|
|
},
|
|
xAxis: {
|
|
visible: false,
|
|
},
|
|
yAxis: {
|
|
title: {
|
|
text: 'CPU Usage (%)',
|
|
},
|
|
plotLines: [{
|
|
value: 0,
|
|
width: 1,
|
|
}],
|
|
},
|
|
plotOptions: {
|
|
area: {
|
|
fillOpacity: 0.10,
|
|
stacking: 'normal',
|
|
lineWidth: 1,
|
|
marker: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
},
|
|
legend: {
|
|
enabled: true
|
|
},
|
|
series: [{
|
|
name: 'Total CPU',
|
|
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
}]
|
|
});
|
|
|
|
// Socket Recieves New Server Stats
|
|
socket.on('proc', function (proc) {
|
|
var MemoryChart = $('#chart_memory').highcharts();
|
|
MemoryChart.series[0].addPoint(parseInt(proc.data.memory.total / (1024 * 1024)), true, true);
|
|
|
|
var CPUChart = $('#chart_cpu').highcharts();
|
|
|
|
if({{ $server->cpu }} > 0) {
|
|
CPUChart.series[0].addPoint(parseFloat(((proc.data.cpu.total / {{ $server->cpu }}) * 100).toFixed(3).toString()), true, true);
|
|
} else {
|
|
CPUChart.series[0].addPoint(proc.data.cpu.total, true, true);
|
|
}
|
|
for (i = 0, length = proc.data.cpu.cores.length; i < length; i++) {
|
|
if (typeof CPUChart.series[ i + 1 ] === 'undefined') {
|
|
CPUChart.addSeries({
|
|
name: 'Core ' + i,
|
|
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
});
|
|
}
|
|
if({{ $server->cpu }} > 0) {
|
|
CPUChart.series[ i + 1 ].addPoint(parseFloat(((proc.data.cpu.cores[i] / {{ $server->cpu }}) * 100).toFixed(3).toString())
|
|
, true, true);
|
|
} else {
|
|
CPUChart.series[ i + 1 ].addPoint(proc.data.cpu.cores[i], true, true);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Socket Recieves New Query
|
|
socket.on('query', function (data){
|
|
if($('#players_notice').is(':visible')){
|
|
$('#players_notice').hide();
|
|
$('#toggle_players').show();
|
|
}
|
|
if(data['data'].players != undefined && data['data'].players.length !== 0){
|
|
$('#toggle_players').html('');
|
|
$.each(data['data'].players, function(id, d) {
|
|
$('#toggle_players').append('<code>' + d.name + '</code>,');
|
|
});
|
|
}else{
|
|
$('#toggle_players').html('<p class=\'text-muted\'>No players are currently online.</p>');
|
|
}
|
|
});
|
|
|
|
// New Console Data Recieved
|
|
socket.on('console', function (data) {
|
|
console.log(JSON.stringify(data));
|
|
$('#live_console').val($('#live_console').val() + data.line);
|
|
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
|
|
});
|
|
|
|
// Update Listings on Initial Status
|
|
socket.on('initial_status', function (data) {
|
|
if (data.status !== 0) {
|
|
$.ajax({
|
|
type: 'GET',
|
|
headers: {
|
|
'X-Access-Token': '{{ $server->daemonSecret }}',
|
|
'X-Access-Server': '{{ $server->uuid }}'
|
|
},
|
|
url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/log',
|
|
timeout: 10000
|
|
}).done(function(data) {
|
|
$('#live_console').val(data);
|
|
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
|
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
|
alert('Unable to load initial server log, try reloading the page.');
|
|
});
|
|
} else {
|
|
$('#live_console').val('Server is currently off.');
|
|
}
|
|
updateServerPowerControls(data.status);
|
|
updatePlayerListVisibility(data.status);
|
|
});
|
|
|
|
// Update Listings on Status
|
|
socket.on('status', function (data) {
|
|
updateServerPowerControls(data.status);
|
|
updatePlayerListVisibility(data.status);
|
|
});
|
|
|
|
// Scroll to the top of the Console when switching to that tab.
|
|
$('#triggerConsoleView').click(function () {
|
|
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
|
|
});
|
|
if($('triggerConsoleView').is(':visible')) {
|
|
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
|
|
}
|
|
$('a[data-toggle=\'tab\']').on('shown.bs.tab', function (e) {
|
|
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
|
|
});
|
|
|
|
// Load Paused Console with Live Console Data
|
|
$('#pause_console').click(function(){
|
|
$('#paused_console').val($('#live_console').val());
|
|
});
|
|
|
|
function updatePlayerListVisibility(data) {
|
|
// Server is On or Starting
|
|
if(data !== 0) {
|
|
$('#stats_players').show();
|
|
} else {
|
|
$('#stats_players').hide();
|
|
}
|
|
}
|
|
@can('command', $server)
|
|
// Send Command to Server
|
|
$('#console_command').submit(function (event) {
|
|
|
|
event.preventDefault();
|
|
var ccmd = $('#ccmd').val();
|
|
if (ccmd == '') {
|
|
return;
|
|
}
|
|
|
|
$('#sending_command').html('<i class=\'fa fa-refresh fa-spin\'></i>').addClass('disabled');
|
|
$.ajax({
|
|
type: 'POST',
|
|
headers: {
|
|
'X-Access-Token': '{{ $server->daemonSecret }}',
|
|
'X-Access-Server': '{{ $server->uuid }}'
|
|
},
|
|
contentType: 'application/json; charset=utf-8',
|
|
url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/command',
|
|
timeout: 10000,
|
|
data: JSON.stringify({ command: ccmd })
|
|
}).fail(function (jqXHR) {
|
|
$('#sc_resp').html('Unable to process your request. Please try again.').fadeIn().delay(5000).fadeOut();
|
|
}).always(function () {
|
|
$('#sending_command').html('→').removeClass('disabled');
|
|
$('#ccmd').val('');
|
|
});
|
|
});
|
|
@endcan
|
|
@can('power', $server)
|
|
var can_run = true;
|
|
function updateServerPowerControls (data) {
|
|
|
|
// Reset Console Data
|
|
if (data === 2) {
|
|
$("#live_console").val('');
|
|
}
|
|
|
|
// Server is On or Starting
|
|
if(data == 1 || data == 2) {
|
|
$("#console_command").slideDown();
|
|
$('[data-attr="power"][data-action="start"]').addClass('disabled');
|
|
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').removeClass('disabled');
|
|
} else {
|
|
$("#console_command").slideUp();
|
|
$('[data-attr="power"][data-action="start"]').removeClass('disabled');
|
|
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').addClass('disabled');
|
|
}
|
|
|
|
if(data !== 0) {
|
|
$('[data-attr="power"][data-action="kill"]').removeClass('disabled');
|
|
} else {
|
|
$('[data-attr="power"][data-action="kill"]').addClass('disabled');
|
|
}
|
|
|
|
}
|
|
|
|
$('[data-attr="power"]').click(function (event) {
|
|
event.preventDefault();
|
|
var action = $(this).data('action');
|
|
if (action === 'kill') {
|
|
var killConfirm = confirm('WARNING: This operation will not save your server data gracefully. You should only use this if your server is failing to respond to normal stop commands.');
|
|
} else { var killConfirm = true; }
|
|
|
|
if(killConfirm) {
|
|
$.ajax({
|
|
type: 'PUT',
|
|
headers: {
|
|
'X-Access-Token': '{{ $server->daemonSecret }}',
|
|
'X-Access-Server': '{{ $server->uuid }}'
|
|
},
|
|
contentType: 'application/json; charset=utf-8',
|
|
data: JSON.stringify({
|
|
action: action
|
|
}),
|
|
url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/power',
|
|
timeout: 10000
|
|
}).done(function(data) {
|
|
$('#pw_resp').attr('class', 'alert alert-success').html('Server has been ' + action + 'ed successfully.').fadeIn().delay(5000).fadeOut();
|
|
}).fail(function(jqXHR) {
|
|
var error = 'An unknown error occured processing this request.';
|
|
if (typeof jqXHR.responseJSON.error !== 'undefined') {
|
|
error = jqXHR.responseJSON.error;
|
|
}
|
|
$('#pw_resp').attr('class', 'alert alert-danger').html('Unable to process your request. Please try again. (' + error + ')').fadeIn().delay(5000).fadeOut();
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
@endcan
|
|
});
|
|
|
|
$(document).ready(function () {
|
|
$('.server-index').addClass('active');
|
|
});
|
|
</script>
|
|
@endsection
|