150 lines
5.3 KiB
Python
150 lines
5.3 KiB
Python
from pathlib import Path
|
|
|
|
from .db import db, utc_now
|
|
|
|
|
|
def _system_timezone() -> str:
|
|
timezone_file = Path("/etc/timezone")
|
|
if timezone_file.exists():
|
|
value = timezone_file.read_text().strip()
|
|
if value:
|
|
return value
|
|
return "UTC"
|
|
|
|
|
|
DEFAULT_SETTINGS = {
|
|
"setup_complete": "false",
|
|
"proxmox_node": "",
|
|
"proxmox_storage": "",
|
|
"local_backup_dir": "/var/lib/vz/dump",
|
|
"rclone_path": "/usr/bin/rclone",
|
|
"rclone_remote": "",
|
|
"rclone_remote_path": "pve-cloud-backup",
|
|
"discord_webhook_url": "",
|
|
"allowed_cors_origins": "http://localhost:5173,http://127.0.0.1:5173",
|
|
"default_compression": "zstd",
|
|
"default_backup_mode": "snapshot",
|
|
"default_retention_type": "days",
|
|
"default_retention_value": "30",
|
|
"max_concurrent_backups": "1",
|
|
"timezone": _system_timezone(),
|
|
}
|
|
|
|
|
|
def run_migrations() -> None:
|
|
with db() as conn:
|
|
conn.execute(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
version INTEGER PRIMARY KEY,
|
|
applied_at TEXT NOT NULL
|
|
)
|
|
"""
|
|
)
|
|
applied = {
|
|
row["version"]
|
|
for row in conn.execute("SELECT version FROM schema_migrations").fetchall()
|
|
}
|
|
if 1 not in applied:
|
|
conn.executescript(
|
|
"""
|
|
CREATE TABLE settings (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE backup_jobs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
guest_vmid INTEGER NOT NULL,
|
|
guest_name TEXT NOT NULL,
|
|
guest_type TEXT NOT NULL CHECK (guest_type IN ('vm','lxc')),
|
|
node TEXT NOT NULL,
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
cron_schedule TEXT NOT NULL,
|
|
proxmox_storage TEXT NOT NULL,
|
|
backup_mode TEXT NOT NULL,
|
|
compression TEXT NOT NULL,
|
|
retention_type TEXT NOT NULL CHECK (retention_type IN ('days','latest')),
|
|
retention_value INTEGER NOT NULL,
|
|
next_run_at TEXT,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE backups (
|
|
id TEXT PRIMARY KEY,
|
|
job_id INTEGER,
|
|
guest_vmid INTEGER NOT NULL,
|
|
guest_name TEXT NOT NULL,
|
|
guest_type TEXT NOT NULL,
|
|
node TEXT NOT NULL,
|
|
state TEXT NOT NULL,
|
|
upid TEXT,
|
|
local_path TEXT,
|
|
remote_path TEXT,
|
|
size_bytes INTEGER,
|
|
error_message TEXT,
|
|
started_at TEXT NOT NULL,
|
|
pve_completed_at TEXT,
|
|
upload_started_at TEXT,
|
|
completed_at TEXT,
|
|
deleted_at TEXT,
|
|
updated_at TEXT NOT NULL,
|
|
FOREIGN KEY (job_id) REFERENCES backup_jobs(id) ON DELETE SET NULL
|
|
);
|
|
|
|
CREATE TABLE notification_logs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
event_type TEXT NOT NULL,
|
|
backup_id TEXT,
|
|
payload TEXT NOT NULL,
|
|
success INTEGER NOT NULL,
|
|
error_message TEXT,
|
|
created_at TEXT NOT NULL,
|
|
FOREIGN KEY (backup_id) REFERENCES backups(id) ON DELETE SET NULL
|
|
);
|
|
|
|
CREATE INDEX idx_backup_jobs_enabled_next_run ON backup_jobs(enabled, next_run_at);
|
|
CREATE INDEX idx_backups_guest_state ON backups(guest_vmid, state);
|
|
CREATE INDEX idx_backups_state ON backups(state);
|
|
"""
|
|
)
|
|
now = utc_now()
|
|
conn.executemany(
|
|
"INSERT INTO settings(key, value, updated_at) VALUES (?, ?, ?)",
|
|
[(key, value, now) for key, value in DEFAULT_SETTINGS.items()],
|
|
)
|
|
conn.execute(
|
|
"INSERT INTO schema_migrations(version, applied_at) VALUES (?, ?)",
|
|
(1, now),
|
|
)
|
|
if 2 not in applied:
|
|
now = utc_now()
|
|
conn.execute(
|
|
"""
|
|
INSERT INTO settings(key, value, updated_at)
|
|
VALUES ('rclone_remote_path', 'pve-cloud-backup', ?)
|
|
ON CONFLICT(key) DO NOTHING
|
|
""",
|
|
(now,),
|
|
)
|
|
conn.execute(
|
|
"INSERT INTO schema_migrations(version, applied_at) VALUES (?, ?)",
|
|
(2, now),
|
|
)
|
|
if 3 not in applied:
|
|
now = utc_now()
|
|
conn.execute(
|
|
"""
|
|
INSERT INTO settings(key, value, updated_at)
|
|
VALUES ('timezone', ?, ?)
|
|
ON CONFLICT(key) DO NOTHING
|
|
""",
|
|
(DEFAULT_SETTINGS["timezone"], now),
|
|
)
|
|
conn.execute(
|
|
"INSERT INTO schema_migrations(version, applied_at) VALUES (?, ?)",
|
|
(3, now),
|
|
)
|