www/proxmox.php

212 lines
8.6 KiB
PHP
Raw Permalink Normal View History

2026-06-27 21:44:44 +00:00
<?php
require_once __DIR__.'/inc/common.php';
define('PMX_HOST', 'https://192.168.10.150:8006');
define('PMX_USER', 'root@pam');
define('PMX_PASS', 'master2000');
define('PMX_NODE', 'pve');
function pmx_auth(): ?array {
$ch = curl_init(PMX_HOST.'/api2/json/access/ticket');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['username' => PMX_USER, 'password' => PMX_PASS]),
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_TIMEOUT => 6,
]);
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
return $r['data'] ?? null;
}
function pmx_get(string $path, array $auth): ?array {
$ch = curl_init(PMX_HOST.'/api2/json'.$path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_TIMEOUT => 6,
CURLOPT_HTTPHEADER => ['Cookie: PVEAuthCookie='.$auth['ticket']],
]);
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
return $r['data'] ?? null;
}
function fmt_bytes(int $b): string {
if ($b >= 1073741824) return round($b/1073741824, 1).' GB';
if ($b >= 1048576) return round($b/1048576, 1).' MB';
return round($b/1024, 1).' KB';
}
function fmt_uptime(int $s): string {
$d = intdiv($s, 86400); $h = intdiv($s % 86400, 3600); $m = intdiv($s % 3600, 60);
return $d ? "{$d}d {$h}h" : ($h ? "{$h}h {$m}m" : "{$m}m");
}
function pct_color(float $p): string {
if ($p >= 85) return '#f85149';
if ($p >= 60) return '#d29922';
return '#3fb950';
}
$auth = pmx_auth();
$error = null;
$node = $containers = $vms = null;
if (!$auth) {
$error = 'Não foi possível autenticar na API do Proxmox.';
} else {
$node = pmx_get('/nodes/'.PMX_NODE.'/status', $auth);
$storage = pmx_get('/nodes/'.PMX_NODE.'/storage', $auth) ?? [];
$containers = pmx_get('/nodes/'.PMX_NODE.'/lxc', $auth) ?? [];
$vms = pmx_get('/nodes/'.PMX_NODE.'/qemu', $auth) ?? [];
usort($containers, fn($a,$b) => $a['vmid'] <=> $b['vmid']);
usort($vms, fn($a,$b) => $a['vmid'] <=> $b['vmid']);
$storage = array_filter($storage, fn($s) => ($s['active'] ?? 0) && ($s['total'] ?? 0) > 0);
usort($storage, fn($a,$b) => strcmp($a['storage'], $b['storage']));
}
$title = 'Proxmox';
ob_start();
?>
<div class="page-header">
<div>
<div class="breadcrumb"><a href="/painel.php">Painel</a><span class="sep"></span>Proxmox</div>
<h1>Proxmox <span style="color:var(--muted);font-weight:400;font-size:16px"><?= PMX_NODE ?></span></h1>
</div>
<button onclick="location.reload()" class="btn btn-secondary"> Atualizar</button>
</div>
<?php if ($error): ?>
<div class="alert alert-error"> <?= h($error) ?></div>
<?php else: ?>
<?php if ($node):
$cpu_pct = round(($node['cpu'] ?? 0) * 100, 1);
$ram_used = $node['memory']['used'] ?? 0;
$ram_tot = $node['memory']['total'] ?? 1;
$ram_pct = round($ram_used / $ram_tot * 100, 1);
?>
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;margin-bottom:20px">
<?php foreach ([
['CPU', $cpu_pct.'%', $cpu_pct],
['RAM', fmt_bytes($ram_used).' / '.fmt_bytes($ram_tot), $ram_pct],
['Uptime', fmt_uptime($node['uptime'] ?? 0), -1],
] as [$label, $val, $pct]): ?>
<div class="card">
<div class="card-body" style="padding:16px">
<div style="font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px"><?= $label ?></div>
<div style="font-size:18px;font-weight:600;color:<?= $pct >= 0 ? pct_color($pct) : 'var(--text)' ?>"><?= $val ?></div>
<?php if ($pct >= 0): ?>
<div style="margin-top:8px;height:4px;background:var(--surface2);border-radius:2px">
<div style="height:4px;border-radius:2px;background:<?= pct_color($pct) ?>;width:<?= min($pct,100) ?>%"></div>
</div>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php foreach ($storage as $s):
$s_used = $s['used'] ?? 0;
$s_tot = $s['total'] ?? 1;
$s_pct = round($s_used / $s_tot * 100, 1);
?>
<div class="card">
<div class="card-body" style="padding:16px">
<div style="font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px"><?= h($s['storage']) ?></div>
<div style="font-size:18px;font-weight:600;color:<?= pct_color($s_pct) ?>"><?= fmt_bytes($s_used) ?></div>
<div style="font-size:11px;color:var(--muted);margin-top:2px">de <?= fmt_bytes($s_tot) ?></div>
<div style="margin-top:8px;height:4px;background:var(--surface2);border-radius:2px">
<div style="height:4px;border-radius:2px;background:<?= pct_color($s_pct) ?>;width:<?= min($s_pct,100) ?>%"></div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- LXC Containers -->
<?php if ($containers): ?>
<div class="card" style="margin-bottom:20px">
<div class="card-header">
<h2>Containers LXC <span style="color:var(--muted);font-weight:400;font-size:13px">(<?= count($containers) ?>)</span></h2>
</div>
<div class="table-wrap">
<table>
<thead><tr><th>ID</th><th>Nome</th><th>Estado</th><th>CPU</th><th>RAM</th><th>Uptime</th></tr></thead>
<tbody>
<?php foreach ($containers as $c):
$running = ($c['status'] === 'running');
$cpu_p = $running ? round(($c['cpu'] ?? 0) * 100, 1) : 0;
$ram_p = $running && ($c['maxmem'] ?? 0) ? round(($c['mem'] ?? 0) / $c['maxmem'] * 100, 1) : 0;
?>
<tr>
<td style="font-family:monospace;font-size:12px;color:var(--muted)"><?= $c['vmid'] ?></td>
<td style="font-weight:500"><?= h($c['name']) ?></td>
<td><?php if($running):?><span class="badge" style="background:#0d2818;color:#3fb950">running</span><?php else:?><span class="badge" style="background:#1e2733;color:var(--muted)"><?= h($c['status']) ?></span><?php endif;?></td>
<td style="font-size:12px">
<?php if($running):?>
<span style="color:<?= pct_color($cpu_p) ?>"><?= $cpu_p ?>%</span>
<?php else: ?><span style="color:var(--muted)">—</span><?php endif;?>
</td>
<td style="font-size:12px">
<?php if($running && ($c['maxmem']??0)):?>
<span style="color:<?= pct_color($ram_p) ?>"><?= fmt_bytes($c['mem']??0) ?></span>
<span style="color:var(--muted)"> / <?= fmt_bytes($c['maxmem']) ?></span>
<?php else: ?><span style="color:var(--muted)">—</span><?php endif;?>
</td>
<td style="color:var(--muted);font-size:12px"><?= $running ? fmt_uptime($c['uptime']??0) : '—' ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
<!-- VMs -->
<?php if ($vms): ?>
<div class="card">
<div class="card-header">
<h2>VMs <span style="color:var(--muted);font-weight:400;font-size:13px">(<?= count($vms) ?>)</span></h2>
</div>
<div class="table-wrap">
<table>
<thead><tr><th>ID</th><th>Nome</th><th>Estado</th><th>CPU</th><th>RAM</th><th>Uptime</th></tr></thead>
<tbody>
<?php foreach ($vms as $v):
$running = ($v['status'] === 'running');
$cpu_p = $running ? round(($v['cpu'] ?? 0) * 100, 1) : 0;
$ram_p = $running && ($v['maxmem'] ?? 0) ? round(($v['mem'] ?? 0) / $v['maxmem'] * 100, 1) : 0;
?>
<tr>
<td style="font-family:monospace;font-size:12px;color:var(--muted)"><?= $v['vmid'] ?></td>
<td style="font-weight:500"><?= h($v['name']) ?></td>
<td><?php if($running):?><span class="badge" style="background:#0d2818;color:#3fb950">running</span><?php else:?><span class="badge" style="background:#1e2733;color:var(--muted)"><?= h($v['status']) ?></span><?php endif;?></td>
<td style="font-size:12px">
<?php if($running):?><span style="color:<?= pct_color($cpu_p) ?>"><?= $cpu_p ?>%</span>
<?php else: ?><span style="color:var(--muted)">—</span><?php endif;?>
</td>
<td style="font-size:12px">
<?php if($running && ($v['maxmem']??0)):?>
<span style="color:<?= pct_color($ram_p) ?>"><?= fmt_bytes($v['mem']??0) ?></span>
<span style="color:var(--muted)"> / <?= fmt_bytes($v['maxmem']) ?></span>
<?php else: ?><span style="color:var(--muted)">—</span><?php endif;?>
</td>
<td style="color:var(--muted);font-size:12px"><?= $running ? fmt_uptime($v['uptime']??0) : '—' ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
<?php $content = ob_get_clean(); require __DIR__.'/inc/layout.php';