RU
games/xencenter-xenadmin-xcp-jumphp / src / Form / PropertiesForm.php · commit fb1b7c9
<?phpnamespace App\Form;use App\Feature\Organize\OrganizeProperties;use App\Gui\IconBox;use App\Gui\Icons;use App\Model\Chain;use App\Model\Connection;use App\Model\Session;use JumPHP\Gui\Button;use JumPHP\Gui\Container;use JumPHP\Gui\Form;use JumPHP\Gui\Label;use JumPHP\Gui\TextBox;/** * The Properties dialog: name and description of a pool, server, VM, template, storage or network; vCPUs and memory of a halted VM * (XAPI only changes them while it is halted, as XenCenter says). Closes with ['properties' => [...]], MainForm applies it. * * @property IconBox $icon * @property Label $heading * @property TextBox $name * @property TextBox $description * @property Container $vmPanel * @property TextBox $vcpus * @property TextBox $memory * @property Label $vmNote * @property TextBox $tags * @property \JumPHP\Gui\ComboBox $folder * @property TextBox $newFolder * @property Label $error * @property Button $alerts * @property Button $ok * @property Button $cancel */final class PropertiesForm extends Form{    public function __construct(private \App\Model\Session $session)    {        parent::__construct();    }    /** XAPI's answers, events and the console go on while this dialog is open. */    protected function tick(float $dt): void    {        $this->session->tick($dt);    }    private array $params = [];    /** @return array<string, mixed> */    public static function paramsFor(Connection $c, string $ref, bool $memory = false): array    {        $r = $c->cache->get($ref) ?? [];        $class = (string)$c->cache->classOf($ref);        return ['target' => $ref, 'class' => $class, 'icon' => Icons::of($class, $r, $c->cache), 'name' => $c->cache->name($ref), 'description' => (string)($r['name_description'] ?? ''),            'vm' => $class === 'vm', 'halted' => ($r['power_state'] ?? '') === 'Halted', 'vcpus' => (int)($r['VCPUs_at_startup'] ?? 1),            'memory' => (int)round((float)($r['memory_static_max'] ?? 0) / 1048576), 'focusMemory' => $memory] + OrganizeProperties::params($c, $ref);    }    protected function loaded(array $params = []): void    {        $this->params = $params;        $this->heading->text = "Properties of '" . ($params['name'] ?? '') . "'";        $this->icon->kind = (string)($params['icon'] ?? 'folder');        $this->name->text = (string)($params['name'] ?? '');        $this->description->text = (string)($params['description'] ?? '');        $this->vmPanel->visible = !empty($params['vm']);        $this->vcpus->text = (string)($params['vcpus'] ?? 1);        $this->memory->text = (string)($params['memory'] ?? 1024);        $halted = !empty($params['halted']);        $this->vcpus->enabled = $this->memory->enabled = $halted;        $this->vmNote->text = $halted ? '' : 'Shut the VM down to change its vCPUs and memory.';        $this->error->text = '';        OrganizeProperties::fill($this, $params);       // Tags and Folder        $this->alerts->visible = in_array($params['class'] ?? '', ['vm', 'host', 'sr', 'pool'], true);       // AlertsForm        $this->setFocus(!empty($params['focusMemory']) && $halted ? $this->memory : $this->name);    }    public function onOkClick(Button $sender): void    {        $vcpus = (int)$this->vcpus->text;        $memory = (int)$this->memory->text;        if (trim($this->name->text) === '') {            $this->error->text = 'Enter a name.';            return;        }        if (!empty($this->params['vm']) && !empty($this->params['halted']) && ($vcpus < 1 || $vcpus > 64 || $memory < 256)) {            $this->error->text = 'From 1 to 64 vCPUs, and at least 256 MB of memory.';            return;        }        $this->close(['properties' => ['target' => $this->params['target'], 'name' => trim($this->name->text), 'description' => $this->description->text,            'vcpus' => $vcpus, 'memory' => $memory] + OrganizeProperties::values($this) + $this->params]);    }    /** XenCenter's Alerts page of the Properties: its own dialog (src/Form/AlertsForm.php), opened by MainForm. */    public function onAlertsClick(Button $sender): void    {        $this->close(['open' => 'object.alerts', 'target' => $this->params['target'] ?? '']);    }    public function onCancelClick(Button $sender): void    {        $this->close();    }    /** What changed is sent to XAPI. @param array<string, mixed> $p */    public static function apply(Session $session, array $p): void    {        $ref = (string)$p['target'];        $c = $session->connectionOf($ref);        if ($c === null) {            return;        }        $class = match ((string)$p['class']) { 'sr' => 'SR', 'vm' => 'VM', default => (string)$p['class']};        if ($p['name'] !== ($c->cache->get($ref)['name_label'] ?? '')) {            $c->call("$class.set_name_label", $ref, (string)$p['name']);        }        if ($p['description'] !== ($c->cache->get($ref)['name_description'] ?? '')) {            $c->call("$class.set_name_description", $ref, (string)$p['description']);        }        OrganizeProperties::apply($c, $ref, $p);        if (!empty($p['vm']) && !empty($p['halted'])) {            $r = $c->cache->get($ref) ?? [];            $bytes = (float)$p['memory'] * 1048576;            $steps = [];            if (abs($bytes - (float)($r['memory_static_max'] ?? 0)) >= 1048576) {                $min = min((float)($r['memory_static_min'] ?? $bytes), $bytes);                $steps[] = fn () => $c->run("Changing the memory of '" . $p['name'] . "'", 'VM.set_memory_limits', [$ref, $min, $bytes, $bytes, $bytes], $ref);            }            $vcpus = (int)$p['vcpus'];            if ($vcpus !== (int)($r['VCPUs_at_startup'] ?? 0)) {                // the maximum first when it grows, the startup count first when it shrinks                $grow = $vcpus > (int)($r['VCPUs_max'] ?? 0);                $steps[] = fn () => $grow ? $c->run("Changing the vCPUs of '" . $p['name'] . "'", 'VM.set_VCPUs_max', [$ref, $vcpus], $ref)                    : $c->run("Changing the vCPUs of '" . $p['name'] . "'", 'VM.set_VCPUs_at_startup', [$ref, $vcpus], $ref);                $steps[] = fn () => $grow ? $c->run("Changing the vCPUs of '" . $p['name'] . "'", 'VM.set_VCPUs_at_startup', [$ref, $vcpus], $ref)                    : $c->run("Changing the vCPUs of '" . $p['name'] . "'", 'VM.set_VCPUs_max', [$ref, $vcpus], $ref);            }            Chain::run($steps)->then(fn () => null, fn () => null);        }    }}