initial commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
function nextInvoiceNo(PDO $pdo, int $year): string {
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
// row lock (InnoDB)
|
||||
$stmt = $pdo->prepare("SELECT last_number FROM invoice_counters WHERE year = :y FOR UPDATE");
|
||||
$stmt->execute([':y' => $year]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$row) {
|
||||
$last = 0;
|
||||
$pdo->prepare("INSERT INTO invoice_counters (year, last_number) VALUES (:y, 0)")
|
||||
->execute([':y' => $year]);
|
||||
} else {
|
||||
$last = (int)$row['last_number'];
|
||||
}
|
||||
|
||||
$next = $last + 1;
|
||||
$pdo->prepare("UPDATE invoice_counters SET last_number = :n WHERE year = :y")
|
||||
->execute([':n' => $next, ':y' => $year]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
return sprintf("RE-%d-%04d", $year, $next);
|
||||
} catch (Throwable $e) {
|
||||
$pdo->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
final class PveApi {
|
||||
private string $host;
|
||||
private string $node;
|
||||
private string $tokenId;
|
||||
private string $tokenSecret;
|
||||
private int $timeout;
|
||||
private bool $verifyTls;
|
||||
|
||||
public function __construct(array $cfg) {
|
||||
$this->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'] ?? [];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user