Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php
10284 views
1
<?php
2
3
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
4
5
use Illuminate\Http\Response;
6
use Illuminate\Http\JsonResponse;
7
use Pterodactyl\Models\Allocation;
8
use Illuminate\Support\Facades\Log;
9
use Pterodactyl\Models\ServerTransfer;
10
use Illuminate\Database\ConnectionInterface;
11
use Pterodactyl\Http\Controllers\Controller;
12
use Pterodactyl\Repositories\Eloquent\ServerRepository;
13
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
14
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
15
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
16
17
class ServerTransferController extends Controller
18
{
19
/**
20
* ServerTransferController constructor.
21
*/
22
public function __construct(
23
private ConnectionInterface $connection,
24
private ServerRepository $repository,
25
private DaemonServerRepository $daemonServerRepository,
26
) {
27
}
28
29
/**
30
* The daemon notifies us about a transfer failure.
31
*
32
* @throws \Throwable
33
*/
34
public function failure(string $uuid): JsonResponse
35
{
36
$server = $this->repository->getByUuid($uuid);
37
$transfer = $server->transfer;
38
if (is_null($transfer)) {
39
throw new ConflictHttpException('Server is not being transferred.');
40
}
41
42
return $this->processFailedTransfer($transfer);
43
}
44
45
/**
46
* The daemon notifies us about a transfer success.
47
*
48
* @throws \Throwable
49
*/
50
public function success(string $uuid): JsonResponse
51
{
52
$server = $this->repository->getByUuid($uuid);
53
$transfer = $server->transfer;
54
if (is_null($transfer)) {
55
throw new ConflictHttpException('Server is not being transferred.');
56
}
57
58
/** @var \Pterodactyl\Models\Server $server */
59
$server = $this->connection->transaction(function () use ($server, $transfer) {
60
$allocations = array_merge([$transfer->old_allocation], $transfer->old_additional_allocations);
61
62
// Remove the old allocations for the server and re-assign the server to the new
63
// primary allocation and node.
64
Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]);
65
$server->update([
66
'allocation_id' => $transfer->new_allocation,
67
'node_id' => $transfer->new_node,
68
]);
69
70
$server = $server->fresh();
71
$server->transfer->update(['successful' => true]);
72
73
return $server;
74
});
75
76
// Delete the server from the old node making sure to point it to the old node so
77
// that we do not delete it from the new node the server was transferred to.
78
try {
79
$this->daemonServerRepository
80
->setServer($server)
81
->setNode($transfer->oldNode)
82
->delete();
83
} catch (DaemonConnectionException $exception) {
84
Log::warning($exception, ['transfer_id' => $server->transfer->id]);
85
}
86
87
return new JsonResponse([], Response::HTTP_NO_CONTENT);
88
}
89
90
/**
91
* Release all the reserved allocations for this transfer and mark it as failed in
92
* the database.
93
*
94
* @throws \Throwable
95
*/
96
protected function processFailedTransfer(ServerTransfer $transfer): JsonResponse
97
{
98
$this->connection->transaction(function () use (&$transfer) {
99
$transfer->forceFill(['successful' => false])->saveOrFail();
100
101
$allocations = array_merge([$transfer->new_allocation], $transfer->new_additional_allocations);
102
Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]);
103
});
104
105
return new JsonResponse([], Response::HTTP_NO_CONTENT);
106
}
107
}
108
109