connection = $connection; $this->repository = $repository; $this->allocationRepository = $allocationRepository; $this->nodeRepository = $nodeRepository; $this->daemonServerRepository = $daemonServerRepository; $this->daemonTransferRepository = $daemonTransferRepository; $this->configurationStructureService = $configurationStructureService; $this->suspensionService = $suspensionService; $this->writer = $writer; } /** * The daemon notifies us about the archive status. * * @param \Illuminate\Http\Request $request * @param string $uuid * @return \Illuminate\Http\JsonResponse * * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Throwable */ public function archive(Request $request, string $uuid) { $server = $this->repository->getByUuid($uuid); // Unsuspend the server and don't continue the transfer. if (! $request->input('successful')) { $this->suspensionService->toggle($server, 'unsuspend'); return JsonResponse::create([], Response::HTTP_NO_CONTENT); } $server->node_id = $server->transfer->new_node; $data = $this->configurationStructureService->handle($server); $data['suspended'] = false; $data['service']['skip_scripts'] = true; $allocations = $server->getAllocationMappings(); $data['allocations']['default']['ip'] = array_key_first($allocations); $data['allocations']['default']['port'] = $allocations[$data['allocations']['default']['ip']][0]; $now = Chronos::now(); $signer = new Sha256; $token = (new Builder)->issuedBy(config('app.url')) ->permittedFor($server->node->getConnectionAddress()) ->identifiedBy(hash('sha256', $server->uuid), true) ->issuedAt($now->getTimestamp()) ->canOnlyBeUsedAfter($now->getTimestamp()) ->expiresAt($now->addMinutes(15)->getTimestamp()) ->relatedTo($server->uuid, true) ->getToken($signer, new Key($server->node->daemonSecret)); // On the daemon transfer repository, make sure to set the node after the server // because setServer() tells the repository to use the server's node and not the one // we want to specify. try { $this->daemonTransferRepository ->setServer($server) ->setNode($this->nodeRepository->find($server->transfer->new_node)) ->notify($server, $data, $server->node, $token->__toString()); } catch (DaemonConnectionException $exception) { throw $exception; } return JsonResponse::create([], Response::HTTP_NO_CONTENT); } /** * The daemon notifies us about a transfer failure. * * @param \Illuminate\Http\Request $request * @param string $uuid * @return \Illuminate\Http\JsonResponse * * @throws \Throwable */ public function failure(string $uuid) { $server = $this->repository->getByUuid($uuid); $transfer = $server->transfer; $allocationIds = json_decode($transfer->new_additional_allocations); array_push($allocationIds, $transfer->new_allocation); // Remove the new allocations. $this->allocationRepository->updateWhereIn('id', $allocationIds, ['server_id' => null]); // Unsuspend the server. $this->suspensionService->toggle($server, 'unsuspend'); return JsonResponse::create([], Response::HTTP_NO_CONTENT); } /** * The daemon notifies us about a transfer success. * * @param string $uuid * @return \Illuminate\Http\JsonResponse * * @throws \Throwable */ public function success(string $uuid) { $server = $this->repository->getByUuid($uuid); $transfer = $server->transfer; $allocationIds = json_decode($transfer->old_additional_allocations); array_push($allocationIds, $transfer->old_allocation); // Begin a transaction. $this->connection->beginTransaction(); // Remove the old allocations. $this->allocationRepository->updateWhereIn('id', $allocationIds, ['server_id' => null]); // Update the server's allocation_id and node_id. $server->allocation_id = $transfer->new_allocation; $server->node_id = $transfer->new_node; $server->save(); // Mark the transfer as successful. $transfer->successful = true; $transfer->save(); // Commit the transaction. $this->connection->commit(); // Delete the server from the old node try { $this->daemonServerRepository->setServer($server)->delete(); } catch (DaemonConnectionException $exception) { $this->writer->warning($exception); } // Unsuspend the server $server->load('node'); $this->suspensionService->toggle($server, $this->suspensionService::ACTION_UNSUSPEND); return JsonResponse::create([], Response::HTTP_NO_CONTENT); } }