38 lines
2.9 KiB
Python
38 lines
2.9 KiB
Python
from pathlib import Path
|
|
import datetime, json, os, sqlite3, subprocess, urllib.request
|
|
|
|
root=Path('/mnt/data/ikar_server')
|
|
baseline=root/'rollback/services-before.jsonl'
|
|
before=[json.loads(line) for line in baseline.read_text().splitlines() if line.strip()]
|
|
current={x['Names']:x for x in map(json.loads,subprocess.check_output(['docker','ps','--format','{{json .}}'],text=True).splitlines())}
|
|
protected=[]
|
|
for previous in before:
|
|
name=previous['Names']
|
|
assert current[name]['ID']==previous['ID']
|
|
state=json.loads(subprocess.check_output(['docker','inspect','--format','{{json .State}}',name],text=True))
|
|
assert state['Running']
|
|
started=datetime.datetime.fromisoformat(state['StartedAt'].replace('Z','+00:00')).timestamp()
|
|
assert started<baseline.stat().st_mtime
|
|
health=state.get('Health',{}).get('Status','running')
|
|
assert health in ('running','healthy')
|
|
protected.append({'name':name,'containerId':current[name]['ID'],'health':health,'startedAt':state['StartedAt'],'notRestarted':True})
|
|
|
|
units={name:subprocess.check_output(['systemctl','is-active',name],text=True).strip() for name in ['ikar_server.service','ikar_server-backup.timer','caddy','tb-paper.service']}
|
|
assert all(x=='active' for x in units.values())
|
|
with sqlite3.connect(f'file:{root / "shared/data/ikar.db"}?mode=ro',uri=True) as db:
|
|
assert db.execute('pragma quick_check').fetchone()[0]=='ok'
|
|
messages=db.execute('select count(*) from Messages').fetchone()[0]
|
|
transcripts=db.execute('select count(*) from Messages where IkarTranscriptText is not null').fetchone()[0]
|
|
assert messages>0 and transcripts>0
|
|
health=json.load(urllib.request.urlopen('http://127.0.0.1:5099/health',timeout=15))
|
|
assert health['status']=='ok' and health['backup']=='ok'
|
|
asr=json.loads(subprocess.check_output(['docker','exec','ikar_server_asr','python','-c','import urllib.request; print(urllib.request.urlopen("http://127.0.0.1:8766/health").read().decode())'],text=True))
|
|
assert asr['status']=='ok'
|
|
old_names=set(subprocess.check_output(['docker','ps','-a','--format','{{.Names}}'],text=True).splitlines())
|
|
assert 'ikar-server' not in old_names and 'ikar-turn' not in old_names
|
|
assert all(not Path(p).exists() for p in ['/mnt/data/ikar-deploy','/mnt/data/ikar-data','/mnt/data/ikar-builds'])
|
|
assert os.path.ismount('/mnt/data') and (root/'shared/data/.ikar-volume').is_file()
|
|
report={'server':'ikar_server','externalDisk':'/mnt/data','release':str((root/'current').resolve()),'health':health,'asr':asr,'units':units,'protectedPrograms':protected,'oldInstallationRemoved':True,'rollback':json.loads((root/'rollback/cleanup.json').read_text()),'persistenceAfterServerReplacement':{'databaseIntegrity':'ok','storedMessages':messages,'storedTranscripts':transcripts},'timestamp':datetime.datetime.now(datetime.timezone.utc).isoformat()}
|
|
(root/'verification.json').write_text(json.dumps(report,indent=2))
|
|
print(json.dumps(report))
|