Merge branch 'feature/vmops' into claude/production-system-image-smcxyr

# Conflicts:
#	tests/conftest.py
#	tests/dev_server.py
#	web/app.py
#	web/static/app.css
#	web/static/icons.svg
Этот коммит содержится в:
Claude
2026-09-25 15:03:48 +00:00
родитель a43f96883e 34684634af
Коммит 2b7223f311
19 изменённых файлов: 1400 добавлений и 22 удалений
+6 -10
Просмотреть файл
@@ -21,12 +21,15 @@
{% if s.running %}
<a class="btn btn-primary" href="/vm/{{ vm.name }}/console" target="_blank" rel="noopener">{{ icon('monitor') }}Открыть экран</a>
<form method="post" action="/vm/{{ vm.name }}/shutdown" class="inline-form" data-toast="Машина выключается — это может занять до минуты"><button class="btn">{{ icon('power') }}Выключить</button></form>
{% elif s.raw == 'paused' %}
<form method="post" action="/vm/{{ vm.name }}/ops/resume" class="inline-form" data-toast="Машина продолжает работу"><button class="btn btn-primary">{{ icon('play') }}Продолжить</button></form>
{% else %}
<form method="post" action="/vm/{{ vm.name }}/start" class="inline-form" data-toast="Машина запускается"><button class="btn btn-primary">{{ icon('play') }}Запустить</button></form>
{% endif %}
<details class="menu">
<summary class="btn btn-icon" aria-label="Другие действия">{{ icon('ellipsis') }}</summary>
<div class="menu-list">
{% set ops_name, ops_state, ops_next, ops_hints = vm.name, s.raw, '/vm/' ~ vm.name, true %}{% include "_vm_ops_menu.html" %}
{% if s.running %}
<form method="post" action="/vm/{{ vm.name }}/reboot" data-toast="Машина перезагружается"><button class="menu-item">{{ icon('rotate-cw') }}<span>Перезагрузить<small>Мягкая перезагрузка системы</small></span></button></form>
<form method="post" action="/vm/{{ vm.name }}/destroy" data-confirm="Машина будет выключена сразу, как при отключении питания. Несохранённые данные внутри неё пропадут." data-confirm-title="Выключить принудительно?" data-confirm-button="Выключить" data-toast="Машина выключена" data-toast-tone="warning"><button class="menu-item danger">{{ icon('zap') }}<span>Выключить принудительно<small>Если система зависла</small></span></button></form>
@@ -48,6 +51,7 @@
{% if msg %}{{ alert('success', msg) }}{% endif %}
{% if err %}{{ alert('danger', err) }}{% endif %}
{% endfor %}
{% include "_vm_ops_alerts.html" %}
{% endblock %}
{% block content %}
@@ -98,6 +102,7 @@
</div>
<div class="stack">
{% include "_vm_ops_cards.html" %}
<article class="card">
<div class="card-body stack-sm">
<form method="post" action="/vm/{{ vm.name }}/{{ 'autostart-disable' if vm.autostart_enabled else 'autostart' }}" class="switch-row" data-no-busy data-toast="{{ 'Автозапуск выключен' if vm.autostart_enabled else 'Машина будет запускаться вместе с сервером' }}">
@@ -191,16 +196,7 @@
</div>
</article>
<article class="card">
<div class="card-header"><h2>Диски</h2></div>
<div class="list">
{% for disk in vm.disk_list %}
<div class="list-item"><span class="list-icon">{{ icon('disc-3' if disk.is_cdrom else 'hard-drive') }}</span><div class="grow"><div class="title truncate">{{ disk.name }}</div><div class="meta">{{ disk.label }} · {{ disk.target }}</div></div></div>
{% else %}
<div class="list-item subtle">Дисков не найдено</div>
{% endfor %}
</div>
</article>
{% include "_vm_disks.html" %}
<article class="card">
<div class="card-header"><h2>Сетевые карты</h2></div>