PL
games/xencenter-xenadmin-xcp-jumphp / src / Xapi / Fake / AlertsOps.php · commit fb1b7c9
<?phpnamespace App\Xapi\Fake;use App\Xapi\Perfmon;use App\Xapi\Rrd;/** * perfmon in the demo pool (part of FakeXapi): every 5 s the alarms of the "perfmon" key of the VMs', hosts' and SRs' other_config * are checked against the same figures /rrd_updates gives; a value over its level for the trigger period makes a message ALARM * whose body is what XAPI writes ("value: 0.953000\nconfig:\n<variable>…"), then nothing for the inhibit period. The demo VM * db-primary comes with a CPU alarm (over 30% for a minute), so the Alerts fill up while the demo runs. */trait AlertsOps{    /** @var array<string, array{above: float, quiet: float}> "ref variable" => seconds over the level, fake time until another alarm may come */    private array $alarmState = [];    private float $alarmsIn = 5.0;    private float $alarmsElapsed = 0.0;    private function buildAlerts(): void    {        foreach ($this->db['vm'] as $ref => $vm) {            if ($vm['name_label'] === 'db-primary') {                $other = (array)$vm['other_config'];                $other['perfmon'] = Perfmon::build(['cpu_usage' => ['level' => 0.3, 'period' => 60, 'inhibit' => 3600]]);                $this->db['vm'][$ref]['other_config'] = $other;            }        }    }    private function pollAlerts(float $dt): void    {        $this->alarmsIn -= $dt;        $this->alarmsElapsed += $dt;        if ($this->alarmsIn > 0) {            return;        }        $elapsed = $this->alarmsElapsed;        $this->alarmsIn = 5.0;        $this->alarmsElapsed = 0.0;        $watched = [];        foreach (['vm' => 'VM', 'host' => 'Host', 'sr' => 'SR'] as $class => $cls) {            foreach ($this->db[$class] ?? [] as $ref => $record) {                $xml = (string)($record['other_config']['perfmon'] ?? '');                if ($xml !== '' && ($class !== 'vm' || ($record['power_state'] === 'Running' && empty($record['is_a_template'])))) {                    $watched[] = [$class, $cls, $ref, $record, Perfmon::parse($xml)];                }            }        }        if ($watched === []) {            return;        }        $rrd = Rrd::parse($this->rrdXml($this->now + (int)$this->clock - 30, true, null));        foreach ($watched as [$class, $cls, $ref, $record, $alarms]) {            foreach ($alarms as $name => $alarm) {                $value = $this->perfmonValue($rrd, $class, $record, $name);                $key = "$ref $name";                $state = $this->alarmState[$key] ?? ['above' => 0.0, 'quiet' => 0.0];                $state['quiet'] = max(0.0, $state['quiet'] - $elapsed);                $state['above'] = $value !== null && Perfmon::fires($name, $value, $alarm['level']) ? $state['above'] + $elapsed : 0.0;                if ($value !== null && $state['above'] >= $alarm['period'] && $state['quiet'] <= 0) {                    $this->add('message', ['name' => 'ALARM', 'priority' => 3, 'cls' => $cls, 'obj_uuid' => $record['uuid'], 'timestamp' => $this->date(),                        'body' => Perfmon::alarmBody($name, $value, $alarm)]);                    $state = ['above' => 0.0, 'quiet' => (float)$alarm['inhibit']];                }                $this->alarmState[$key] = $state;            }        }    }    /** The figure perfmon compares: from the RRD (CPU, network, disks, free memory) or the record (storage used). @param array<string, mixed> $record */    private function perfmonValue(Rrd $rrd, string $class, array $record, string $name): ?float    {        $last = function (string $kind, string $pattern) use ($rrd, $record): array {            $values = [];            foreach ($rrd->names($kind, (string)$record['uuid']) as $n) {                if (preg_match($pattern, $n)) {                    $series = $rrd->series($kind, (string)$record['uuid'], $n);                    if ($series !== []) {                        $values[] = (float)end($series)[1];                    }                }            }            return $values;        };        return match ("$class $name") {            'vm cpu_usage', 'host cpu_usage' => ($v = $last($class, '/^cpu\d+$/')) === [] ? null : array_sum($v) / count($v),            'vm network_usage' => ($v = $last('vm', '/^vif_\d+_(rx|tx)$/')) === [] ? null : array_sum($v),            'vm disk_usage' => ($v = $last('vm', '/^vbd_\w+_(read|write)$/')) === [] ? null : array_sum($v),            'host network_usage' => ($v = $last('host', '/^pif_\w+_(rx|tx)$/')) === [] ? null : array_sum($v),            'host memory_free_kib' => ($v = $last('host', '/^memory_free_kib$/')) === [] ? null : $v[0],            'sr physical_utilisation' => (float)$record['physical_size'] > 0 ? (float)$record['physical_utilisation'] / (float)$record['physical_size'] : null,            'sr sr_io_throughput_total_per_host' => max(0.0, 3.0 + 2.0 * sin($this->clock / 40)),          // MiB/s            default => null,        };    }}