212 lines
8.6 KiB
PHP
212 lines
8.6 KiB
PHP
<?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';
|