From 2b5cc99abd4131a98e7880dd45197c2c74853ff5 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sat, 30 Jan 2021 12:46:27 -0700 Subject: [PATCH] feat(database-hosts): allow linking of multiple nodes --- .../Api/Client/Servers/DatabaseController.php | 23 ++-------- app/Models/Node.php | 11 +++++ .../Databases/DeployServerDatabaseService.php | 26 +++++------ ...database_host_id_column_to_nodes_table.php | 46 +++++++++++++++++++ 4 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 database/migrations/2021_01_30_193343_add_database_host_id_column_to_nodes_table.php diff --git a/app/Http/Controllers/Api/Client/Servers/DatabaseController.php b/app/Http/Controllers/Api/Client/Servers/DatabaseController.php index 4f9aed59d..dad7a4eae 100644 --- a/app/Http/Controllers/Api/Client/Servers/DatabaseController.php +++ b/app/Http/Controllers/Api/Client/Servers/DatabaseController.php @@ -18,25 +18,10 @@ use Pterodactyl\Http\Requests\Api\Client\Servers\Databases\RotatePasswordRequest class DatabaseController extends ClientApiController { - /** - * @var \Pterodactyl\Services\Databases\DeployServerDatabaseService - */ - private $deployDatabaseService; - - /** - * @var \Pterodactyl\Repositories\Eloquent\DatabaseRepository - */ - private $repository; - - /** - * @var \Pterodactyl\Services\Databases\DatabaseManagementService - */ - private $managementService; - - /** - * @var \Pterodactyl\Services\Databases\DatabasePasswordService - */ - private $passwordService; + private DeployServerDatabaseService $deployDatabaseService; + private DatabaseRepository $repository; + private DatabaseManagementService $managementService; + private DatabasePasswordService $passwordService; /** * DatabaseController constructor. diff --git a/app/Models/Node.php b/app/Models/Node.php index a41689c1c..29020b59b 100644 --- a/app/Models/Node.php +++ b/app/Models/Node.php @@ -28,6 +28,7 @@ use Illuminate\Contracts\Encryption\Encrypter; * @property int $daemonListen * @property int $daemonSFTP * @property string $daemonBase + * @property int|null $database_host_id * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at * @property \Pterodactyl\Models\Location $location @@ -239,6 +240,16 @@ class Node extends Model return $this->hasMany(Allocation::class); } + /** + * Gets the database host associated with a node. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function databaseHost() + { + return $this->belongsTo(DatabaseHost::class); + } + /** * Returns a boolean if the node is viable for an additional server to be placed on it. */ diff --git a/app/Services/Databases/DeployServerDatabaseService.php b/app/Services/Databases/DeployServerDatabaseService.php index 3946cb83f..2004d1569 100644 --- a/app/Services/Databases/DeployServerDatabaseService.php +++ b/app/Services/Databases/DeployServerDatabaseService.php @@ -10,10 +10,7 @@ use Pterodactyl\Exceptions\Service\Database\NoSuitableDatabaseHostException; class DeployServerDatabaseService { - /** - * @var \Pterodactyl\Services\Databases\DatabaseManagementService - */ - private $managementService; + private DatabaseManagementService $managementService; /** * ServerDatabaseCreationService constructor. @@ -35,21 +32,22 @@ class DeployServerDatabaseService Assert::notEmpty($data['database'] ?? null); Assert::notEmpty($data['remote'] ?? null); - $hosts = DatabaseHost::query()->get()->toBase(); - if ($hosts->isEmpty()) { - throw new NoSuitableDatabaseHostException(); - } else { - $nodeHosts = $hosts->where('node_id', $server->node_id)->toBase(); - - if ($nodeHosts->isEmpty() && !config('pterodactyl.client_features.databases.allow_random')) { + $databaseHostId = $server->node->database_host_id; + if (is_null($databaseHostId)) { + if (!config('pterodactyl.client_features.databases.allow_random')) { throw new NoSuitableDatabaseHostException(); } + + $hosts = DatabaseHost::query()->get()->toBase(); + if ($hosts->isEmpty()) { + throw new NoSuitableDatabaseHostException(); + } + + $databaseHostId = $hosts->random()->id; } return $this->managementService->create($server, [ - 'database_host_id' => $nodeHosts->isEmpty() - ? $hosts->random()->id - : $nodeHosts->random()->id, + 'database_host_id' => $databaseHostId, 'database' => DatabaseManagementService::generateUniqueDatabaseName($data['database'], $server->id), 'remote' => $data['remote'], ]); diff --git a/database/migrations/2021_01_30_193343_add_database_host_id_column_to_nodes_table.php b/database/migrations/2021_01_30_193343_add_database_host_id_column_to_nodes_table.php new file mode 100644 index 000000000..31b569f88 --- /dev/null +++ b/database/migrations/2021_01_30_193343_add_database_host_id_column_to_nodes_table.php @@ -0,0 +1,46 @@ +dropForeign(['node_id']); + $table->dropColumn('node_id'); + }); + + Schema::table('nodes', function (Blueprint $table) { + $table->integer('database_host_id')->nullable()->unsigned()->after('daemonBase'); + $table->index('database_host_id')->nullable(); + $table->foreign('database_host_id')->references('id')->on('database_hosts')->onDelete('set null'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('nodes', function (Blueprint $table) { + $table->dropForeign(['database_host_id']); + $table->dropColumn('database_host_id'); + }); + + Schema::table('database_hosts', function (Blueprint $table) { + $table->integer('node_id')->nullable()->unsigned()->after('max_databases'); + $table->index('node_id')->nullable(); + $table->foreign('node_id')->references('id')->on('nodes'); + }); + } +}