<?phpnamespace App\Feature\Pools;use App\Gui\Units;use App\Model\Connection;use App\Model\Session;use App\Xapi\Rrd;/** * The cards of the Dashboard tab (the root node "XenCenter"): one per connection, with what the cache and the performance figures * say. A card: id (the tree node to select), index (of the connection), name, state, detail, pool (bool), hosts, vms, running, * cpu (0..1 or null: no figures yet), memory (0..1 or null), memoryText, alerts. */final class Dashboard{ /** @param array<int, Rrd> $rrd the figures of each connection (MainForm::$rrd) @return list<array<string, mixed>> */ public static function cards(Session $session, array $rrd): array { $cards = []; foreach ($session->connections as $i => $c) { $cards[] = self::card($c, $i, $rrd[$i] ?? null); } return $cards; } /** @return array<string, mixed> */ public static function card(Connection $c, int $index, ?Rrd $rrd): array { $card = ['index' => $index, 'id' => 'conn:' . $index, 'name' => $c->name(), 'state' => $c->state, 'pool' => false, 'hosts' => 0, 'vms' => 0, 'running' => 0, 'cpu' => null, 'memory' => null, 'memoryText' => '', 'alerts' => 0, 'detail' => match ($c->state) { Connection::CONNECTING => $c->phase ?: 'Connecting…', Connection::FAILED => $c->error, default => $c->profile->host, }]; if (!$c->isConnected()) { return $card; } $cache = $c->cache; $card['pool'] = $cache->isRealPool(); $card['id'] = (string)($card['pool'] ? $cache->poolRef() : $cache->master()); $card['detail'] = $c->profile->host; $hosts = $cache->hosts(); $card['hosts'] = count($hosts); foreach ($cache->vms() as $vm) { $card['vms']++; $card['running'] += $vm['power_state'] === 'Running' ? 1 : 0; } // memory: what the hosts' metrics say; CPU: the last figure of each host's CPUs, weighted by their number $total = $used = 0.0; $cpuSum = 0.0; $cpuCount = 0; foreach ($hosts as $ref => $h) { $m = $cache->hostMemory($ref); $total += $m['total']; $used += $m['used']; if ($rrd !== null) { foreach ($rrd->names('host', (string)$h['uuid']) as $name) { if (preg_match('/^cpu\d+$/', $name)) { $series = $rrd->series('host', (string)$h['uuid'], $name); if ($series !== []) { $cpuSum += (float)end($series)[1]; $cpuCount++; } } } } } $card['cpu'] = $cpuCount > 0 ? $cpuSum / $cpuCount : null; $card['memory'] = $total > 0 ? $used / $total : null; $card['memoryText'] = $total > 0 ? Units::bytes($used) . ' of ' . Units::bytes($total) : ''; $card['alerts'] = count($cache->messages()); return $card; } /** The line over the cards. @param list<array<string, mixed>> $cards */ public static function summary(array $cards): string { if ($cards === []) { return 'No server yet: File > Add New Server… (or Open the Demo Pool).'; } $connected = count(array_filter($cards, fn ($c) => $c['state'] === Connection::CONNECTED)); $hosts = array_sum(array_column($cards, 'hosts')); $vms = array_sum(array_column($cards, 'vms')); $running = array_sum(array_column($cards, 'running')); $alerts = array_sum(array_column($cards, 'alerts')); return "$connected of " . count($cards) . " connected · $hosts servers · $running of $vms VMs running · $alerts alerts"; }}