repository->getByUuid($uuid); $transfer = $server->transfer; if (is_null($transfer)) { throw new ConflictHttpException('Server is not being transferred.'); } /* @var Node $node */ Assert::isInstanceOf($node = $request->attributes->get('node'), Node::class); // Either node can tell the panel that the transfer has failed. Only the new node // can tell the panel that it was successful. if (! $node->is($transfer->newNode) && ! $node->is($transfer->oldNode)) { throw new HttpForbiddenException('Requesting node does not have permission to access this server.'); } return $this->processFailedTransfer($transfer); } /** * The daemon notifies us about a transfer success. * * @throws \Throwable */ public function success(Request $request, string $uuid): JsonResponse { $server = $this->repository->getByUuid($uuid); $transfer = $server->transfer; if (is_null($transfer)) { throw new ConflictHttpException('Server is not being transferred.'); } /* @var Node $node */ Assert::isInstanceOf($node = $request->attributes->get('node'), Node::class); // Only the new node communicates a successful state to the panel, so we should // not allow the old node to hit this endpoint. if (! $node->is($transfer->newNode)) { throw new HttpForbiddenException('Requesting node does not have permission to access this server.'); } /** @var \Pterodactyl\Models\Server $server */ $server = $this->connection->transaction(function () use ($server, $transfer) { $allocations = array_merge([$transfer->old_allocation], $transfer->old_additional_allocations); // Remove the old allocations for the server and re-assign the server to the new // primary allocation and node. Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]); $server->update([ 'allocation_id' => $transfer->new_allocation, 'node_id' => $transfer->new_node, ]); $server = $server->fresh(); $server->transfer->update(['successful' => true]); return $server; }); // Delete the server from the old node making sure to point it to the old node so // that we do not delete it from the new node the server was transferred to. try { $this->daemonServerRepository ->setServer($server) ->setNode($transfer->oldNode) ->delete(); } catch (DaemonConnectionException $exception) { Log::warning($exception, ['transfer_id' => $server->transfer->id]); } return new JsonResponse([], Response::HTTP_NO_CONTENT); } /** * Release all the reserved allocations for this transfer and mark it as failed in * the database. * * @throws \Throwable */ protected function processFailedTransfer(ServerTransfer $transfer): JsonResponse { $this->connection->transaction(function () use (&$transfer) { $transfer->forceFill(['successful' => false])->saveOrFail(); $allocations = array_merge([$transfer->new_allocation], $transfer->new_additional_allocations); Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]); }); return new JsonResponse([], Response::HTTP_NO_CONTENT); } }