init_db.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/usr/bin/env python3
  2. """Initialise (ou migre) la base de données SQLite. Appelé par les scripts install et upgrade."""
  3. import os
  4. import sqlite3
  5. import sys
  6. config_path = sys.argv[1] if len(sys.argv) > 1 else None
  7. if config_path:
  8. os.environ["BACKUPMANAGER_CONFIG"] = config_path
  9. # Lire DB_PATH directement depuis le fichier de config (sans importer app/SQLAlchemy)
  10. # pour pouvoir migrer le schéma AVANT que l'import de app ne tente de requêter la DB.
  11. _cfg = {}
  12. if config_path and os.path.exists(config_path):
  13. with open(config_path) as _f:
  14. exec(compile(_f.read(), config_path, "exec"), _cfg)
  15. db_path = _cfg.get("DB_PATH") or os.path.join(
  16. os.path.dirname(os.path.abspath(__file__)), "backupmanager.db"
  17. )
  18. # Migrations SQLite directes — avant tout import de SQLAlchemy/app
  19. if os.path.exists(db_path):
  20. _conn = sqlite3.connect(db_path)
  21. _cur = _conn.execute("PRAGMA table_info(jobs)")
  22. existing_cols = {row[1] for row in _cur.fetchall()}
  23. migrations = [
  24. ("destination_id", "ALTER TABLE jobs ADD COLUMN destination_id INTEGER REFERENCES destinations(id)"),
  25. ("remote_instance_id","ALTER TABLE jobs ADD COLUMN remote_instance_id INTEGER REFERENCES remote_instances(id)"),
  26. ]
  27. for col, sql in migrations:
  28. if col not in existing_cols:
  29. _conn.execute(sql)
  30. _conn.commit()
  31. print(f"Migration : colonne {col} ajoutée à jobs.")
  32. # Table many-to-many job_destinations
  33. tables = {r[0] for r in _conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()}
  34. if "job_destinations" not in tables:
  35. _conn.execute("""
  36. CREATE TABLE job_destinations (
  37. id INTEGER PRIMARY KEY AUTOINCREMENT,
  38. job_id INTEGER NOT NULL REFERENCES jobs(id),
  39. dest_type TEXT NOT NULL,
  40. dest_id INTEGER NOT NULL
  41. )
  42. """)
  43. # Migrer les données existantes depuis destination_id / remote_instance_id
  44. if "destination_id" in existing_cols:
  45. for job_id, dest_id, inst_id in _conn.execute(
  46. "SELECT id, destination_id, remote_instance_id FROM jobs"
  47. ).fetchall():
  48. if dest_id:
  49. _conn.execute(
  50. "INSERT INTO job_destinations (job_id, dest_type, dest_id) VALUES (?, 'ssh', ?)",
  51. (job_id, dest_id),
  52. )
  53. if inst_id:
  54. _conn.execute(
  55. "INSERT INTO job_destinations (job_id, dest_type, dest_id) VALUES (?, 'instance', ?)",
  56. (job_id, inst_id),
  57. )
  58. _conn.commit()
  59. print("Migration : table job_destinations créée et données migrées.")
  60. _conn.close()
  61. # Import de app après les migrations — SQLAlchemy peut désormais requêter la DB
  62. from app import app, db
  63. with app.app_context():
  64. db.create_all()
  65. print("Base de données initialisée.")