Replace Deck video generation with selected external service lifecycle
This commit is contained in:
+47
-1
@@ -1,6 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Root-owned local helper. Only inventory and fresh Docker install; no generic RPC."""
|
||||
import argparse
|
||||
import re
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
@@ -97,8 +100,51 @@ class Manager:
|
||||
self._checked(['/usr/bin/docker','compose','version','--short'])
|
||||
self._phase('Docker bereit. Keine Anwendungen oder Modelle installiert.','complete')
|
||||
except Exception as exc:self._phase(str(exc) if isinstance(exc,ValueError) else 'Docker-Installation fehlgeschlagen. Hostzustand vor erneutem Versuch prüfen.','failed')
|
||||
def video_configs(self):
|
||||
path=self.state/'video-services.json'
|
||||
if not path.exists():return []
|
||||
if path.is_symlink() or path.stat().st_uid!=0 or path.stat().st_mode&0o022:raise ValueError('Videodienste müssen durch root eingerichtet werden.')
|
||||
configs=json.loads(path.read_text())
|
||||
if not isinstance(configs,list) or len(configs)>20:raise ValueError('Ungültige Dienstliste.')
|
||||
ids=set()
|
||||
for config in configs:
|
||||
if not re.fullmatch('[a-z0-9-]{1,40}',config.get('id','')) or config['id'] in ids or not re.fullmatch('[a-f0-9]{64}',config.get('container_id','')):raise ValueError('Ungültige Dienstzuordnung.')
|
||||
ids.add(config['id'])
|
||||
return configs
|
||||
def video_status(self,config):
|
||||
result=run(['/usr/bin/docker','inspect','--format','{{.State.Running}}',config['container_id']])
|
||||
if result.returncode:return dict(id=config['id'],name=config['name'],running=None,ready=False,api_url=config['api_url'],message='Zugeordneter Container fehlt.')
|
||||
running=result.stdout.strip()=='true';ready=False
|
||||
if running:
|
||||
class NoRedirect(urllib.request.HTTPRedirectHandler):
|
||||
def redirect_request(self,*args,**kwargs):return None
|
||||
try:
|
||||
headers={}
|
||||
if config.get('token_file'):headers['Authorization']='Bearer '+Path(config['token_file']).read_text().strip()
|
||||
request=urllib.request.Request(config['health_url'],headers=headers)
|
||||
with urllib.request.build_opener(NoRedirect).open(request,timeout=2) as response:ready=response.status==200
|
||||
except (OSError,ValueError,urllib.error.URLError):pass
|
||||
return dict(id=config['id'],name=config['name'],running=running,ready=ready,api_url=config['api_url'],message=config.get('message','Original-API des Dienstes.'))
|
||||
def video_inventory(self):return {'services':[self.video_status(config) for config in self.video_configs()]}
|
||||
def video_action(self,ident,start):
|
||||
with self.lock:
|
||||
configs=self.video_configs();config=next((c for c in configs if c['id']==ident),None)
|
||||
if config is None:raise ValueError('Videodienst nicht freigegeben.')
|
||||
status=self.video_status(config)
|
||||
if start and status['running']:return status
|
||||
if start:
|
||||
if any(self.video_status(c)['running'] is not False for c in configs if c['id']!=ident):raise ValueError('Ein anderer Videodienst ist noch aktiv oder nicht prüfbar.')
|
||||
probe=run(['/usr/bin/nvidia-smi','--query-compute-apps=pid','--format=csv,noheader,nounits'])
|
||||
if probe.returncode or probe.stdout.strip():raise ValueError('GPU durch einen anderen Dienst belegt. Deck beendet keine fremden Modelle. Alten Router zuerst freigeben.')
|
||||
result=run(['/usr/bin/docker','start',config['container_id']] if start else ['/usr/bin/docker','stop','--time','30',config['container_id']],timeout=45)
|
||||
if result.returncode:raise ValueError('Videodienst konnte nicht gestartet oder beendet werden.')
|
||||
return self.video_status(config)
|
||||
def dispatch(self,data):
|
||||
if not isinstance(data,dict) or set(data)!={'action'}:raise ValueError('Ungültige Helferanfrage.')
|
||||
if not isinstance(data,dict):raise ValueError('Ungültige Helferanfrage.')
|
||||
if set(data)=={'action','service'} and data['action'] in ('video-start','video-stop'):
|
||||
return self.video_action(data['service'],data['action']=='video-start')
|
||||
if set(data)!={'action'}:raise ValueError('Ungültige Helferanfrage.')
|
||||
if data['action']=='video-status':return self.video_inventory()
|
||||
if data['action']=='status':return self.status()
|
||||
if data['action']=='install':return self.install()
|
||||
raise ValueError('Aktion nicht erlaubt.')
|
||||
|
||||
Reference in New Issue
Block a user