diff --git a/app/Http/Controllers/Admin/AddressPools/AddressController.php b/app/Http/Controllers/Admin/AddressPools/AddressController.php index e2c4f2409e1..5f287fc98e1 100644 --- a/app/Http/Controllers/Admin/AddressPools/AddressController.php +++ b/app/Http/Controllers/Admin/AddressPools/AddressController.php @@ -48,7 +48,7 @@ public function index(Request $request, AddressPool $addressPool) AllowedFilter::exact('server_id')->nullable(), ], ) - ->paginate(min($request->query('per_page', 50), 100))->appends( + ->paginate(min($request->query('per_page', 50), 999999))->appends( $request->query(), ); diff --git a/app/Http/Controllers/Admin/Nodes/AddressController.php b/app/Http/Controllers/Admin/Nodes/AddressController.php index c7bd5afb942..ff633ec02b3 100644 --- a/app/Http/Controllers/Admin/Nodes/AddressController.php +++ b/app/Http/Controllers/Admin/Nodes/AddressController.php @@ -25,7 +25,7 @@ public function index(Request $request, Node $node) new FiltersAddressWildcard(), ), AllowedFilter::exact('server_id')->nullable()], ) - ->paginate(min($request->query('per_page', 50), 100))->appends( + ->paginate(min($request->query('per_page', 50), 999999))->appends( $request->query(), ); diff --git a/app/Repositories/Proxmox/Server/ProxmoxGuestAgentRepository.php b/app/Repositories/Proxmox/Server/ProxmoxGuestAgentRepository.php new file mode 100644 index 00000000000..d9752f5f2b4 --- /dev/null +++ b/app/Repositories/Proxmox/Server/ProxmoxGuestAgentRepository.php @@ -0,0 +1,61 @@ +server, Server::class); + + $response = $this->getHttpClient() + ->withUrlParameters([ + 'node' => $this->node->cluster, + 'server' => $this->server->vmid, + ]) + ->get('/api2/json/nodes/{node}/qemu/{server}/agent/get-osinfo') + ->json(); + + return $this->getData($response); + } + + /** + * Update Guest Agent password for Administrator user. + * + * @param string $password + * @return mixed + * + * @throws ProxmoxConnectionException + */ + public function updateGuestAgentPassword(string $username, string $password) + { + Assert::isInstanceOf($this->server, Server::class); + + $params = [ + 'username' => $username, + 'password' => $password, + ]; + + $response = $this->getHttpClient() + ->withUrlParameters([ + 'node' => $this->node->cluster, + 'server' => $this->server->vmid, + ]) + ->post('/api2/json/nodes/{node}/qemu/{server}/agent/set-user-password', $params) + ->json(); + + return $this->getData($response); + } +} \ No newline at end of file diff --git a/app/Services/Servers/ServerAuthService.php b/app/Services/Servers/ServerAuthService.php index 590948888e1..cac708546eb 100644 --- a/app/Services/Servers/ServerAuthService.php +++ b/app/Services/Servers/ServerAuthService.php @@ -4,30 +4,45 @@ use Convoy\Models\Server; use Convoy\Repositories\Proxmox\Server\ProxmoxConfigRepository; +use Convoy\Repositories\Proxmox\Server\ProxmoxGuestAgentRepository; +use Illuminate\Support\Str; class ServerAuthService { - public function __construct(private ProxmoxConfigRepository $configRepository) + public function __construct(private ProxmoxConfigRepository $configRepository, private ProxmoxGuestAgentRepository $guestAgentRepository) { } - public function updatePassword(Server $server, string $password) + public function updatePassword(Server $server, string $password): void { - // if (!empty($password)) { + // Always store CIPassword first $this->configRepository->setServer($server)->update(['cipassword' => $password]); - // } else { - // $this->configRepository->setServer($server)->update(['delete' => 'cipassword']); - // } + + try { + $osInfo = $this->guestAgentRepository->setServer($server)->guestAgentOs(); + + // If we have valid OS info, decide which username to use + if (is_array($osInfo) && isset($osInfo['result']['name'])) { + $osName = $osInfo['result']['name']; + $username = Str::contains(Str::lower($osName), 'windows') ? 'Administrator' : 'root'; + + $this->guestAgentRepository + ->setServer($server) + ->updateGuestAgentPassword($username, $password); + } + } catch (\Exception $e) { + // Optionally log or handle exceptions + } } - public function getSSHKeys(Server $server) + public function getSSHKeys(Server $server): string { $raw = collect($this->configRepository->setServer($server)->getConfig())->where('key', '=', 'sshkeys')->first()['value'] ?? ''; return rawurldecode($raw); } - public function updateSSHKeys(Server $server, ?string $keys) + public function updateSSHKeys(Server $server, ?string $keys): void { if (! empty($keys)) { $this->configRepository->setServer($server)->update(['sshkeys' => rawurlencode($keys)]); diff --git a/app/Services/Servers/ServerBuildDispatchService.php b/app/Services/Servers/ServerBuildDispatchService.php index 528d81e78fb..42a6357f2a0 100644 --- a/app/Services/Servers/ServerBuildDispatchService.php +++ b/app/Services/Servers/ServerBuildDispatchService.php @@ -2,20 +2,21 @@ namespace Convoy\Services\Servers; -use Convoy\Models\Server; +use Convoy\Data\Server\Deployments\ServerDeploymentData; +use Convoy\Enums\Server\PowerAction; use Convoy\Enums\Server\State; use Convoy\Enums\Server\Status; -use Illuminate\Support\Facades\Bus; -use Convoy\Enums\Server\PowerAction; -use Convoy\Jobs\Server\SyncBuildJob; use Convoy\Jobs\Server\BuildServerJob; use Convoy\Jobs\Server\DeleteServerJob; use Convoy\Jobs\Server\MonitorStateJob; -use Convoy\Jobs\Server\UpdatePasswordJob; use Convoy\Jobs\Server\SendPowerCommandJob; +use Convoy\Jobs\Server\SyncBuildJob; +use Convoy\Jobs\Server\UpdatePasswordJob; use Convoy\Jobs\Server\WaitUntilVmIsCreatedJob; use Convoy\Jobs\Server\WaitUntilVmIsDeletedJob; -use Convoy\Data\Server\Deployments\ServerDeploymentData; +use Convoy\Models\Server; +use Illuminate\Support\Facades\Bus; +use Illuminate\Support\Str; class ServerBuildDispatchService { @@ -55,26 +56,39 @@ public function rebuild(ServerDeploymentData $deployment): void private function getChainedBuildJobs(ServerDeploymentData $deployment): array { - if ($deployment->should_create_server) { - $jobs = [ + // Base jobs: either create a new server or sync an existing one + $jobs = $deployment->should_create_server + ? [ new BuildServerJob($deployment->server->id, $deployment->template->id), new WaitUntilVmIsCreatedJob($deployment->server->id), new SyncBuildJob($deployment->server->id), - ]; - } else { - $jobs = [ + ] + : [ new SyncBuildJob($deployment->server->id), ]; - } - if (! empty($deployment->account_password)) { - $jobs[] = new UpdatePasswordJob($deployment->server->id, $deployment->account_password); - } + if (Str::contains(Str::lower($deployment->template->name), 'windows')) { + $jobs = [ + ...$jobs, + new SendPowerCommandJob($deployment->server->id, PowerAction::START), + new MonitorStateJob($deployment->server->id, State::RUNNING), + ]; - if ($deployment->start_on_completion) { - $jobs[] = new SendPowerCommandJob($deployment->server->id, PowerAction::START); + if (! empty($deployment->account_password)) { + $jobs[] = new UpdatePasswordJob($deployment->server->id, $deployment->account_password); + } + } else { + // For non-Windows, update password first if provided + if (! empty($deployment->account_password)) { + $jobs[] = new UpdatePasswordJob($deployment->server->id, $deployment->account_password); + } + // Then power on if user wants to start on completion + if ($deployment->start_on_completion) { + $jobs[] = new SendPowerCommandJob($deployment->server->id, PowerAction::START); + } } + // Final callback to clear the status $jobs[] = function () use ($deployment) { Server::findOrFail($deployment->server->id)->update(['status' => null]); };