diff --git a/client/src/pages/AdminPage.jsx b/client/src/pages/AdminPage.jsx index cf4b62e..0d23b93 100644 --- a/client/src/pages/AdminPage.jsx +++ b/client/src/pages/AdminPage.jsx @@ -296,6 +296,14 @@ function MatchAdminCard({ m, run, busy, token, reload, setNotice }) { {current.live?.roundsPlayed != null && Runde {current.live.roundsPlayed + 1}} )} + {m.server?.address && m.server.status !== 'stopped' && ( +
+ Server {m.server.address.host}:{m.server.address.port} + {m.server.address.tvPort && ( + CSTV {m.server.address.host}:{m.server.address.tvPort} + )} +
+ )} {paused && Pausiert} diff --git a/client/src/styles.css b/client/src/styles.css index 87abb8c..3ba7b9a 100644 --- a/client/src/styles.css +++ b/client/src/styles.css @@ -568,3 +568,5 @@ input:focus, select:focus { border-color: var(--link); outline: none; } .host-matches li { padding: 3px 0; border-top: 1px solid var(--line); } .host-disk { font-size: .85rem; color: var(--muted); margin: -2px 0 8px; font-variant-numeric: tabular-nums; } .host-disk.is-low { color: var(--error); font-weight: 600; } +.admin-address { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 8px; font-size: .85rem; } +.admin-address code { font: 500 .85rem ui-monospace, SFMono-Regular, Consolas, monospace; padding: 1px 6px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); } diff --git a/server/src/matchService.js b/server/src/matchService.js index 7c6b597..f4a61d4 100644 --- a/server/src/matchService.js +++ b/server/src/matchService.js @@ -956,6 +956,9 @@ export class MatchService extends EventEmitter { updatedAt: row.updated_at, idleTimeoutMinutes: this.config.idleTimeoutMinutes, }; + if (viewer.isOrganizer && row.host) { + view.address = { host: row.host, port: row.port, tvPort: row.tv_port }; + } const configured = row.status === 'configured'; if (!configured || viewer.role === 'public') return view; diff --git a/server/src/servers/dockerAdapter.js b/server/src/servers/dockerAdapter.js index 261e680..98f26d7 100644 --- a/server/src/servers/dockerAdapter.js +++ b/server/src/servers/dockerAdapter.js @@ -251,7 +251,7 @@ export class DockerHostPool { } /** - * Freier Speicher unter /var/lib/docker auf einem Host, per SSH. Ergebnis wird eine Minute lang + * Freier Speicher auf einem Host, per SSH: dort, wo das Gameserver-Volume liegt. Ergebnis wird eine Minute lang * zwischengespeichert, weil die Admin-Seite alle paar Sekunden abfragt. Ohne ssh:// gibt es null. */ async diskUsage(name) { @@ -265,7 +265,7 @@ export class DockerHostPool { try { const { stdout } = await exec('ssh', [ '-o', 'BatchMode=yes', '-o', 'ConnectTimeout=5', host.dockerHost.slice('ssh://'.length), - 'df -B1 /var/lib/docker 2>/dev/null || df -B1 /', + `df -B1 "$(docker volume inspect ${host.volume} --format '{{with .Options}}{{.device}}{{end}}' 2>/dev/null | grep . || docker volume inspect ${host.volume} --format '{{.Mountpoint}}' 2>/dev/null || echo /var/lib/docker)" 2>/dev/null || df -B1 /var/lib/docker 2>/dev/null || df -B1 /`, ], { timeout: 10_000 }); value = parseDf(stdout.trim().split('\n').pop()); } catch {