Allow backup transfers (#2068)

Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com>
This commit is contained in:
JoanFo
2026-01-18 22:23:21 +01:00
committed by GitHub
parent 107286d618
commit d064bf9734
3 changed files with 43 additions and 5 deletions

View File

@@ -11,10 +11,12 @@ use App\Filament\Components\Forms\Fields\StartupVariable;
use App\Filament\Components\StateCasts\ServerConditionStateCast;
use App\Filament\Server\Pages\Console;
use App\Models\Allocation;
use App\Models\Backup;
use App\Models\Egg;
use App\Models\Server;
use App\Models\User;
use App\Repositories\Daemon\DaemonServerRepository;
use App\Services\Backups\DeleteBackupService;
use App\Services\Eggs\EggChangerService;
use App\Services\Servers\RandomWordService;
use App\Services\Servers\ReinstallServerService;
@@ -27,6 +29,7 @@ use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Exception;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\KeyValue;
@@ -48,6 +51,7 @@ use Filament\Schemas\Components\Image;
use Filament\Schemas\Components\StateCasts\BooleanStateCast;
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Schemas\Components\Text;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
@@ -962,9 +966,17 @@ class EditServer extends EditRecord
->disabled(fn (Server $server) => user()?->accessibleNodes()->count() <= 1 || $server->isInConflictState())
->modalHeading(trans('admin/server.transfer'))
->schema($this->transferServer())
->action(function (TransferServerService $transfer, Server $server, $data) {
->action(function (TransferServerService $transfer, DeleteBackupService $deleteBackup, Server $server, $data) {
try {
$transfer->handle($server, Arr::get($data, 'node_id'), Arr::get($data, 'allocation_id'), Arr::get($data, 'allocation_additional', []));
$selectedBackupUuids = Arr::get($data, 'backups', []);
$transfer->handle($server, Arr::get($data, 'node_id'), Arr::get($data, 'allocation_id'), Arr::get($data, 'allocation_additional', []), $selectedBackupUuids);
$server->backups
->whereNotIn('uuid', $selectedBackupUuids)
->where('disk', Backup::ADAPTER_DAEMON)
->each(function ($backup) {
$backup->delete();
});
Notification::make()
->title(trans('admin/server.notifications.transfer_started'))
@@ -1054,6 +1066,19 @@ class EditServer extends EditRecord
->options(fn (Get $get) => Allocation::where('node_id', $get('node_id'))->whereNull('server_id')->when($get('allocation_id'), fn ($query) => $query->whereNot('id', $get('allocation_id')))->get()->mapWithKeys(fn (Allocation $allocation) => [$allocation->id => $allocation->address]))
->searchable(['ip', 'port', 'ip_alias'])
->placeholder(trans('admin/server.select_additional')),
Grid::make()
->columnSpanFull()
->schema([
CheckboxList::make('backups')
->label(trans('admin/server.backups'))
->bulkToggleable()
->options(fn (Server $server) => $server->backups->where('disk', Backup::ADAPTER_DAEMON)->mapWithKeys(fn ($backup) => [$backup->uuid => $backup->name]))
->columns(fn (Server $record) => (int) ceil($record->backups->where('disk', Backup::ADAPTER_DAEMON)->count() / 4)),
Text::make('backup_helper')
->columnSpanFull()
->content(trans('admin/server.warning_backups')),
])
->hidden(fn (Server $server) => $server->backups->where('disk', Backup::ADAPTER_DAEMON)->count() === 0),
];
}

View File

@@ -3,6 +3,7 @@
namespace App\Services\Servers;
use App\Models\Allocation;
use App\Models\Backup;
use App\Models\Node;
use App\Models\Server;
use App\Models\ServerTransfer;
@@ -23,11 +24,19 @@ class TransferServerService
private NodeJWTService $nodeJWTService,
) {}
private function notify(ServerTransfer $transfer, UnencryptedToken $token): void
/**
* @param string[] $backup_uuids
*/
private function notify(ServerTransfer $transfer, UnencryptedToken $token, array $backup_uuids = []): void
{
$backups = [];
if (config('backups.default') === Backup::ADAPTER_DAEMON) {
$backups = $backup_uuids;
}
Http::daemon($transfer->oldNode)->post("/api/servers/{$transfer->server->uuid}/transfer", [
'url' => $transfer->newNode->getConnectionAddress() . '/api/transfers',
'token' => 'Bearer ' . $token->toString(),
'backups' => $backups,
'server' => [
'uuid' => $transfer->server->uuid,
'start_on_completion' => false,
@@ -39,10 +48,11 @@ class TransferServerService
* Starts a transfer of a server to a new node.
*
* @param int[] $additional_allocations
* @param string[] $backup_uuid
*
* @throws Throwable
*/
public function handle(Server $server, int $node_id, ?int $allocation_id = null, ?array $additional_allocations = []): bool
public function handle(Server $server, int $node_id, ?int $allocation_id = null, ?array $additional_allocations = [], ?array $backup_uuid = []): bool
{
$additional_allocations = array_map(intval(...), $additional_allocations);
@@ -93,7 +103,7 @@ class TransferServerService
->handle($transfer->newNode, $server->uuid, 'sha256');
// Notify the source node of the pending outgoing transfer.
$this->notify($transfer, $token);
$this->notify($transfer, $token, $backup_uuid);
return true;
}

View File

@@ -109,6 +109,8 @@ return [
'add_allocation' => 'Add Allocation',
'view' => 'View',
'no_log' => 'No Log Available',
'select_backups' => 'Select Backups',
'warning_backups' => 'Be aware, not transferred backups will be deleted.',
'tabs' => [
'information' => 'Information',
'egg_configuration' => 'Egg Configuration',
@@ -142,6 +144,7 @@ return [
'transfer_started' => 'Transfer started',
'transfer_failed' => 'Transfer failed',
'already_transfering' => 'Server is currently being transferred.',
'backup_transfer_failed' => 'Backup Transfer Failed',
],
'notes' => 'Notes',
'no_notes' => 'No Notes',