2026-05-19 04:48:13 +02:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
from django.core.management.base import BaseCommand, CommandError
|
|
|
|
|
|
|
|
|
|
from pobsync.config.load import load_global_config, load_host_config
|
|
|
|
|
from pobsync.paths import PobsyncPaths
|
|
|
|
|
from pobsync_backend.models import GlobalConfig, HostConfig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Command(BaseCommand):
|
|
|
|
|
help = "Import pobsync YAML configs into the Django database."
|
|
|
|
|
|
|
|
|
|
def add_arguments(self, parser) -> None:
|
|
|
|
|
parser.add_argument("--prefix", default=settings.POBSYNC_HOME, help="Pobsync home directory")
|
|
|
|
|
|
|
|
|
|
def handle(self, *args: Any, **options: Any) -> None:
|
|
|
|
|
paths = PobsyncPaths(home=Path(options["prefix"]))
|
|
|
|
|
if not paths.global_config_path.exists():
|
|
|
|
|
raise CommandError(f"Missing global config: {paths.global_config_path}")
|
|
|
|
|
|
|
|
|
|
global_cfg = load_global_config(paths.global_config_path)
|
2026-05-19 05:04:49 +02:00
|
|
|
global_ssh = global_cfg.get("ssh") or {}
|
|
|
|
|
global_rsync = global_cfg.get("rsync") or {}
|
|
|
|
|
global_defaults = global_cfg.get("defaults") or {}
|
|
|
|
|
retention_defaults = global_cfg.get("retention_defaults") or {}
|
2026-05-19 04:48:13 +02:00
|
|
|
GlobalConfig.objects.update_or_create(
|
|
|
|
|
name="default",
|
|
|
|
|
defaults={
|
|
|
|
|
"backup_root": global_cfg["backup_root"],
|
|
|
|
|
"pobsync_home": global_cfg.get("pobsync_home", str(paths.home)),
|
2026-05-19 05:04:49 +02:00
|
|
|
"ssh_user": global_ssh.get("user") or "root",
|
|
|
|
|
"ssh_port": global_ssh.get("port") or 22,
|
|
|
|
|
"ssh_options": global_ssh.get("options") or [],
|
|
|
|
|
"rsync_binary": global_rsync.get("binary") or "rsync",
|
|
|
|
|
"rsync_args": global_rsync.get("args") or [],
|
|
|
|
|
"rsync_extra_args": global_rsync.get("extra_args") or [],
|
|
|
|
|
"rsync_timeout_seconds": global_rsync.get("timeout_seconds") or 0,
|
|
|
|
|
"rsync_bwlimit_kbps": global_rsync.get("bwlimit_kbps") or 0,
|
|
|
|
|
"default_source_root": global_defaults.get("source_root") or "/",
|
|
|
|
|
"default_destination_subdir": global_defaults.get("destination_subdir") or "",
|
|
|
|
|
"excludes_default": global_cfg.get("excludes_default") or [],
|
|
|
|
|
"retention_daily": retention_defaults.get("daily", 14),
|
|
|
|
|
"retention_weekly": retention_defaults.get("weekly", 8),
|
|
|
|
|
"retention_monthly": retention_defaults.get("monthly", 12),
|
|
|
|
|
"retention_yearly": retention_defaults.get("yearly", 0),
|
2026-05-19 04:48:13 +02:00
|
|
|
"data": global_cfg,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
for host_path in sorted(paths.hosts_dir.glob("*.yaml")):
|
|
|
|
|
host_cfg = load_host_config(host_path)
|
2026-05-19 05:04:49 +02:00
|
|
|
host_ssh = host_cfg.get("ssh") or {}
|
|
|
|
|
host_rsync = host_cfg.get("rsync") or {}
|
|
|
|
|
host_retention = host_cfg.get("retention") or {}
|
2026-05-19 04:48:13 +02:00
|
|
|
HostConfig.objects.update_or_create(
|
|
|
|
|
host=host_cfg["host"],
|
|
|
|
|
defaults={
|
|
|
|
|
"address": host_cfg["address"],
|
2026-05-19 05:04:49 +02:00
|
|
|
"ssh_user": host_ssh.get("user") or "",
|
|
|
|
|
"ssh_port": host_ssh.get("port"),
|
|
|
|
|
"source_root": host_cfg.get("source_root") or "",
|
|
|
|
|
"includes": host_cfg.get("includes") or [],
|
|
|
|
|
"excludes_add": host_cfg.get("excludes_add") or [],
|
|
|
|
|
"excludes_replace": host_cfg.get("excludes_replace"),
|
|
|
|
|
"rsync_extra_args": host_rsync.get("extra_args") or [],
|
|
|
|
|
"retention_daily": host_retention.get("daily", 14),
|
|
|
|
|
"retention_weekly": host_retention.get("weekly", 8),
|
|
|
|
|
"retention_monthly": host_retention.get("monthly", 12),
|
|
|
|
|
"retention_yearly": host_retention.get("yearly", 0),
|
2026-05-19 04:48:13 +02:00
|
|
|
"config": host_cfg,
|
|
|
|
|
"enabled": True,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
|
|
self.stdout.write(self.style.SUCCESS(f"Imported global config and {count} host config(s)."))
|