130 строки
8.3 KiB
HTML
130 строки
8.3 KiB
HTML
{% extends "base.html" %}
|
|
{% from "_ui.html" import icon, badge, meter, empty, alert %}
|
|
{% set page_title = 'Резервные копии' %}
|
|
|
|
{% block page_header %}
|
|
<div class="page-header">
|
|
<div>
|
|
<h1>Резервные копии</h1>
|
|
<p class="lead">Полная копия машины: настройки и все её диски. Из копии можно восстановить машину на этом сервере — под тем же или новым названием.</p>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block alerts %}
|
|
{% if backup_message %}{{ alert('success', backup_message) }}{% endif %}
|
|
{% if backup_error %}{{ alert('danger', backup_error) }}{% endif %}
|
|
{% for op in running %}
|
|
<div class="alert info">{{ icon('activity') }}<div><strong>{{ op.title }} — {{ op.progress|default(0) }}%</strong>{{ op.message }}</div><a class="btn btn-sm alert-action" href="/operations/{{ op.id }}">Следить</a></div>
|
|
{% endfor %}
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<section class="grid grid-3">
|
|
<article class="card stat">
|
|
<div class="stat-head">Копий на сервере<span class="stat-icon">{{ icon('database', 'icon-sm') }}</span></div>
|
|
<div class="stat-value">{{ storage.count }}<small>{{ plural(storage.count, 'копия', 'копии', 'копий') }}</small></div>
|
|
<div class="stat-foot">{{ groups|length }} {{ plural(groups|length, 'машина', 'машины', 'машин') }}</div>
|
|
</article>
|
|
<article class="card stat">
|
|
<div class="stat-head">Занято копиями<span class="stat-icon">{{ icon('hard-drive', 'icon-sm') }}</span></div>
|
|
<div class="stat-value">{{ storage.used }}</div>
|
|
{{ meter(storage.used_pct, 'brand') }}
|
|
<div class="stat-foot">{{ storage.used_pct }}% места на диске сервера</div>
|
|
</article>
|
|
<article class="card stat">
|
|
<div class="stat-head">Свободно для новых копий<span class="stat-icon">{{ icon('layers', 'icon-sm') }}</span></div>
|
|
<div class="stat-value">{{ storage.free }}</div>
|
|
<div class="stat-foot">Перед копированием место проверяется автоматически</div>
|
|
</article>
|
|
</section>
|
|
|
|
<article class="card mt-3" id="schedule">
|
|
<div class="card-header">
|
|
<div class="row">
|
|
<span class="vm-avatar">{{ icon('clock') }}</span>
|
|
<div>
|
|
<h2>Автоматические копии {{ badge('включены', 'success', cls='hide-sm') if schedule.enabled else badge('выключены', 'neutral', False, cls='hide-sm') }}</h2>
|
|
{% if schedule.enabled %}
|
|
<p>{{ schedule.when|capitalize }} · {{ 'все машины' if schedule.all_vms else schedule.vms|join(', ') }} · хранить {{ schedule.keep }} {{ plural(schedule.keep, 'последнюю копию', 'последние копии', 'последних копий') }}</p>
|
|
{% else %}
|
|
<p>Сервер может сам копировать машины каждую ночь или раз в неделю и удалять старые копии.</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<a class="btn btn-sm" href="/backups/schedule">{{ icon('settings', 'icon-sm') }}{{ 'Изменить' if schedule.enabled else 'Настроить' }}</a>
|
|
</div>
|
|
{% if schedule.enabled or schedule.last %}
|
|
<div class="list">
|
|
{% if schedule.enabled %}
|
|
<div class="list-item">
|
|
<span class="list-icon brand">{{ icon('clock') }}</span>
|
|
<div class="grow"><div class="title">Следующая копия: {{ schedule.next }}</div><div class="meta">Работающие машины на время копирования выключаются и потом запускаются снова</div></div>
|
|
</div>
|
|
{% endif %}
|
|
{% if schedule.missed %}
|
|
<div class="list-item">
|
|
<span class="list-icon info">{{ icon('info') }}</span>
|
|
<div class="grow"><div class="title">Копия {{ schedule.missed }} пропущена</div><div class="meta">В это время сервер был выключен, копия будет сделана в следующий раз</div></div>
|
|
</div>
|
|
{% endif %}
|
|
{% if schedule.last %}
|
|
{% set last = schedule.last %}
|
|
<div class="list-item">
|
|
<span class="list-icon {{ 'info' if last.running else 'danger' if last.failed else 'success' }}">{{ icon('activity' if last.running else 'triangle-alert' if last.failed else 'circle-check') }}</span>
|
|
<div class="grow">
|
|
<div class="title">
|
|
{% if last.running %}Идёт копирование по расписанию {{ last.when }}: готово {{ last.count }}
|
|
{% elif not last.count %}Запуск {{ last.when }}: машин для копирования не было
|
|
{% else %}Запуск {{ last.when }}: скопировано {{ last.ok }} из {{ last.count }} {{ plural(last.count, 'машины', 'машин', 'машин') }}{% endif %}
|
|
</div>
|
|
{% for item in last.failed %}<div class="meta"><strong>{{ item.vm }}</strong>: {{ item.message }}</div>{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</article>
|
|
|
|
{% if groups %}
|
|
<div class="stack mt-3">
|
|
{% for g in groups %}
|
|
<article class="card">
|
|
<div class="card-header">
|
|
<div class="row">
|
|
<span class="vm-avatar">{{ icon('monitor') }}</span>
|
|
<div>
|
|
<h2>{% if g.exists %}<a href="/vm/{{ g.vm }}" style="color:inherit">{{ g.vm }}</a>{% else %}{{ g.vm }}{% endif %}{% if not g.exists %} {{ badge('машина удалена', 'warning', cls='hide-sm') }}{% endif %}</h2>
|
|
<p>{{ g.count }} {{ plural(g.count, 'копия', 'копии', 'копий') }} · {{ g.size }}{% if not g.exists %} · машины больше нет на сервере, но её можно восстановить{% endif %}</p>
|
|
</div>
|
|
</div>
|
|
{% if g.exists %}<a class="btn btn-sm" href="/vm/{{ g.vm }}/backups">{{ icon('plus', 'icon-sm') }}Создать копию</a>{% endif %}
|
|
</div>
|
|
<div class="list">
|
|
{% with rows = g.backups, back = '/backups' %}{% include "_backup_rows.html" %}{% endwith %}
|
|
</div>
|
|
</article>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<article class="card mt-3">
|
|
{{ empty('database', 'Копий пока нет', 'Откройте страницу машины, перейдите на вкладку «Резервные копии» и нажмите «Создать копию». Копирование идёт в фоне — страницу можно закрыть.', '/', 'К списку машин', 'monitor') }}
|
|
</article>
|
|
{% endif %}
|
|
|
|
<section class="grid grid-2 mt-3">
|
|
<article class="card">
|
|
<div class="card-body stack-sm">
|
|
<div class="row">{{ icon('shield-check') }}<h3>Что входит в копию</h3></div>
|
|
<p class="muted small">Настройки машины (процессор, память, сеть, порядок загрузки) и все её диски целиком. Установочные образы (ISO) не копируются — они лежат отдельно в разделе «Образы ОС». Диски сжимаются, поэтому копия обычно меньше самой машины.</p>
|
|
</div>
|
|
</article>
|
|
<article class="card">
|
|
<div class="card-body stack-sm">
|
|
<div class="row">{{ icon('info') }}<h3>Как это работает</h3></div>
|
|
<p class="muted small">Работающая машина на время копирования аккуратно выключается и потом запускается снова. При восстановлении машина создаётся выключенной: под новым названием — с новыми сетевыми адресами, чтобы не мешать оригиналу; при замене — с прежними. Копии хранятся в папке <code>/var/lib/virtuality/backups</code>. Копии по расписанию сервер удаляет сам, оставляя последние. Копии, сделанные вручную, лежат, пока вы их не удалите.</p>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
{% endblock %}
|