feat: Initial commit for OnEver Drive centralized backup system with Windows PyQt6 agent and Proxmox LXC deployment

This commit is contained in:
2026-08-13 19:33:44 -03:00
commit 1bfb808c79
77 changed files with 10675 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
import sqlite3
import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional, Dict, Any, List
from agent.config import AGENT_HOME
STATE_DB_PATH = AGENT_HOME / "agent_state.db"
class StateDatabase:
"""Local SQLite database for agent offline resiliency, session resume tracking and file caching."""
def __init__(self, db_path: Path = STATE_DB_PATH):
self.db_path = db_path
self._init_db()
def _get_conn(self) -> sqlite3.Connection:
return sqlite3.connect(str(self.db_path))
def _init_db(self):
with self._get_conn() as conn:
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS upload_sessions (
filepath TEXT PRIMARY KEY,
sha256 TEXT NOT NULL,
session_code TEXT NOT NULL,
total_chunks INTEGER NOT NULL,
chunk_size INTEGER NOT NULL,
completed_chunks INTEGER DEFAULT 0,
status TEXT NOT NULL,
last_updated TIMESTAMP NOT NULL
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS completed_files (
filepath TEXT PRIMARY KEY,
sha256 TEXT NOT NULL,
file_size INTEGER NOT NULL,
job_id INTEGER,
last_backup_time TIMESTAMP NOT NULL
)
""")
conn.commit()
def save_session(
self,
filepath: str,
sha256: str,
session_code: str,
total_chunks: int,
chunk_size: int,
status: str = "UPLOADING"
):
with self._get_conn() as conn:
cursor = conn.cursor()
now = datetime.now(timezone.utc).isoformat()
cursor.execute("""
INSERT OR REPLACE INTO upload_sessions
(filepath, sha256, session_code, total_chunks, chunk_size, status, last_updated)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (filepath, sha256, session_code, total_chunks, chunk_size, status, now))
conn.commit()
def get_session(self, filepath: str) -> Optional[Dict[str, Any]]:
with self._get_conn() as conn:
cursor = conn.cursor()
cursor.execute("SELECT filepath, sha256, session_code, total_chunks, chunk_size, completed_chunks, status FROM upload_sessions WHERE filepath = ?", (filepath,))
row = cursor.fetchone()
if row:
return {
"filepath": row[0],
"sha256": row[1],
"session_code": row[2],
"total_chunks": row[3],
"chunk_size": row[4],
"completed_chunks": row[5],
"status": row[6]
}
return None
def mark_session_completed(self, filepath: str, sha256: str, file_size: int, job_id: Optional[int] = None):
with self._get_conn() as conn:
cursor = conn.cursor()
now = datetime.now(timezone.utc).isoformat()
cursor.execute("DELETE FROM upload_sessions WHERE filepath = ?", (filepath,))
cursor.execute("""
INSERT OR REPLACE INTO completed_files (filepath, sha256, file_size, job_id, last_backup_time)
VALUES (?, ?, ?, ?, ?)
""", (filepath, sha256, file_size, job_id, now))
conn.commit()
def is_file_already_backed_up(self, filepath: str, current_sha256: str) -> bool:
with self._get_conn() as conn:
cursor = conn.cursor()
cursor.execute("SELECT sha256 FROM completed_files WHERE filepath = ?", (filepath,))
row = cursor.fetchone()
if row and row[0] == current_sha256:
return True
return False
state_db = StateDatabase()