host = $cfg['host']; $this->node = $cfg['node']; $this->tokenId = $cfg['token_id']; $this->tokenSecret = $cfg['token_secret']; $this->timeout = (int)($cfg['timeout'] ?? 15); $this->verifyTls = (bool)($cfg['verify_tls'] ?? true); } public function node(): string { return $this->node; } /** VMID 100-199 => lxc, 200-299 => qemu */ public function typeForVmid(int $vmid): string { if ($vmid >= 100 && $vmid <= 199) return 'lxc'; if ($vmid >= 200 && $vmid <= 299) return 'qemu'; throw new InvalidArgumentException("VMID {$vmid} liegt nicht im ANJUMA Bereich (100-299)."); } public function statusCurrent(int $vmid): array { $type = $this->typeForVmid($vmid); return $this->request('GET', "/nodes/{$this->node}/{$type}/{$vmid}/status/current")['data'] ?? []; } /** action: start|stop|reboot|reset (reset nur qemu sinnvoll) */ public function powerAction(int $vmid, string $action): string { $type = $this->typeForVmid($vmid); $allowed = ['start','stop','reboot','reset']; if (!in_array($action, $allowed, true)) { throw new InvalidArgumentException("Ungültige action: {$action}"); } if ($type === 'lxc' && $action === 'reset') { throw new InvalidArgumentException("reset gibt's praktisch nur für qemu/VMs."); } $res = $this->request('POST', "/nodes/{$this->node}/{$type}/{$vmid}/status/{$action}"); // Proxmox liefert meist UPID als string in data return (string)($res['data'] ?? ''); } private function request(string $method, string $path, array $data = null): array { $url = "https://{$this->host}:8006/api2/json{$path}"; $ch = curl_init($url); $headers = [ "Authorization: PVEAPIToken={$this->tokenId}={$this->tokenSecret}", ]; curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => strtoupper($method), CURLOPT_HTTPHEADER => $headers, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_SSL_VERIFYPEER => $this->verifyTls, CURLOPT_SSL_VERIFYHOST => $this->verifyTls ? 2 : 0, ]); if ($data !== null) { $headers[] = "Content-Type: application/x-www-form-urlencoded"; curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); } $raw = curl_exec($ch); if ($raw === false) { throw new RuntimeException("cURL error: " . curl_error($ch)); } $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $json = json_decode($raw, true); if ($code < 200 || $code >= 300) { $msg = is_array($json) ? json_encode($json) : $raw; throw new RuntimeException("PVE HTTP {$code}: {$msg}"); } return is_array($json) ? $json : []; } public function listLxc(): array { return $this->request('GET', "/nodes/{$this->node}/lxc")['data'] ?? []; } public function listQemu(): array { return $this->request('GET', "/nodes/{$this->node}/qemu")['data'] ?? []; } }