2026-04-17 02:27:47 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\V2\Server;
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
use App\Models\ServerMachine;
|
|
|
|
|
use App\Models\ServerMachineLoadHistory;
|
|
|
|
|
use App\Services\ServerService;
|
|
|
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* machine controller
|
|
|
|
|
*/
|
|
|
|
|
class MachineController extends Controller
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* get nodes list for machine
|
|
|
|
|
*/
|
|
|
|
|
public function nodes(Request $request): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$machine = $this->authenticateMachine($request);
|
|
|
|
|
|
|
|
|
|
$nodes = ServerService::getMachineNodes($machine)
|
|
|
|
|
->map(fn($node) => [
|
|
|
|
|
'id' => $node->id,
|
|
|
|
|
'type' => $node->type,
|
|
|
|
|
'name' => $node->name,
|
|
|
|
|
])->values();
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'nodes' => $nodes,
|
|
|
|
|
'base_config' => [
|
|
|
|
|
'push_interval' => (int) admin_setting('server_push_interval', 60),
|
|
|
|
|
'pull_interval' => (int) admin_setting('server_pull_interval', 60),
|
|
|
|
|
],
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* report machine status
|
|
|
|
|
*/
|
|
|
|
|
public function status(Request $request): JsonResponse
|
|
|
|
|
{
|
|
|
|
|
$request->validate([
|
|
|
|
|
'cpu' => 'required|numeric|min:0|max:100',
|
|
|
|
|
'mem.total' => 'required|integer|min:0',
|
|
|
|
|
'mem.used' => 'required|integer|min:0',
|
|
|
|
|
'swap.total' => 'nullable|integer|min:0',
|
|
|
|
|
'swap.used' => 'nullable|integer|min:0',
|
|
|
|
|
'disk.total' => 'nullable|integer|min:0',
|
|
|
|
|
'disk.used' => 'nullable|integer|min:0',
|
2026-04-18 02:02:06 +08:00
|
|
|
'net.in_speed' => 'nullable|numeric|min:0',
|
|
|
|
|
'net.out_speed' => 'nullable|numeric|min:0',
|
2026-04-17 02:27:47 +08:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$machine = $this->authenticateMachine($request);
|
|
|
|
|
$recordedAt = now()->timestamp;
|
|
|
|
|
|
2026-04-18 02:02:06 +08:00
|
|
|
$loadStatus = [
|
|
|
|
|
'cpu' => (float) $request->input('cpu'),
|
|
|
|
|
'mem' => [
|
|
|
|
|
'total' => (int) $request->input('mem.total'),
|
|
|
|
|
'used' => (int) $request->input('mem.used'),
|
|
|
|
|
],
|
|
|
|
|
'swap' => [
|
|
|
|
|
'total' => (int) $request->input('swap.total', 0),
|
|
|
|
|
'used' => (int) $request->input('swap.used', 0),
|
|
|
|
|
],
|
|
|
|
|
'disk' => [
|
|
|
|
|
'total' => (int) $request->input('disk.total', 0),
|
|
|
|
|
'used' => (int) $request->input('disk.used', 0),
|
2026-04-17 02:27:47 +08:00
|
|
|
],
|
2026-04-18 02:02:06 +08:00
|
|
|
'updated_at' => $recordedAt,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$netInSpeed = $request->input('net.in_speed');
|
|
|
|
|
$netOutSpeed = $request->input('net.out_speed');
|
|
|
|
|
|
|
|
|
|
if ($netInSpeed !== null && $netOutSpeed !== null) {
|
|
|
|
|
$loadStatus['net'] = [
|
|
|
|
|
'in_speed' => (float) $netInSpeed,
|
|
|
|
|
'out_speed' => (float) $netOutSpeed,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$machine->forceFill([
|
|
|
|
|
'load_status' => $loadStatus,
|
2026-04-17 02:27:47 +08:00
|
|
|
'last_seen_at' => $recordedAt,
|
|
|
|
|
])->save();
|
|
|
|
|
|
2026-04-18 02:02:06 +08:00
|
|
|
$historyData = [
|
2026-04-17 02:27:47 +08:00
|
|
|
'machine_id' => $machine->id,
|
|
|
|
|
'cpu' => (float) $request->input('cpu'),
|
|
|
|
|
'mem_total' => (int) $request->input('mem.total'),
|
|
|
|
|
'mem_used' => (int) $request->input('mem.used'),
|
|
|
|
|
'disk_total' => (int) $request->input('disk.total', 0),
|
|
|
|
|
'disk_used' => (int) $request->input('disk.used', 0),
|
|
|
|
|
'recorded_at' => $recordedAt,
|
2026-04-18 02:02:06 +08:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if ($netInSpeed !== null && $netOutSpeed !== null) {
|
|
|
|
|
$historyData['net_in_speed'] = (float) $netInSpeed;
|
|
|
|
|
$historyData['net_out_speed'] = (float) $netOutSpeed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ServerMachineLoadHistory::create($historyData);
|
2026-04-17 02:27:47 +08:00
|
|
|
|
|
|
|
|
// Time-based cleanup: keep 24h of data, runs on ~5% of requests
|
|
|
|
|
if (random_int(1, 20) === 1) {
|
|
|
|
|
ServerMachineLoadHistory::query()
|
|
|
|
|
->where('machine_id', $machine->id)
|
|
|
|
|
->where('recorded_at', '<', now()->subDay()->timestamp)
|
|
|
|
|
->delete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response()->json(['data' => true]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function authenticateMachine(Request $request): ServerMachine
|
|
|
|
|
{
|
|
|
|
|
$request->validate([
|
|
|
|
|
'machine_id' => 'required|integer',
|
|
|
|
|
'token' => 'required|string',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$machine = ServerMachine::where('id', $request->input('machine_id'))
|
|
|
|
|
->where('token', $request->input('token'))
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
if (!$machine || !$machine->is_active) {
|
|
|
|
|
abort(403, 'Machine not found or disabled');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$machine->forceFill(['last_seen_at' => now()->timestamp])->saveQuietly();
|
|
|
|
|
|
|
|
|
|
return $machine;
|
|
|
|
|
}
|
|
|
|
|
}
|