<?phpnamespace App\Xapi\Fake;use App\Xapi\XapiError;/** * XCP-ng's updates in the demo pool (part of FakeXapi): the host plugin updater.py, as XCP-ng 8.x has it (yum behind it). * host.call_plugin($host, 'updater.py', 'check_update', {}) answers the packages yum would update, as a JSON string; * 'update' installs them (a long call: Async.host.call_plugin), after which a new kernel / Xen / XAPI waits for a reboot. */trait UpdatesOps{ /** @var array<string, list<array<string, mixed>>> host ref => the packages yum would update */ public array $pendingUpdates = []; private function buildUpdates(): void { $packages = [ ['xapi-core', '24.19.2', '1.6.xcpng8.3', '24.19.1', '1.4.xcpng8.3', 'xapi - the Xen Cloud Platform toolstack', 'Fix a crash of event.from when a VM is destroyed during a migration'], ['xapi-xe', '24.19.2', '1.6.xcpng8.3', '24.19.1', '1.4.xcpng8.3', 'The xe command line client of XAPI', 'Rebuild for xapi 24.19.2'], ['xen-hypervisor', '4.17.5', '4.xcpng8.3', '4.17.4', '3.xcpng8.3', 'The Xen hypervisor', 'XSA-462, XSA-463: security fixes'], ['xen-dom0-tools', '4.17.5', '4.xcpng8.3', '4.17.4', '3.xcpng8.3', 'Xen tools of the control domain', 'XSA-462, XSA-463'], ['kernel', '4.19.19', '8.0.38.1.xcpng8.3', '4.19.19', '8.0.37.2.xcpng8.3', 'The Linux kernel of dom0', 'Backports of storage driver fixes (megaraid_sas, nvme)'], ['sm', '3.2.3', '1.8.xcpng8.3', '3.2.3', '1.6.xcpng8.3', 'Storage manager: the SR drivers', 'LVHD: faster coalesce of snapshot chains'], ['openssl-libs', '1.0.2k', '26.2.xcpng8.3', '1.0.2k', '26.1.xcpng8.3', 'The OpenSSL libraries', 'CVE-2024-5535'], ['xcp-ng-xapi-plugins', '1.11.0', '1.xcpng8.3', '1.10.1', '1.xcpng8.3', 'XAPI plugins of XCP-ng (updater.py, smartctl...)', 'updater.py: report the size of each package'], ['curl', '8.9.1', '2.xcpng8.3', '8.9.1', '1.xcpng8.3', 'A tool to transfer data with URLs', 'CVE-2024-8096'], ]; $n = 0; foreach (array_keys($this->db['host'] ?? []) as $host) { // the second server was updated more recently: fewer packages $list = $n === 0 ? $packages : array_values(array_filter($packages, fn ($p) => in_array($p[0], ['xapi-core', 'xapi-xe', 'openssl-libs', 'curl', 'sm'], true))); $this->pendingUpdates[$host] = array_map(fn (array $p) => ['name' => $p[0], 'version' => $p[1], 'release' => $p[2], 'current_version' => $p[3], 'current_release' => $p[4], 'description' => $p[5], 'changelog' => ['date' => '2024-10-15', 'author' => 'XCP-ng team', 'description' => $p[6]], 'url' => 'https://updates.xcp-ng.org/8/8.3/base/x86_64/Packages/' . $p[0] . '-' . $p[1] . '-' . $p[2] . '.x86_64.rpm', 'size' => 180000 + strlen($p[5]) * 37111], $list); $n++; } } /** @return array{0: float, 1: \Closure, 2: string, 3: string}|null */ private function updatesOperation(string $class, string $method, array $p): ?array { if ($class !== 'host' || $method !== 'call_plugin') { return null; } $host = (string)($p[0] ?? ''); $this->record('host', $host); $plugin = (string)($p[1] ?? ''); $fn = (string)($p[2] ?? ''); if ($plugin !== 'updater.py') { throw new XapiError(['XENAPI_MISSING_PLUGIN', $plugin]); } return match ($fn) { 'check_update' => [2.0, fn (): string => (string)json_encode($this->pendingUpdates[$host] ?? [], JSON_UNESCAPED_SLASHES), 'Checking for updates', $host], 'update' => [5.0, function () use ($host): string { $installed = $this->pendingUpdates[$host] ?? []; $this->pendingUpdates[$host] = []; $sw = (array)$this->db['host'][$host]['software_version']; foreach ($installed as $package) { if ($package['name'] === 'xapi-core') { $sw['xapi'] = '24.19'; $sw['build_number'] = 'release/yangtze/master/' . (58 + count($installed)); } } $this->set('host', $host, ['software_version' => $sw]); return ''; }, 'Installing updates', $host], default => throw new XapiError(['XENAPI_PLUGIN_FAILURE', $fn, 'NotFound', "updater.py has no function $fn"]), }; }}