forked from pterodactyl/panel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBuildModificationService.php
More file actions
155 lines (132 loc) · 5.98 KB
/
BuildModificationService.php
File metadata and controls
155 lines (132 loc) · 5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php
namespace Pterodactyl\Services\Servers;
use Illuminate\Support\Arr;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Allocation;
use Illuminate\Database\ConnectionInterface;
use Pterodactyl\Exceptions\DisplayException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
class BuildModificationService
{
/**
* @var \Illuminate\Database\ConnectionInterface
*/
private $connection;
/**
* @var \Pterodactyl\Repositories\Wings\DaemonServerRepository
*/
private $daemonServerRepository;
/**
* @var \Pterodactyl\Services\Servers\ServerConfigurationStructureService
*/
private $structureService;
/**
* BuildModificationService constructor.
*
* @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $structureService
* @param \Illuminate\Database\ConnectionInterface $connection
* @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository
*/
public function __construct(
ServerConfigurationStructureService $structureService,
ConnectionInterface $connection,
DaemonServerRepository $daemonServerRepository
) {
$this->daemonServerRepository = $daemonServerRepository;
$this->connection = $connection;
$this->structureService = $structureService;
}
/**
* Change the build details for a specified server.
*
* @param \Pterodactyl\Models\Server $server
* @param array $data
* @return \Pterodactyl\Models\Server
*
* @throws \Throwable
* @throws \Pterodactyl\Exceptions\DisplayException
*/
public function handle(Server $server, array $data)
{
$this->connection->beginTransaction();
$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 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 = $server->fresh();
$updateData = $this->structureService->handle($server);
if (!empty($updateData['build'])) {
$this->daemonServerRepository->setServer($server)->update([
'build' => $updateData['build'],
]);
}
$this->connection->commit();
return $server;
}
/**
* Process the allocations being assigned in the data and ensure they are available for a server.
*
* @param \Pterodactyl\Models\Server $server
* @param array $data
*
* @throws \Pterodactyl\Exceptions\DisplayException
*/
private function processAllocations(Server $server, array &$data)
{
if (empty($data['add_allocations']) && empty($data['remove_allocations'])) {
return;
}
// Handle the addition of allocations to this server. Only assign allocations that are not currently
// assigned to a different server, and only allocations on the same node as the server.
if (! empty($data['add_allocations'])) {
$query = Allocation::query()
->where('node_id', $server->node_id)
->whereIn('id', $data['add_allocations'])
->whereNull('server_id');
// Keep track of all the allocations we're just now adding so that we can use the first
// one to reset the default allocation to.
$freshlyAllocated = $query->pluck('id')->first();
$query->update(['server_id' => $server->id, 'notes' => null]);
}
if (! empty($data['remove_allocations'])) {
foreach ($data['remove_allocations'] as $allocation) {
// If we are attempting to remove the default allocation for the server, see if we can reassign
// to the first provided value in add_allocations. If there is no new first allocation then we
// will throw an exception back.
if ($allocation === ($data['allocation_id'] ?? $server->allocation_id)) {
if (empty($freshlyAllocated)) {
throw new DisplayException(
'You are attempting to delete the default allocation for this server but there is no fallback allocation to use.'
);
}
// Update the default allocation to be the first allocation that we are creating.
$data['allocation_id'] = $freshlyAllocated;
}
}
// Remove any of the allocations we got that are currently assigned to this server on
// this node. Also set the notes to null, otherwise when re-allocated to a new server those
// notes will be carried over.
Allocation::query()->where('node_id', $server->node_id)
->where('server_id', $server->id)
// Only remove the allocations that we didn't also attempt to add to the server...
->whereIn('id', array_diff($data['remove_allocations'], $data['add_allocations'] ?? []))
->update([
'notes' => null,
'server_id' => null,
]);
}
}
}