54 lines
2.0 KiB
Python
54 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Copy old Athena dashboard telemetry once, without reading chats or logs.
|
|
|
|
Run before the first Deck dashboard start. SQLite's backup API safely includes
|
|
the source WAL while the old dashboard is still collecting samples.
|
|
"""
|
|
import argparse
|
|
import os
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
REQUIRED = {'meta','samples_raw','samples_hourly','slot_samples_raw',
|
|
'slot_samples_hourly','token_totals','token_hourly','model_events'}
|
|
|
|
|
|
def import_history(source, target):
|
|
source=Path(source)
|
|
target=Path(target)
|
|
if not source.is_file() or target.exists():
|
|
raise ValueError('Quelldatenbank fehlt oder Deck-Ziel existiert bereits; nichts überschrieben.')
|
|
target.parent.mkdir(parents=True,exist_ok=True)
|
|
old=sqlite3.connect('file:'+str(source)+'?mode=ro',uri=True)
|
|
try:
|
|
tables={row[0] for row in old.execute("SELECT name FROM sqlite_master WHERE type='table'")}
|
|
if not REQUIRED<=tables:raise ValueError('Unbekanntes Dashboard-History-Schema.')
|
|
new=sqlite3.connect(target)
|
|
try:
|
|
old.backup(new)
|
|
if new.execute('PRAGMA integrity_check').fetchone()[0]!='ok':
|
|
raise ValueError('Kopierte Datenbank ist beschädigt.')
|
|
counts={table:new.execute('SELECT COUNT(*) FROM '+table).fetchone()[0]
|
|
for table in ('samples_raw','slot_samples_raw','token_hourly','model_events')}
|
|
except Exception:
|
|
new.close()
|
|
target.unlink(missing_ok=True)
|
|
raise
|
|
finally:
|
|
if new: new.close()
|
|
target.chmod(0o600)
|
|
if os.geteuid()==0:
|
|
owner=target.parent.stat()
|
|
os.chown(target,owner.st_uid,owner.st_gid)
|
|
return counts
|
|
finally:
|
|
old.close()
|
|
|
|
|
|
if __name__=='__main__':
|
|
parser=argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('source',type=Path)
|
|
parser.add_argument('target',type=Path)
|
|
args=parser.parse_args()
|
|
print(import_history(args.source,args.target))
|