Fix server transfer backend (#1139)

* fix notify in transfer service

* remove magical array

* fix phpstan

* better validation for allocation_additional and better docs generation

* update transfer ui

* update request body
This commit is contained in:
Boy132 2025-04-01 11:19:14 +02:00 committed by GitHub
parent 630031e1c2
commit 9c3f47590c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 27 deletions

View File

@ -55,6 +55,7 @@ use Filament\Resources\Pages\EditRecord;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Client\ConnectionException; use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Support\HtmlString; use Illuminate\Support\HtmlString;
use LogicException; use LogicException;
@ -921,7 +922,7 @@ class EditServer extends EditRecord
->modalheading(trans('admin/server.transfer')) ->modalheading(trans('admin/server.transfer'))
->action(function (TransferServerService $transfer, Server $server, $data) { ->action(function (TransferServerService $transfer, Server $server, $data) {
try { try {
$transfer->handle($server, $data); $transfer->handle($server, Arr::get($data, 'node_id'), Arr::get($data, 'allocation_id'), Arr::get($data, 'allocation_additional', []));
Notification::make() Notification::make()
->title('Transfer started') ->title('Transfer started')

View File

@ -13,6 +13,7 @@ use App\Services\Servers\TransferServerService;
use Dedoc\Scramble\Attributes\Group; use Dedoc\Scramble\Attributes\Group;
use Illuminate\Http\Client\ConnectionException; use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Illuminate\Support\Arr;
#[Group('Server', weight: 4)] #[Group('Server', weight: 4)]
class ServerManagementController extends ApplicationApiController class ServerManagementController extends ApplicationApiController
@ -82,15 +83,24 @@ class ServerManagementController extends ApplicationApiController
$validatedData = $request->validate([ $validatedData = $request->validate([
'node_id' => 'required|exists:nodes,id', 'node_id' => 'required|exists:nodes,id',
'allocation_id' => 'required|bail|unique:servers|exists:allocations,id', 'allocation_id' => 'required|bail|unique:servers|exists:allocations,id',
'allocation_additional' => 'nullable', 'allocation_additional' => 'nullable|array',
'allocation_additional.*' => 'integer|exists:allocations,id',
]); ]);
if ($this->transferServerService->handle($server, $validatedData)) { if ($this->transferServerService->handle($server, Arr::get($validatedData, 'node_id'), Arr::get($validatedData, 'allocation_id'), Arr::get($validatedData, 'allocation_additional', []))) {
// Transfer started /**
* Transfer started
*
* @status 204
*/
return $this->returnNoContent(); return $this->returnNoContent();
} }
// Node was not viable /**
* Node was not viable
*
* @status 406
*/
return $this->returnNotAcceptable(); return $this->returnNotAcceptable();
} }
@ -104,7 +114,11 @@ class ServerManagementController extends ApplicationApiController
public function cancelTransfer(ServerWriteRequest $request, Server $server): Response public function cancelTransfer(ServerWriteRequest $request, Server $server): Response
{ {
if (!$transfer = $server->transfer) { if (!$transfer = $server->transfer) {
// Server is not transferring /**
* Server is not transferring
*
* @status 406
*/
return $this->returnNotAcceptable(); return $this->returnNotAcceptable();
} }
@ -113,6 +127,11 @@ class ServerManagementController extends ApplicationApiController
$this->daemonServerRepository->setServer($server)->cancelTransfer(); $this->daemonServerRepository->setServer($server)->cancelTransfer();
/**
* Transfer cancelled
*
* @status 204
*/
return $this->returnNoContent(); return $this->returnNoContent();
} }
} }

View File

@ -22,37 +22,28 @@ class TransferServerService
private NodeJWTService $nodeJWTService, private NodeJWTService $nodeJWTService,
) {} ) {}
private function notify(Server $server, Plain $token): void private function notify(ServerTransfer $transfer, Plain $token): void
{ {
Http::daemon($server->node)->post('/api/transfer', [ Http::daemon($transfer->oldNode)->post("/api/servers/{$transfer->server->uuid}/transfer", [
'json' => [ 'url' => $transfer->newNode->getConnectionAddress() . '/api/transfers',
'server_id' => $server->uuid, 'token' => 'Bearer ' . $token->toString(),
'url' => $server->node->getConnectionAddress() . "/api/servers/$server->uuid/archive", 'server' => [
'token' => 'Bearer ' . $token->toString(), 'uuid' => $transfer->server->uuid,
'server' => [ 'start_on_completion' => false,
'uuid' => $server->uuid,
'start_on_completion' => false,
],
], ],
])->toPsrResponse(); ]);
} }
/** /**
* Starts a transfer of a server to a new node. * Starts a transfer of a server to a new node.
* *
* @param array{ * @param int[] $additional_allocations
* allocation_id: int,
* node_id: int,
* allocation_additional?: ?int[],
* } $data
* *
* @throws \Throwable * @throws \Throwable
*/ */
public function handle(Server $server, array $data): bool public function handle(Server $server, int $node_id, int $allocation_id, array $additional_allocations): bool
{ {
$node_id = $data['node_id']; $additional_allocations = array_map(intval(...), $additional_allocations);
$allocation_id = intval($data['allocation_id']);
$additional_allocations = array_map(intval(...), $data['allocation_additional'] ?? []);
// Check if the node is viable for the transfer. // Check if the node is viable for the transfer.
$node = Node::query() $node = Node::query()
@ -94,7 +85,7 @@ class TransferServerService
->handle($transfer->newNode, $server->uuid, 'sha256'); ->handle($transfer->newNode, $server->uuid, 'sha256');
// Notify the source node of the pending outgoing transfer. // Notify the source node of the pending outgoing transfer.
$this->notify($server, $token); $this->notify($transfer, $token);
return $transfer; return $transfer;
}); });