Files

191 строка
8.3 KiB
HTML
Исходник Постоянная ссылка Ответственный История

Этот файл содержит неоднозначные символы Юникода
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ app_name }} Panel</title>
<link rel="stylesheet" href="/static/app.css">
</head>
<body>
<div class="v-layout">
{% include "_sidebar.html" %}
<main class="v-main">
<header class="v-topbar">
<div>
<div class="v-title">Обзор</div>
<div class="v-subtitle">{{ system.hostname }} · {{ system.ip }} · {{ system.time }}</div>
</div>
<div class="top-meta">
<span>user: {{ user }}</span>
<form method="post" action="/logout" class="logout-form"><button class="ghost">Выйти</button></form>
</div>
</header>
{% if update_notice and update_notice.has_update %}
<section class="card update-banner">
<div>
<div class="label">Доступно обновление Virtuality</div>
<div class="value small">{{ update_notice.current_version }} → {{ update_notice.latest_version }}</div>
<div class="muted small-note">Пропущено версий: {{ update_notice.missing_count }} · новых коммитов: {{ update_notice.commit_count }}</div>
</div>
<div class="actions">
<a class="link-pill accent" href="/update">Посмотреть изменения</a>
</div>
</section>
{% endif %}
<section class="grid stats">
<article class="card stat">
<div class="label">Uptime</div>
<div class="value">{{ system.uptime }}</div>
</article>
<article class="card stat">
<div class="label">Load</div>
<div class="value">{{ system.load }}</div>
</article>
<article class="card stat">
<div class="label">Kernel</div>
<div class="value small">{{ system.kernel }}</div>
</article>
<article class="card stat">
<div class="label">VM</div>
<div class="value">{{ vms|length }}</div>
</article>
</section>
<section class="card">
<div class="card-head">
<h2>Виртуальные машины</h2>
<div class="actions">
<a class="link-pill" href="/operations">Операции</a>
<a class="link-pill" href="/logs">Журналы</a>
</div>
</div>
<table class="vm-table">
<thead>
<tr><th>ID</th><th>Name</th><th>IP</th><th>State</th><th>Autostart</th><th>Actions</th></tr>
</thead>
<tbody>
{% for vm in vms %}
{% set is_running = 'running' in vm.state %}
<tr class="vm-row {{ 'is-running' if is_running else 'is-stopped' }}">
<td>{{ vm.id }}</td>
<td class="strong"><a class="table-link" href="/vm/{{ vm.name }}">{{ vm.name }}</a></td>
<td class="strong">{{ vm.ip|default('—') }}</td>
<td><span class="status {{ 'ok' if is_running else 'err' if 'shut' in vm.state else 'warn' }}">{{ vm.state }}</span></td>
<td class="autostart-cell">
{% if vm.autostart_enabled %}
<form method="post" action="/vm/{{ vm.name }}/autostart-disable" class="inline-form">
<button class="status status-button ok" title="Отключить автозапуск">{{ vm.autostart_label|default('enabled') }}</button>
</form>
{% else %}
<form method="post" action="/vm/{{ vm.name }}/autostart" class="inline-form">
<button class="status status-button err" title="Включить автозапуск">{{ vm.autostart_label|default('disabled') }}</button>
</form>
{% endif %}
</td>
<td class="vm-actions-cell">
<div class="vm-actions compact-actions">
<a class="icon-action" href="/vm/{{ vm.name }}" title="Подробнее"><span></span><em>Детали</em></a>
<a class="icon-action accent" href="/vm/{{ vm.name }}/console" target="_blank" rel="noopener" title="Консоль"><span></span><em>Консоль</em></a>
{% if is_running %}
<form method="post" action="/vm/{{ vm.name }}/reboot"><button class="icon-action" title="Перезагрузить"><span></span><em>Reboot</em></button></form>
<form method="post" action="/vm/{{ vm.name }}/shutdown"><button class="icon-action" title="Мягко выключить"><span></span><em>Shutdown</em></button></form>
<form method="post" action="/vm/{{ vm.name }}/destroy"><button class="icon-action danger" title="Принудительно выключить"><span></span><em>Power</em></button></form>
{% else %}
<form method="post" action="/vm/{{ vm.name }}/start"><button class="icon-action success" title="Запустить"><span></span><em>Start</em></button></form>
<form method="post" action="/vm/{{ vm.name }}/delete" onsubmit="return confirm('Удалить VM {{ vm.name }} вместе с дисками?');"><button class="icon-action danger" title="Удалить VM"><span>🗑</span><em>Delete</em></button></form>
{% endif %}
</div>
</td>
</tr>
{% else %}
<tr><td colspan="6" class="muted">Виртуальных машин пока нет</td></tr>
{% endfor %}
</tbody>
</table>
</section>
<section class="grid three dashboard-service-grid">
<article class="card">
<div class="card-head">
<h2>Сервисы</h2>
<span class="pill">systemd</span>
</div>
<div class="services">
{% for name, state in services.items() %}
<div class="service-row">
<span>{{ name }}</span>
<span class="status {{ 'ok' if state == 'active' else 'warn' }}">{{ state }}</span>
</div>
{% endfor %}
</div>
</article>
<article class="card">
<div class="card-head">
<h2>Storage pools</h2>
<span class="pill">libvirt</span>
</div>
<table>
<thead>
<tr><th>Name</th><th>State</th><th>Autostart</th></tr>
</thead>
<tbody>
{% for pool in pools %}
<tr>
<td>{{ pool.name }}</td>
<td><span class="status {{ 'ok' if pool.state == 'active' else 'warn' }}">{{ pool.state }}</span></td>
<td>{{ pool.autostart }}</td>
</tr>
{% else %}
<tr><td colspan="3" class="muted">Storage pools не найдены</td></tr>
{% endfor %}
</tbody>
</table>
</article>
<article class="card">
<div class="card-head">
<h2>Последние операции</h2>
<a class="link-pill" href="/operations">Все операции</a>
</div>
<div class="services">
{% for operation in operations %}
<a class="service-row service-link" href="/operations/{{ operation.id }}">
<span>
<strong>{{ operation.title }}</strong>
<small>{{ operation.created_at }} · {{ operation.message }}</small>
</span>
<span class="status {{ operation_css(operation.status) }}">{{ operation.status }}</span>
</a>
{% else %}
<div class="muted">Операций пока нет.</div>
{% endfor %}
</div>
</article>
</section>
<section class="grid two">
<article class="card">
<div class="card-head">
<h2>Интерфейсы</h2>
<span class="pill">ip -br a</span>
</div>
<pre>{{ network.interfaces }}</pre>
</article>
<article class="card">
<div class="card-head">
<h2>Маршруты</h2>
<span class="pill">ip route</span>
</div>
<pre>{{ network.routes }}</pre>
</article>
</section>
</main>
</div>
<script src="/static/panel.js" defer></script>
</body>
</html>