No description
  • Less 48.6%
  • Rust 33.1%
  • Vue 12.9%
  • JavaScript 4.7%
  • Dockerfile 0.5%
  • Other 0.1%
Find a file
2026-07-28 03:32:10 +04:00
backend feat: метрики 2026-07-28 01:09:37 +04:00
deploy/grafana feat: метрики 2026-07-28 01:09:37 +04:00
frontend feat: админский токен API и остановка ВМ 2026-07-28 01:09:36 +04:00
.gitignore feat: контейнеризация 2026-07-28 01:09:37 +04:00
Cargo.lock feat: метрики 2026-07-28 01:09:37 +04:00
Cargo.toml Взлетаем 2026-07-28 01:09:31 +04:00
config.toml fix: БОЖЕ Я БОЛЬШЕ НИКОГДА НЕ БУДУ СВЯЗЫВАТЬСЯ С ДОКЕРФАЙЛАМИ 2026-07-28 03:32:10 +04:00
Containerfile fix: БОЖЕ Я БОЛЬШЕ НИКОГДА НЕ БУДУ СВЯЗЫВАТЬСЯ С ДОКЕРФАЙЛАМИ 2026-07-28 03:32:10 +04:00
Justfile Взлетаем 2026-07-28 01:09:31 +04:00
README.md feat: контейнеризация 2026-07-28 01:09:37 +04:00

CloudStack RBD Backup

Внешний сервис резервного копирования для CloudStack VM с дисками в Ceph/RBD.

Зависимости

  • CloudStack — auth/catalog/control-plane: логин, sessionkey, пользователи, проекты, ВМ, тома, stop/start VM.
  • Ceph/RBD — data-plane для снапшотов, экспортов и rollback.
  • KVM/libvirt — только short-lived consistency guard при создании снапшота: suspend/resume или domfsfreeze/domfsthaw.
  • MariaDB — jobs, snapshots, exports, schedules, job_events.

Браузер хранит настоящий CloudStack sessionkey. Бекенд не выпускает собственные токены. Прозрачные CloudStack proxy-команды используют пользовательский ключ сессии.

API

Одна ручка:

GET  /client/api
POST /client/api

Проксируемые CloudStack-команды включают login, logout, listUsers, listProjects, listVirtualMachines, listVolumes, listStoragePools, listApis, listCapabilities и др. Поведение некоторых проксируемых команд модифицировано, также добавлены локальные команды:

  • createRbdSnapshot
  • listRbdSnapshots
  • deleteRbdSnapshot
  • createRbdSnapshotExport
  • listRbdSnapshotExports
  • downloadRbdSnapshotExport
  • rollbackRbdVolumeToSnapshot
  • listRbdJobs
  • createRbdSnapshotSchedule
  • listRbdSnapshotSchedules
  • updateRbdSnapshotSchedule
  • deleteRbdSnapshotSchedule

Основные сценарии

Создание снапшота

createRbdSnapshot volumeid=<volumeid>

Алгоритм:

  1. Проверка пользовательской CloudStack-сессии.
  2. Проверка доступа к тому через CloudStack.
  3. Сохранение backup_jobs=CREATE_SNAPSHOT и rbd_snapshots=CREATING.
  4. Worker забирает job.
  5. Если VM Running и есть host/domain:
    • suspend/resume или fsfreeze/fsthaw через KVM/libvirt.
  6. rbd snap create pool/image@snap.
  7. SUCCESS/FAILED + job_events.

Экспорт снапшота

createRbdSnapshotExport snapshotid=<id> exporttype=FULL|DIFF
  • FULL выполняет rbd export pool/image@snap file.raw.
  • DIFF ищет предыдущий готоый снапшот этого же тома и выполняет rbd export-diff --from-snap previous pool/image@current file.diff.

Скачивание:

downloadRbdSnapshotExport id=<exportid>&sessionkey=<sessionkey>

Перед выдачей файла backend проверяет доступ пользователя к исходному тому.

In-place rollback / восстановление ВМ из снапшота

rollbackRbdVolumeToSnapshot snapshotid=<id> confirm=true autostopvm=true|false

Если autostopvm=false:

  1. VM должна быть уже Stopped.
  2. Worker дополнительно проверяет RBD watchers.
  3. Safety snapshot: rbd snap create pool/image@pre-rollback-.
  4. rbd snap rollback pool/image@snap.

Если autostopvm=true:

  1. CloudStack service API: stopVirtualMachine forced=true.
  2. Ожидание VM state=Stopped.
  3. RBD watchers check.
  4. Safety snapshot.
  5. rbd snap rollback.
  6. CloudStack service API: startVirtualMachine.
  7. Ожидание VM state=Running.

