Accedi
IT
games/xencenter-xenadmin-xcp-jumphp / src / Feature / FeatureCommands.php · commit fb1b7c9
<?phpnamespace App\Feature;use App\Feature\Updates\RollingUpdate;use App\Feature\Updates\Updates;use App\Feature\Xva\XvaTransfers;use App\Form\AlertsForm;use App\Form\ConfirmForm;use App\Form\ExportForm;use App\Form\ImportForm;use App\Form\MainForm;use App\Model\Connection;use App\View\Commands;use JumPHP\Kernel\Engine;/** * The commands of the updates, the XVA export / import and the alerts, kept apart from View\Commands and Form\MainForm (which only * call here): their menu items, their confirmations, what they do, what their dialogs answer. *   updates.check     Check for Updates (a pool: every server; a server: it) *   updates.install   Install Updates… on one server *   updates.rolling   Rolling Pool Update… (master first, maintenance mode, update, reboot, enable) *   vm.export         Export… (a halted VM, an XVA file) *   file.import       Import… (an XVA file into the pool) *   object.alerts     Alerts… (perfmon alarms of a VM / server / SR, e-mail of a pool) */final class FeatureCommands{    public const IDS = ['updates.check', 'updates.install', 'updates.rolling', 'vm.export', 'file.import', 'object.alerts'];    // menu items ---------------------------------------------------------------------------------------------------------------    /** @return list<array<string, mixed>|string> */    public static function vmItems(?Connection $c, string $vm): array    {        $halted = ($c?->cache->field($vm, 'power_state', '') ?? '') === 'Halted';        return [Commands::item('vm.export', 'Export…', $halted), Commands::item('object.alerts', 'Alerts…')];    }    /** @return list<array<string, mixed>|string> */    public static function hostItems(?Connection $c, string $host): array    {        $pending = $c !== null ? Updates::pending($c, $host) : 0;        return [Commands::item('updates.check', 'Check for Updates'), Commands::item('updates.install', $pending > 0 ? "Install $pending Updates…" : 'Install Updates…', $pending > 0),            Commands::item('object.alerts', 'Alerts…')];    }    /** @return list<array<string, mixed>|string> */    public static function poolItems(?Connection $c, string $pool): array    {        return [Commands::item('updates.check', 'Check for Updates'), Commands::item('updates.rolling', 'Rolling Pool Update…', $c !== null && RollingUpdate::order($c) !== []),            Commands::item('file.import', 'Import…'), Commands::item('object.alerts', 'E-mail Alerts…')];    }    /** @return list<array<string, mixed>|string> */    public static function srItems(): array    {        return [Commands::item('object.alerts', 'Alerts…')];    }    /** @return list<array<string, mixed>|string> */    public static function fileItems(?Connection $c): array    {        return [Commands::item('file.import', 'Import…', $c !== null && $c->isConnected())];    }    // running them -------------------------------------------------------------------------------------------------------------    public static function confirmation(string $id, Connection $c, string $target): ?string    {        $name = $c->cache->name($target);        return match ($id) {            'updates.install' => 'Install ' . Updates::pending($c, $target) . " updates on server '$name'?\n\n"                . (Updates::needsReboot(Updates::of($c, $target)->packages ?? []) ? "A new kernel, Xen or XAPI is among them: the server needs a reboot afterwards (move its VMs away first, or use the Rolling Pool Update)."                    : 'Its VMs keep running.'),            'updates.rolling' => "Update the servers of '" . $c->name() . "' one after the other?\n\n"                . implode(', ', array_map(fn ($h) => $c->cache->name($h), RollingUpdate::order($c)))                . "\n\nThe pool master first. Each is put into maintenance mode (its VMs migrate to the others), updated, rebooted if needed, then enabled again.",            default => null,        };    }    /** One of these commands from MainForm::command(): true when it was one (done, or a dialog opened). */    public static function run(MainForm $form, string $id, ?Connection $c, string $target, bool $confirmed): bool    {        if (!in_array($id, self::IDS, true)) {            return false;        }        if ($c === null || !$c->isConnected()) {            return true;        }        $class = (string)$c->cache->classOf($target);        if (!$confirmed && ($question = self::confirmation($id, $c, $id === 'updates.rolling' ? (string)$c->cache->poolRef() : $target)) !== null) {            Engine::get()->scenes->push(ConfirmForm::class, ['message' => $question, 'command' => $id, 'target' => $target, 'ok' => $id === 'updates.rolling' ? 'Update' : 'Install']);            return true;        }        switch ($id) {            case 'updates.check':                Updates::check($c, $class === 'host' ? $target : null);                break;            case 'updates.install':                if ($class === 'host') {                    Updates::install($c, $target)->then(fn () => null, fn () => null);                }                break;            case 'updates.rolling':                RollingUpdate::run($form->session, $c)->then(fn () => null, fn () => null);                break;            case 'vm.export':                Engine::get()->scenes->push(ExportForm::class, ExportForm::paramsFor($c, $target));                break;            case 'file.import':                Engine::get()->scenes->push(ImportForm::class, ImportForm::paramsFor($c, $class === 'host' ? $target : null));                break;            case 'object.alerts':                $ref = in_array($class, ['vm', 'host', 'sr', 'pool'], true) ? $target : (string)$c->cache->poolRef();                Engine::get()->scenes->push(AlertsForm::class, AlertsForm::paramsFor($c, $ref));                break;        }        $form->refresh(true);        return true;    }    /** What their dialogs answered (MainForm::resume()): true when it was theirs. @param array<string, mixed> $result */    public static function result(MainForm $form, array $result): bool    {        if (isset($result['alerts'])) {            AlertsForm::apply($form->session, $result['alerts']);            return true;        }        if (isset($result['open'])) {            // Properties > Alerts…            $form->command((string)$result['open'], (string)($result['target'] ?? ''));            return true;        }        if (!isset($result['xva'])) {            return false;        }        $x = $result['xva'];        if ($x['op'] === 'export') {            $c = $form->session->connectionOf((string)$x['target']);            if ($c !== null) {                XvaTransfers::export($form->session, $c, (string)$x['target'], (string)$x['file'], !empty($x['compress']))->then(fn () => null, fn () => null);            }        } else {            $c = $form->session->connectionOf((string)$x['sr']);            if ($c !== null) {                XvaTransfers::import($form->session, $c, (string)$x['file'], (string)$x['sr'], (string)$x['host'], (string)$x['label'])->then(fn () => null, fn () => null);            }        }        return true;    }}