mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-09-10 23:08:43 -06:00
Merge pull request #38 from bunny-lab-io/codex/merge-multiple-databases-into-sqlite3
Use unified SQLite database
This commit is contained in:
@@ -648,18 +648,21 @@ registered_agents: Dict[str, Dict] = {}
|
|||||||
agent_configurations: Dict[str, Dict] = {}
|
agent_configurations: Dict[str, Dict] = {}
|
||||||
latest_images: Dict[str, Dict] = {}
|
latest_images: Dict[str, Dict] = {}
|
||||||
|
|
||||||
# Device database initialization
|
# Database initialization (merged into a single SQLite database)
|
||||||
DB_PATH = os.path.abspath(
|
DB_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "database.db"))
|
||||||
os.path.join(os.path.dirname(__file__), "..", "..", "Databases", "devices.db")
|
|
||||||
)
|
|
||||||
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
|
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
def init_db():
|
def init_db():
|
||||||
|
"""Initialize all required tables in the unified database."""
|
||||||
conn = sqlite3.connect(DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
# Device details table
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS device_details (hostname TEXT PRIMARY KEY, description TEXT, details TEXT)"
|
"CREATE TABLE IF NOT EXISTS device_details (hostname TEXT PRIMARY KEY, description TEXT, details TEXT)"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Activity history table for script/job runs
|
# Activity history table for script/job runs
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
@@ -676,21 +679,8 @@ def init_db():
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
init_db()
|
# Saved device list views
|
||||||
|
|
||||||
# Views database (device list saved views)
|
|
||||||
VIEWS_DB_PATH = os.path.abspath(
|
|
||||||
os.path.join(os.path.dirname(__file__), "..", "..", "Databases", "devices_list_views.db")
|
|
||||||
)
|
|
||||||
os.makedirs(os.path.dirname(VIEWS_DB_PATH), exist_ok=True)
|
|
||||||
|
|
||||||
def init_views_db():
|
|
||||||
conn = sqlite3.connect(VIEWS_DB_PATH)
|
|
||||||
cur = conn.cursor()
|
|
||||||
# Store name, ordered column ids as JSON, and filters as JSON
|
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE IF NOT EXISTS device_list_views (
|
CREATE TABLE IF NOT EXISTS device_list_views (
|
||||||
@@ -703,22 +693,7 @@ def init_views_db():
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
init_views_db()
|
|
||||||
|
|
||||||
# ---------------------------------------------
|
|
||||||
# Sites database (site list + device assignments)
|
|
||||||
# ---------------------------------------------
|
|
||||||
SITES_DB_PATH = os.path.abspath(
|
|
||||||
os.path.join(os.path.dirname(__file__), "..", "..", "Databases", "sites.db")
|
|
||||||
)
|
|
||||||
os.makedirs(os.path.dirname(SITES_DB_PATH), exist_ok=True)
|
|
||||||
|
|
||||||
def init_sites_db():
|
|
||||||
conn = sqlite3.connect(SITES_DB_PATH)
|
|
||||||
cur = conn.cursor()
|
|
||||||
# Sites master table
|
# Sites master table
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
@@ -730,6 +705,7 @@ def init_sites_db():
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
# Device assignments. A device (hostname) can be assigned to at most one site.
|
# Device assignments. A device (hostname) can be assigned to at most one site.
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
@@ -741,10 +717,12 @@ def init_sites_db():
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
init_sites_db()
|
|
||||||
|
init_db()
|
||||||
|
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
# Sites API
|
# Sites API
|
||||||
@@ -764,7 +742,7 @@ def _row_to_site(row):
|
|||||||
@app.route("/api/sites", methods=["GET"])
|
@app.route("/api/sites", methods=["GET"])
|
||||||
def list_sites():
|
def list_sites():
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(SITES_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
@@ -795,7 +773,7 @@ def create_site():
|
|||||||
return jsonify({"error": "name is required"}), 400
|
return jsonify({"error": "name is required"}), 400
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(SITES_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"INSERT INTO sites(name, description, created_at) VALUES (?, ?, ?)",
|
"INSERT INTO sites(name, description, created_at) VALUES (?, ?, ?)",
|
||||||
@@ -833,7 +811,7 @@ def delete_sites():
|
|||||||
if not norm_ids:
|
if not norm_ids:
|
||||||
return jsonify({"status": "ok", "deleted": 0})
|
return jsonify({"status": "ok", "deleted": 0})
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(SITES_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
# Clean assignments first (in case FK ON DELETE CASCADE not enforced)
|
# Clean assignments first (in case FK ON DELETE CASCADE not enforced)
|
||||||
cur.execute(
|
cur.execute(
|
||||||
@@ -867,7 +845,7 @@ def sites_device_map():
|
|||||||
p = part.strip()
|
p = part.strip()
|
||||||
if p:
|
if p:
|
||||||
filter_set.add(p)
|
filter_set.add(p)
|
||||||
conn = sqlite3.connect(SITES_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
if filter_set:
|
if filter_set:
|
||||||
placeholders = ','.join('?' * len(filter_set))
|
placeholders = ','.join('?' * len(filter_set))
|
||||||
@@ -910,7 +888,7 @@ def assign_devices_to_site():
|
|||||||
return jsonify({"error": "hostnames must be a list of strings"}), 400
|
return jsonify({"error": "hostnames must be a list of strings"}), 400
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(SITES_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
# Ensure site exists
|
# Ensure site exists
|
||||||
cur.execute("SELECT 1 FROM sites WHERE id = ?", (site_id,))
|
cur.execute("SELECT 1 FROM sites WHERE id = ?", (site_id,))
|
||||||
@@ -951,7 +929,7 @@ def _row_to_view(row):
|
|||||||
@app.route("/api/device_list_views", methods=["GET"])
|
@app.route("/api/device_list_views", methods=["GET"])
|
||||||
def list_device_list_views():
|
def list_device_list_views():
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(VIEWS_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"SELECT id, name, columns_json, filters_json, created_at, updated_at FROM device_list_views ORDER BY name COLLATE NOCASE ASC"
|
"SELECT id, name, columns_json, filters_json, created_at, updated_at FROM device_list_views ORDER BY name COLLATE NOCASE ASC"
|
||||||
@@ -966,7 +944,7 @@ def list_device_list_views():
|
|||||||
@app.route("/api/device_list_views/<int:view_id>", methods=["GET"])
|
@app.route("/api/device_list_views/<int:view_id>", methods=["GET"])
|
||||||
def get_device_list_view(view_id: int):
|
def get_device_list_view(view_id: int):
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(VIEWS_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"SELECT id, name, columns_json, filters_json, created_at, updated_at FROM device_list_views WHERE id = ?",
|
"SELECT id, name, columns_json, filters_json, created_at, updated_at FROM device_list_views WHERE id = ?",
|
||||||
@@ -999,7 +977,7 @@ def create_device_list_view():
|
|||||||
|
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(VIEWS_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"INSERT INTO device_list_views(name, columns_json, filters_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?)",
|
"INSERT INTO device_list_views(name, columns_json, filters_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?)",
|
||||||
@@ -1054,7 +1032,7 @@ def update_device_list_view(view_id: int):
|
|||||||
params.append(view_id)
|
params.append(view_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(VIEWS_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(f"UPDATE device_list_views SET {', '.join(fields)} WHERE id = ?", params)
|
cur.execute(f"UPDATE device_list_views SET {', '.join(fields)} WHERE id = ?", params)
|
||||||
if cur.rowcount == 0:
|
if cur.rowcount == 0:
|
||||||
@@ -1077,7 +1055,7 @@ def update_device_list_view(view_id: int):
|
|||||||
@app.route("/api/device_list_views/<int:view_id>", methods=["DELETE"])
|
@app.route("/api/device_list_views/<int:view_id>", methods=["DELETE"])
|
||||||
def delete_device_list_view(view_id: int):
|
def delete_device_list_view(view_id: int):
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(VIEWS_DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute("DELETE FROM device_list_views WHERE id = ?", (view_id,))
|
cur.execute("DELETE FROM device_list_views WHERE id = ?", (view_id,))
|
||||||
if cur.rowcount == 0:
|
if cur.rowcount == 0:
|
||||||
|
Reference in New Issue
Block a user