Store SQLite DB on remote host via SCP for persistence
Instead of syncing JSON files back, the SQLite DB itself is now the persistent store on the remote HAProxy host: - Startup: download remote DB via SCP (skip migration if exists) - After writes: upload local DB via SCP (WAL checkpoint first) - JSON sync removed (sync_servers_json, sync_certs_json deleted) New functions: - ssh_ops: remote_download_file(), remote_upload_file() via SCP - db: sync_db_to_remote(), _try_download_remote_db() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -125,6 +125,58 @@ def remote_file_exists(path: str) -> bool:
|
||||
return result.stdout.strip() == "yes"
|
||||
|
||||
|
||||
def _scp_base_cmd() -> list[str]:
|
||||
"""Build base SCP command with options."""
|
||||
cmd = [
|
||||
"scp",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "LogLevel=ERROR",
|
||||
"-o", "BatchMode=yes",
|
||||
"-o", "ConnectTimeout=10",
|
||||
"-P", str(SSH_PORT),
|
||||
]
|
||||
if SSH_KEY:
|
||||
cmd.extend(["-i", SSH_KEY])
|
||||
return cmd
|
||||
|
||||
|
||||
def remote_download_file(remote_path: str, local_path: str) -> bool:
|
||||
"""Download a binary file from the remote host via SCP.
|
||||
|
||||
Args:
|
||||
remote_path: Absolute file path on remote host
|
||||
local_path: Absolute local file path to write to
|
||||
|
||||
Returns:
|
||||
True if downloaded successfully, False if file doesn't exist
|
||||
"""
|
||||
cmd = _scp_base_cmd() + [f"{SSH_USER}@{SSH_HOST}:{remote_path}", local_path]
|
||||
logger.debug("SCP download: %s -> %s", remote_path, local_path)
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=SUBPROCESS_TIMEOUT)
|
||||
if result.returncode != 0:
|
||||
logger.debug("SCP download failed: %s", result.stderr.strip())
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def remote_upload_file(local_path: str, remote_path: str) -> None:
|
||||
"""Upload a binary file to the remote host via SCP.
|
||||
|
||||
Args:
|
||||
local_path: Absolute local file path to upload
|
||||
remote_path: Absolute file path on remote host
|
||||
|
||||
Raises:
|
||||
IOError: If upload fails
|
||||
"""
|
||||
cmd = _scp_base_cmd() + [local_path, f"{SSH_USER}@{SSH_HOST}:{remote_path}"]
|
||||
logger.debug("SCP upload: %s -> %s", local_path, remote_path)
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=SUBPROCESS_TIMEOUT)
|
||||
if result.returncode != 0:
|
||||
raise IOError(f"SCP upload failed: {result.stderr.strip()}")
|
||||
|
||||
|
||||
def run_command(args: list[str], timeout: int = SUBPROCESS_TIMEOUT) -> subprocess.CompletedProcess:
|
||||
"""Execute a command locally or remotely based on REMOTE_MODE.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user