33namespace Pterodactyl \Http \Controllers \Api \Remote \Servers ;
44
55use Cake \Chronos \Chronos ;
6+ use Illuminate \Database \ConnectionInterface ;
67use Illuminate \Http \JsonResponse ;
78use Illuminate \Http \Request ;
89use Illuminate \Http \Response ;
910use Illuminate \Support \Facades \Log ;
1011use Lcobucci \JWT \Builder ;
1112use Lcobucci \JWT \Signer \Hmac \Sha256 ;
1213use Lcobucci \JWT \Signer \Key ;
14+ use Pterodactyl \Contracts \Repository \AllocationRepositoryInterface ;
15+ use Pterodactyl \Exceptions \Http \Connection \DaemonConnectionException ;
1316use Pterodactyl \Http \Controllers \Controller ;
14- use Pterodactyl \Models \Server ;
1517use Pterodactyl \Repositories \Eloquent \ServerRepository ;
1618use Pterodactyl \Repositories \Eloquent \NodeRepository ;
1719use Pterodactyl \Repositories \Wings \DaemonTransferRepository ;
20+ use Pterodactyl \Services \Servers \ServerConfigurationStructureService ;
21+ use Pterodactyl \Services \Servers \SuspensionService ;
1822
1923class ServerTransferController extends Controller
2024{
25+ /**
26+ * @var \Illuminate\Database\ConnectionInterface
27+ */
28+ private $ connection ;
29+
2130 /**
2231 * @var \Pterodactyl\Repositories\Eloquent\ServerRepository
2332 */
2433 private $ repository ;
2534
35+ /**
36+ * @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface
37+ */
38+ private $ allocationRepository ;
39+
2640 /**
2741 * @var \Pterodactyl\Repositories\Eloquent\NodeRepository
2842 */
@@ -33,21 +47,43 @@ class ServerTransferController extends Controller
3347 */
3448 private $ daemonTransferRepository ;
3549
50+ /**
51+ * @var \Pterodactyl\Services\Servers\ServerConfigurationStructureService
52+ */
53+ private $ configurationStructureService ;
54+
55+ /**
56+ * @var \Pterodactyl\Services\Servers\SuspensionService
57+ */
58+ private $ suspensionService ;
59+
3660 /**
3761 * ServerTransferController constructor.
3862 *
63+ * @param \Illuminate\Database\ConnectionInterface $connection
3964 * @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
65+ * @param \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface $allocationRepository
4066 * @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository
41- * @param DaemonTransferRepository $daemonTransferRepository
67+ * @param \Pterodactyl\Repositories\Wings\DaemonTransferRepository $daemonTransferRepository
68+ * @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $configurationStructureService
69+ * @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
4270 */
4371 public function __construct (
72+ ConnectionInterface $ connection ,
4473 ServerRepository $ repository ,
74+ AllocationRepositoryInterface $ allocationRepository ,
4575 NodeRepository $ nodeRepository ,
46- DaemonTransferRepository $ daemonTransferRepository
76+ DaemonTransferRepository $ daemonTransferRepository ,
77+ ServerConfigurationStructureService $ configurationStructureService ,
78+ SuspensionService $ suspensionService
4779 ) {
80+ $ this ->connection = $ connection ;
4881 $ this ->repository = $ repository ;
82+ $ this ->allocationRepository = $ allocationRepository ;
4983 $ this ->nodeRepository = $ nodeRepository ;
5084 $ this ->daemonTransferRepository = $ daemonTransferRepository ;
85+ $ this ->configurationStructureService = $ configurationStructureService ;
86+ $ this ->suspensionService = $ suspensionService ;
5187 }
5288
5389 /**
@@ -59,17 +95,28 @@ public function __construct(
5995 *
6096 * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
6197 * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
98+ * @throws \Throwable
6299 */
63100 public function archive (Request $ request , string $ uuid )
64101 {
65102 $ server = $ this ->repository ->getByUuid ($ uuid );
66103
67104 // Unsuspend the server and don't continue the transfer.
68105 if (!$ request ->input ('successful ' )) {
69- // $this->suspensionService->toggle($server, 'unsuspend');
106+ $ this ->suspensionService ->toggle ($ server , 'unsuspend ' );
70107 return JsonResponse::create ([], Response::HTTP_NO_CONTENT );
71108 }
72109
110+ $ server ->node_id = $ server ->transfer ->new_node ;
111+
112+ $ data = $ this ->configurationStructureService ->handle ($ server );
113+ $ data ['suspended ' ] = false ;
114+ $ data ['service ' ]['skip_scripts ' ] = true ;
115+
116+ $ allocations = $ server ->getAllocationMappings ();
117+ $ data ['allocations ' ]['default ' ]['ip ' ] = array_key_first ($ allocations );
118+ $ data ['allocations ' ]['default ' ]['port ' ] = $ allocations [$ data ['allocations ' ]['default ' ]['ip ' ]][0 ];
119+
73120 $ now = Chronos::now ();
74121 $ signer = new Sha256 ;
75122
@@ -85,10 +132,92 @@ public function archive(Request $request, string $uuid)
85132 // On the daemon transfer repository, make sure to set the node after the server
86133 // because setServer() tells the repository to use the server's node and not the one
87134 // we want to specify.
88- $ this ->daemonTransferRepository
89- ->setServer ($ server )
90- ->setNode ($ this ->nodeRepository ->find ($ server ->transfer ->new_node ))
91- ->notify ($ server , $ server ->node , $ token ->__toString ());
135+ try {
136+ $ this ->daemonTransferRepository
137+ ->setServer ($ server )
138+ ->setNode ($ this ->nodeRepository ->find ($ server ->transfer ->new_node ))
139+ ->notify ($ server , $ data , $ server ->node , $ token ->__toString ());
140+ } catch (DaemonConnectionException $ exception ) {
141+ throw $ exception ;
142+ }
143+
144+ return JsonResponse::create ([], Response::HTTP_NO_CONTENT );
145+ }
146+
147+ /**
148+ * The daemon notifies us about a transfer failure.
149+ *
150+ * @param \Illuminate\Http\Request $request
151+ * @param string $uuid
152+ * @return \Illuminate\Http\JsonResponse
153+ *
154+ * @throws \Throwable
155+ */
156+ public function failure (string $ uuid )
157+ {
158+ $ server = $ this ->repository ->getByUuid ($ uuid );
159+ $ transfer = $ server ->transfer ;
160+
161+ $ allocationIds = json_decode ($ transfer ->new_additional_allocations );
162+ array_push ($ allocationIds , $ transfer ->new_allocation );
163+
164+ // Begin a transaction.
165+ $ this ->connection ->beginTransaction ();
166+
167+ // Remove the new allocations.
168+ $ this ->allocationRepository ->updateWhereIn ('id ' , $ allocationIds , ['server_id ' => null ]);
169+
170+ // Commit the transaction.
171+ $ this ->connection ->commit ();
172+
173+ // Unsuspend the server.
174+ $ this ->suspensionService ->toggle ($ server , 'unsuspend ' );
175+
176+ return JsonResponse::create ([], Response::HTTP_NO_CONTENT );
177+ }
178+
179+ /**
180+ * The daemon notifies us about a transfer success.
181+ *
182+ * @param string $uuid
183+ * @return \Illuminate\Http\JsonResponse
184+ *
185+ * @throws \Throwable
186+ */
187+ public function success (string $ uuid )
188+ {
189+ $ server = $ this ->repository ->getByUuid ($ uuid );
190+ $ transfer = $ server ->transfer ;
191+
192+ // TODO: Notify old daemon about transfer and get it to remove server files.
193+
194+ $ allocationIds = json_decode ($ transfer ->old_additional_allocations );
195+ array_push ($ allocationIds , $ transfer ->old_allocation );
196+
197+ // Begin a transaction.
198+ $ this ->connection ->beginTransaction ();
199+
200+ // Remove the old allocations.
201+ $ this ->allocationRepository ->updateWhereIn ('id ' , $ allocationIds , ['server_id ' => null ]);
202+
203+ // Update the server's allocation_id and node_id.
204+ $ server ->allocation_id = $ transfer ->new_allocation ;
205+ $ server ->node_id = $ transfer ->new_node ;
206+ $ server ->save ();
207+
208+ // Mark the transfer as successful.
209+ $ transfer ->successful = true ;
210+ $ transfer ->save ();
211+
212+ // Commit the transaction.
213+ $ this ->connection ->commit ();
214+
215+ // Unsuspend the server
216+ $ server ->load ('node ' );
217+ Log::debug (json_encode ($ server ));
218+ Log::debug (json_encode ($ server ->node_id ));
219+ Log::debug (json_encode ($ server ->node ));
220+ $ this ->suspensionService ->toggle ($ server , $ this ->suspensionService ::ACTION_UNSUSPEND );
92221
93222 return JsonResponse::create ([], Response::HTTP_NO_CONTENT );
94223 }
0 commit comments