Важно: остановка/запуск при restore выполняются через CloudStack control-plane, не через virsh shutdown/start.

Расписания

Расписание хранится в snapshot_schedules и реально исполняется schedule_worker.

Поддержанные действия:

  • CREATE_SNAPSHOT — создать снапшот;
  • EXPORT_LAST_SNAPSHOT — экспортировать последний READY-снапшот volume;
  • RESTORE_VM_FROM_SNAPSHOT — in-place rollback к указанному snapshot.

Для описания интервалов поддерживается стандартный cron-синтаксис из 5 полей:

minute hour day-of-month month day-of-week

Поддерживаются *, */N, списки A,B,C и точные числа.

Конфигурация

Бекенд читает TOML из CONFIG_PATH или config.toml.

Переменные окружения:

  • LISTEN_ADDR переопределяет [server].listen;
  • CLOUDSTACK_URL переопределяет [cloudstack].api_url;
  • CLOUDSTACK_USER — логин для выполнения административных действий;
  • CLOUDSTACK_KEY — ключ API для выполнения административных действий;
  • CLOUDSTACK_SECRET — секретный ключ CloudStack;
  • DB_URL переопределяет [database].url;
  • CONFIG_PATH — путь к toml;
  • FRONTEND_DIR — путь к собранному фронтенду;
  • LOG_DIR — директория файловых логов;
  • RUST_LOG — уровень трассировки Rust, например info или debug.

Ключи CLOUDSTACK_ используются только внутренними воркерами бекенда после пользовательской авторизации операции. Сейчас они нужны для:

  • stopVirtualMachine/startVirtualMachine при autostopvm=true;
  • запланированных задач;
  • инфраструктурного enrichment, если user API не отдаёт storage/host details.

Пример конфигурации:

[server]
listen = "0.0.0.0:8081"

[cloudstack]
api_url = "http://cloudstack.example/client/api"
timeout_seconds = 30
validate_session_ttl_seconds = 60

[ceph]
cluster = "ceph"
config_path = "/secrets/ceph.conf"
user = "client.cloudstack-rbd-backup"
keyring_path = "/secrets/ceph.client.cloudstack-rbd-backup.keyring"
rbd_bin = "/usr/bin/rbd"
export_dir = "/exports"

[kvm.ssh]
user = "root"
private_key_path = "/secrets/id_ed25519"
known_hosts_path = "/secrets/known_hosts"
connect_timeout_seconds = 10
command_timeout_seconds = 60

[kvm.libvirt]
virsh_bin = "/usr/bin/virsh"
suspend_method = "suspend" # suspend | fsfreeze | domfsfreeze | none
resume_on_failure = true

[database]
url = "mysql://backup:backup@mariadb:3306/cloudstack_rbd_backup"
max_connections = 10

[scheduler]
enabled = true
tick_seconds = 30
worker_concurrency = 2

Логи и наблюдаемость

Логи пишутся одновременно:

stdout/stderr
$LOG_DIR/backend.log.YYYY-MM-DD

В MariaDB пишется timeline jobs в job_events, например:

QUEUED
CLAIMED
KVM_SUSPEND / KVM_FSFREEZE
CEPH_SNAPSHOT_CREATE
RBD_EXPORT
CLOUDSTACK_STOP_VM
RBD_SNAPSHOT_ROLLBACK
CLOUDSTACK_START_VM
SUCCESS / FAILED

Чувствительные параметры (sessionkey, password, apikey, signature, secret) маскируются в request logs.

Container

Containerfile собирает единый контейнер на базе ALT Linux:

Сборка:

podman build -f Containerfile -t cloudstack-rbd-backup:latest .

Пример запуска:

podman run --rm \
  -p 8081:8081 \
  -e CONFIG_PATH=/app/config.toml \
  -e CLOUDSTACK_URL=http://10.0.19.67/client/api \
  -e CLOUDSTACK_USER=backup-service \
  -e CLOUDSTACK_KEY=... \
  -e CLOUDSTACK_SECRET=... \
  -e DB_URL=mysql://backup:backup@mariadb:3306/cloudstack_rbd_backup \
  -v ./secrets:/secrets:ro \
  -v ./exports:/exports:Z \
  -v ./logs:/logs:Z \
  cloudstack-rbd-backup:latest

Если нужно использовать внешний конфиг:

-v ./config.toml:/app/config.toml:ro

Разработка

just backend-run
just frontend-dev
just check