diff --git a/CHANGELOG.md b/CHANGELOG.md index a0fa415ee..9af05c890 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,23 @@ This file is a running track of new features and fixes to each version of the pa This project follows [Semantic Versioning](http://semver.org) guidelines. +## v1.6.0 +### Fixed +* Fixes array merging logic for server transfers that would cause a 500 error to occur in some scenarios. +* Fixes user password updates not correctly logging the user out and returning a failure message even upon successful update. +* Fixes the count of used backups when browsing a paginated backup list for a server. + +### Added +* Adds foreign key relationship on the `mount_node`, `mount_server` and `egg_mount` tables. +* Adds environment variable `PER_SCHEDULE_TASK_LIMIT` to allow manual overrides for the number of tasks that can exist on a single schedule. This is currently defaulted to `10`. +* OOM killer can now be configured at the time of server creation. + +### Changed +* Server updates are not dependent on a successful call to Wings occurring — if the API call fails internally the error will be logged but the server update will still be persisted. + +### Removed +* Removed `WingsServerRepository::update()` function — if you were previously using this to modify server elements on Wings please replace calls to it with `::sync()` after updating Wings. + ## v1.5.1 ### Fixed * Fixes Docker image 404ing instead of being able to access the Panel. diff --git a/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php b/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php index 6427c5cb8..031ed777c 100644 --- a/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php +++ b/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php @@ -3,7 +3,6 @@ namespace Pterodactyl\Http\Controllers\Api\Remote\Servers; use Carbon\CarbonImmutable; -use Illuminate\Support\Arr; use Illuminate\Http\Request; use Illuminate\Http\Response; use Pterodactyl\Models\Allocation; @@ -61,20 +60,7 @@ class ServerTransferController extends Controller return $this->processFailedTransfer($server->transfer); } - // We want to generate a new configuration using the new node_id value from the - // transfer, and not the old node value. - $data = $this->configurationStructureService->handle($server, [ - 'node_id' => $server->transfer->new_node, - ]); - - $allocations = $server->getAllocationMappings(); - $primary = array_key_first($allocations); - Arr::set($data, 'allocations.default.ip', $primary); - Arr::set($data, 'allocations.default.port', $allocations[$primary][0]); - Arr::set($data, 'service.skip_scripts', true); - Arr::set($data, 'suspended', false); - - $this->connection->transaction(function () use ($data, $server) { + $this->connection->transaction(function () use ($server) { // This token is used by the new node the server is being transferred to. It allows // that node to communicate with the old node during the process to initiate the // actual file transfer. @@ -93,7 +79,7 @@ class ServerTransferController extends Controller $this->daemonTransferRepository ->setServer($server) ->setNode($server->transfer->newNode) - ->notify($server, $data, $server->node, $token->toString()); + ->notify($server, $token); }); return new Response('', Response::HTTP_NO_CONTENT); diff --git a/app/Repositories/Wings/DaemonServerRepository.php b/app/Repositories/Wings/DaemonServerRepository.php index 35df86d84..f013ac08c 100644 --- a/app/Repositories/Wings/DaemonServerRepository.php +++ b/app/Repositories/Wings/DaemonServerRepository.php @@ -4,6 +4,7 @@ namespace Pterodactyl\Repositories\Wings; use Webmozart\Assert\Assert; use Pterodactyl\Models\Server; +use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\TransferException; use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; @@ -34,34 +35,34 @@ class DaemonServerRepository extends DaemonRepository * * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException */ - public function create(array $data): void + public function create(bool $startOnCompletion = true): void { Assert::isInstanceOf($this->server, Server::class); try { - $this->getHttpClient()->post( - '/api/servers', - [ - 'json' => $data, - ] - ); - } catch (TransferException $exception) { + $this->getHttpClient()->post('/api/servers', [ + 'json' => [ + 'uuid' => $this->server->uuid, + 'start_on_completion' => $startOnCompletion, + ], + ]); + } catch (GuzzleException $exception) { throw new DaemonConnectionException($exception); } } /** - * Updates details about a server on the Daemon. + * Triggers a server sync on Wings. * * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException */ - public function update(array $data): void + public function sync(): void { Assert::isInstanceOf($this->server, Server::class); try { - $this->getHttpClient()->patch('/api/servers/' . $this->server->uuid, ['json' => $data]); - } catch (TransferException $exception) { + $this->getHttpClient()->post("/api/servers/{$this->server->uuid}/sync"); + } catch (GuzzleException $exception) { throw new DaemonConnectionException($exception); } } @@ -101,26 +102,6 @@ class DaemonServerRepository extends DaemonRepository } } - /** - * By default this function will suspend a server instance on the daemon. However, passing - * "true" as the first argument will unsuspend the server. - * - * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException - */ - public function suspend(bool $unsuspend = false): void - { - Assert::isInstanceOf($this->server, Server::class); - - try { - $this->getHttpClient()->patch( - '/api/servers/' . $this->server->uuid, - ['json' => ['suspended' => !$unsuspend]] - ); - } catch (TransferException $exception) { - throw new DaemonConnectionException($exception); - } - } - /** * Requests the daemon to create a full archive of the server. Once the daemon is finished * they will send a POST request to "/api/remote/servers/{uuid}/archive" with a boolean. diff --git a/app/Repositories/Wings/DaemonTransferRepository.php b/app/Repositories/Wings/DaemonTransferRepository.php index 74a1e3dc7..3939a47cd 100644 --- a/app/Repositories/Wings/DaemonTransferRepository.php +++ b/app/Repositories/Wings/DaemonTransferRepository.php @@ -2,28 +2,31 @@ namespace Pterodactyl\Repositories\Wings; -use Pterodactyl\Models\Node; +use Lcobucci\JWT\Token\Plain; use Pterodactyl\Models\Server; -use GuzzleHttp\Exception\TransferException; +use GuzzleHttp\Exception\GuzzleException; use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; class DaemonTransferRepository extends DaemonRepository { /** - * @throws DaemonConnectionException + * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException */ - public function notify(Server $server, array $data, Node $node, string $token): void + public function notify(Server $server, Plain $token): void { try { $this->getHttpClient()->post('/api/transfer', [ 'json' => [ 'server_id' => $server->uuid, - 'url' => $node->getConnectionAddress() . sprintf('/api/servers/%s/archive', $server->uuid), - 'token' => 'Bearer ' . $token, - 'server' => $data, + 'url' => $server->node->getConnectionAddress() . sprintf('/api/servers/%s/archive', $server->uuid), + 'token' => 'Bearer ' . $token->toString(), + 'server' => [ + 'uuid' => $server->uuid, + 'start_on_completion' => false, + ], ], ]); - } catch (TransferException $exception) { + } catch (GuzzleException $exception) { throw new DaemonConnectionException($exception); } } diff --git a/app/Services/Servers/BuildModificationService.php b/app/Services/Servers/BuildModificationService.php index 9a8c1c3c4..86658c6e8 100644 --- a/app/Services/Servers/BuildModificationService.php +++ b/app/Services/Servers/BuildModificationService.php @@ -33,6 +33,8 @@ class BuildModificationService * BuildModificationService constructor. * * @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $structureService + * @param \Illuminate\Database\ConnectionInterface $connection + * @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository */ public function __construct( ServerConfigurationStructureService $structureService, @@ -56,46 +58,45 @@ class BuildModificationService { $this->connection->beginTransaction(); - $this->processAllocations($server, $data); + /** @var \Pterodactyl\Models\Server $server */ + $server = $this->connection->transaction(function() use ($server, $data) { + $this->processAllocations($server, $data); - if (isset($data['allocation_id']) && $data['allocation_id'] != $server->allocation_id) { - try { - Allocation::query()->where('id', $data['allocation_id'])->where('server_id', $server->id)->firstOrFail(); - } catch (ModelNotFoundException $ex) { - throw new DisplayException('The requested default allocation is not currently assigned to this server.'); + if (isset($data['allocation_id']) && $data['allocation_id'] != $server->allocation_id) { + try { + Allocation::query()->where('id', $data['allocation_id'])->where('server_id', $server->id)->firstOrFail(); + } catch (ModelNotFoundException $ex) { + throw new DisplayException('The requested default allocation is not currently assigned to this server.'); + } } - } - // If any of these values are passed through in the data array go ahead and set - // them correctly on the server model. - $merge = Arr::only($data, ['oom_disabled', 'memory', 'swap', 'io', 'cpu', 'threads', 'disk', 'allocation_id']); + // If any of these values are passed through in the data array go ahead and set + // them correctly on the server model. + $merge = Arr::only($data, ['oom_disabled', 'memory', 'swap', 'io', 'cpu', 'threads', 'disk', 'allocation_id']); - $server->forceFill(array_merge($merge, [ - 'database_limit' => Arr::get($data, 'database_limit', 0) ?? null, - 'allocation_limit' => Arr::get($data, 'allocation_limit', 0) ?? null, - 'backup_limit' => Arr::get($data, 'backup_limit', 0) ?? 0, - ]))->saveOrFail(); + $server->forceFill(array_merge($merge, [ + 'database_limit' => Arr::get($data, 'database_limit', 0) ?? null, + 'allocation_limit' => Arr::get($data, 'allocation_limit', 0) ?? null, + 'backup_limit' => Arr::get($data, 'backup_limit', 0) ?? 0, + ]))->saveOrFail(); - $server = $server->fresh(); + return $server->refresh(); + }); $updateData = $this->structureService->handle($server); // Because Wings always fetches an updated configuration from the Panel when booting // a server this type of exception can be safely "ignored" and just written to the logs. - // Ideally this request succeedes so we can apply resource modifications on the fly - // but if it fails it isn't the end of the world. + // Ideally this request succeedes so we can apply resource modifications on the fly, but + // if it fails we can just continue on as normal. if (!empty($updateData['build'])) { try { - $this->daemonServerRepository->setServer($server)->update([ - 'build' => $updateData['build'], - ]); + $this->daemonServerRepository->setServer($server)->sync(); } catch (DaemonConnectionException $exception) { Log::warning($exception, ['server_id' => $server->id]); } } - $this->connection->commit(); - return $server; } diff --git a/app/Services/Servers/ServerCreationService.php b/app/Services/Servers/ServerCreationService.php index e538e6dde..48fa8cc33 100644 --- a/app/Services/Servers/ServerCreationService.php +++ b/app/Services/Servers/ServerCreationService.php @@ -162,15 +162,10 @@ class ServerCreationService try { $this->daemonServerRepository->setServer($server)->create( - array_merge( - $this->configurationStructureService->handle($server), - [ - 'start_on_completion' => Arr::get($data, 'start_on_completion', false), - ], - ), + Arr::get($data, 'start_on_completion', false) ?? false ); } catch (DaemonConnectionException $exception) { - $this->serverDeletionService->withForce(true)->handle($server); + $this->serverDeletionService->withForce()->handle($server); throw $exception; } diff --git a/app/Services/Servers/SuspensionService.php b/app/Services/Servers/SuspensionService.php index 3c61b1935..f7d0f77b1 100644 --- a/app/Services/Servers/SuspensionService.php +++ b/app/Services/Servers/SuspensionService.php @@ -63,9 +63,9 @@ class SuspensionService 'status' => $isSuspending ? Server::STATUS_SUSPENDED : null, ]); - // Only send the suspension request to wings if the server is not currently being transferred. + // Only trigger a Wings server sync if it is not currently being transferred. if (is_null($server->transfer)) { - $this->daemonServerRepository->setServer($server)->suspend($action === self::ACTION_UNSUSPEND); + $this->daemonServerRepository->setServer($server)->sync(); } }); } diff --git a/resources/scripts/components/server/features/JavaVersionModalFeature.tsx b/resources/scripts/components/server/features/JavaVersionModalFeature.tsx index fb81c07a4..3756b55b0 100644 --- a/resources/scripts/components/server/features/JavaVersionModalFeature.tsx +++ b/resources/scripts/components/server/features/JavaVersionModalFeature.tsx @@ -75,9 +75,9 @@ const JavaVersionModalFeature = () => { return ( setVisible(false)} closeOnBackground={false} showSpinnerOverlay={loading}> -

Invalid Java Version, Update Docker Image?

-

This server is unable to start due to the required java version not being met.

-

By pressing {'"Update Docker Image"'} below you are acknowledging that the docker image this server uses will be changed to a image below that has the Java version you are requesting.

+

Invalid Java version, update Docker image?

+

This server is unable to start due to the required Java version not being met.

+

By pressing {'"Update Docker Image"'} below you are acknowledging that the Docker image this server uses will be changed to an image below that has the Java version you are requesting.

Please select a Java version from the list below.