Admin: Spieldateien auf allen Hosts per SteamCMD aktualisieren, mit Prozentanzeige

Ein kurzlebiger Container je Host aktualisiert CS2 im Spieldateien-Volume. Hosts mit
laufenden Servern werden ausgelassen (erzwingbar), während des Updates startet dort
kein neuer Server. Fertig nur, wenn Steam die App als vollständig installiert meldet.
This commit is contained in:
mregosar committed 2026-11-01 18:22:23 +01:00
1 parent 2c57b8c170
commit 3c5a9b4162
7 files changed
+281 -5

No files matched your search

+55 -3
View File
@@ -685,13 +685,15 @@ function DockerHostsPanel({ token, setNotice }) {
// Während das Image lädt, alle 3 Sekunden den Stand holen (ohne die bearbeiteten Zeilen zu überschreiben)
const pulling = !!data?.pull?.running;
const updating = !!data?.files?.running;
const [forceFiles, setForceFiles] = useState(false);
useEffect(() => {
if (!pulling) return undefined;
if (!pulling && !updating) return undefined;
const timer = setInterval(() => {
load().then((res) => setData((d) => ({ ...d, pull: res.pull }))).catch(() => {});
load().then((res) => setData((d) => ({ ...d, pull: res.pull, files: res.files }))).catch(() => {});
}, 3000);
return () => clearInterval(timer);
}, [pulling, load]);
}, [pulling, updating, load]);
if (!data) return null;
if (!data.editable) {
@@ -742,6 +744,14 @@ function DockerHostsPanel({ token, setNotice }) {
run(() => api('/admin/docker-hosts', { method: 'DELETE', token }), 'Hosts aus der .env aktiv');
};
const updateFiles = () => {
const warn = forceFiles
? 'Spieldateien auf ALLEN Hosts aktualisieren, auch wo Server laufen? Laufende Server können dabei abstürzen.'
: 'Spieldateien auf allen Hosts ohne laufende Server aktualisieren?';
if (!window.confirm(warn)) return;
run(() => api('/admin/docker-hosts/update-files', { method: 'POST', body: { force: forceFiles }, token }));
};
const pull = () => {
if (!window.confirm(`Image ${data.image} auf allen Hosts neu laden? Laufende Server laufen weiter.`)) return;
run(() => api('/admin/docker-hosts/pull', { method: 'POST', token }));
@@ -799,9 +809,51 @@ function DockerHostsPanel({ token, setNotice }) {
)}
</ul>
)}
<h3>Spieldateien aktualisieren</h3>
<p className="small muted">
Holt das neueste CS2-Update per SteamCMD in das Volume jedes Hosts. Das Image-Update oben reicht dafür nicht.
Hosts mit laufenden Servern werden ausgelassen, damit niemandem die Dateien unter dem laufenden Server ausgetauscht werden.
Bestehende Server nutzen die neuen Dateien erst nach einem Neustart.
</p>
<div className="admin-actions">
<button className="btn btn-sm btn-primary" disabled={busy || updating || dirty} onClick={updateFiles}>
{updating ? filesLabel(data.files) : 'Spieldateien aktualisieren'}
</button>
<label className="admin-check small">
<input type="checkbox" checked={forceFiles} onChange={(e) => setForceFiles(e.target.checked)} disabled={updating} />
auch Hosts mit laufenden Servern
</label>
</div>
{data.files?.results?.length > 0 && (
<ul className="pull-results">
{data.files.results.map((r) => (
<li key={r.name} className={`pull-${r.state === 'skipped' ? 'skipped' : r.state}`}>
<strong>{r.name}</strong>
<span>{r.state === 'running' ? 'läuft' : r.state === 'ok' ? 'fertig' : r.state === 'skipped' ? 'ausgelassen' : 'fehlgeschlagen'}</span>
{r.message && <code className="small">{r.message}</code>}
{r.state === 'running' && r.progress != null && (
<span className="files-bar" role="progressbar" aria-valuenow={Math.round(r.progress)} aria-valuemin={0} aria-valuemax={100}>
<i style={{ width: `${Math.min(100, r.progress)}%` }} />
</span>
)}
</li>
))}
{data.files.finishedAt && (
<li className="small muted">Zuletzt fertig: {new Date(data.files.finishedAt).toLocaleString('de-DE')}</li>
)}
</ul>
)}
</section>
);
}
/** Knopftext während des Spieldateien-Updates: "Update läuft 43 %" (niedrigster Stand der laufenden Hosts) */
function filesLabel(files) {
const running = files?.results?.filter((r) => r.state === 'running') ?? [];
const known = running.filter((r) => r.progress != null).map((r) => r.progress);
return known.length ? `Update läuft ${Math.floor(Math.min(...known))} %` : 'Update läuft …';
}
/** Datum und Uhrzeit auf Deutsch, z. B. 29.10.2026, 12:54 Uhr */
function formatDateTime(ms) {
return `${new Date(ms).toLocaleString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })} Uhr`;