diff --git a/app/Repositories/Wings/DaemonBackupRepository.php b/app/Repositories/Wings/DaemonBackupRepository.php index d95573d1f..7657c53f7 100644 --- a/app/Repositories/Wings/DaemonBackupRepository.php +++ b/app/Repositories/Wings/DaemonBackupRepository.php @@ -3,6 +3,7 @@ namespace Pterodactyl\Repositories\Wings; use Webmozart\Assert\Assert; +use Pterodactyl\Models\Backup; use Pterodactyl\Models\Server; use Psr\Http\Message\ResponseInterface; use GuzzleHttp\Exception\TransferException; @@ -10,6 +11,33 @@ use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; class DaemonBackupRepository extends DaemonRepository { + /** + * Tells the remote Daemon to begin generating a backup for the server. + * + * @param \Pterodactyl\Models\Backup $backup + * @return \Psr\Http\Message\ResponseInterface + * + * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException + */ + public function backup(Backup $backup): ResponseInterface + { + Assert::isInstanceOf($this->server, Server::class); + + try { + return $this->getHttpClient()->post( + sprintf('/api/servers/%s/backup', $this->server->uuid), + [ + 'json' => [ + 'uuid' => $backup->uuid, + 'ignored_files' => explode(PHP_EOL, $backup->ignored_files), + ], + ] + ); + } catch (TransferException $exception) { + throw new DaemonConnectionException($exception); + } + } + /** * Returns a stream of a backup's contents from the Wings instance so that we * do not need to send the user directly to the Daemon. diff --git a/app/Services/Backups/InitiateBackupService.php b/app/Services/Backups/InitiateBackupService.php index b58fba018..f9c4de4b5 100644 --- a/app/Services/Backups/InitiateBackupService.php +++ b/app/Services/Backups/InitiateBackupService.php @@ -6,7 +6,9 @@ use Ramsey\Uuid\Uuid; use Carbon\CarbonImmutable; use Pterodactyl\Models\Backup; use Pterodactyl\Models\Server; +use Illuminate\Database\ConnectionInterface; use Pterodactyl\Repositories\Eloquent\BackupRepository; +use Pterodactyl\Repositories\Wings\DaemonBackupRepository; class InitiateBackupService { @@ -20,14 +22,31 @@ class InitiateBackupService */ private $repository; + /** + * @var \Illuminate\Database\ConnectionInterface + */ + private $connection; + + /** + * @var \Pterodactyl\Repositories\Wings\DaemonBackupRepository + */ + private $daemonBackupRepository; + /** * InitiateBackupService constructor. * * @param \Pterodactyl\Repositories\Eloquent\BackupRepository $repository + * @param \Illuminate\Database\ConnectionInterface $connection + * @param \Pterodactyl\Repositories\Wings\DaemonBackupRepository $daemonBackupRepository */ - public function __construct(BackupRepository $repository) - { + public function __construct( + BackupRepository $repository, + ConnectionInterface $connection, + DaemonBackupRepository $daemonBackupRepository + ) { $this->repository = $repository; + $this->connection = $connection; + $this->daemonBackupRepository = $daemonBackupRepository; } /** @@ -50,19 +69,23 @@ class InitiateBackupService * @param string|null $name * @return \Pterodactyl\Models\Backup * - * @throws \Exception + * @throws \Throwable */ public function handle(Server $server, string $name = null): Backup { - /** @var \Pterodactyl\Models\Backup $backup */ - $backup = $this->repository->create([ - 'server_id' => $server->id, - 'uuid' => Uuid::uuid4()->toString(), - 'name' => trim($name) ?: sprintf('Backup at %s', CarbonImmutable::now()->toDateTimeString()), - 'ignored_files' => $this->ignoredFiles ?? '', - 'disk' => 'local', - ], true, true); + return $this->connection->transaction(function () use ($server, $name) { + /** @var \Pterodactyl\Models\Backup $backup */ + $backup = $this->repository->create([ + 'server_id' => $server->id, + 'uuid' => Uuid::uuid4()->toString(), + 'name' => trim($name) ?: sprintf('Backup at %s', CarbonImmutable::now()->toDateTimeString()), + 'ignored_files' => $this->ignoredFiles ?? '', + 'disk' => 'local', + ], true, true); - return $backup; + $this->daemonBackupRepository->setServer($server)->backup($backup); + + return $backup; + }); } }