로그인
KO
games/xencenter-xenadmin-xcp-jumphp / src / Form / DiskForm.php · commit fb1b7c9
<?phpnamespace App\Form;use App\Feature\Storage\Menus;use App\Gui\Units;use App\Model\Connection;use JumPHP\Gui\Button;use JumPHP\Gui\ComboBox;use JumPHP\Gui\Container;use JumPHP\Gui\Form;use JumPHP\Gui\Label;use JumPHP\Gui\ListBox;use JumPHP\Gui\TextBox;/** * A disk for a VM (Feature\Storage\Actions): "add" = VDI.create on an SR then VBD.create (+ VBD.plug when the VM runs); * "attach" = VBD.create on a disk no VM uses. Closes with ['addDisk' => [vm, name, description, size (bytes, a float), sr]] * or ['attachDisk' => [vm, vdi]]. * * @property Label $heading * @property Label $where * @property Container $addPanel * @property TextBox $name * @property TextBox $description * @property TextBox $size * @property ComboBox $sr * @property Container $attachPanel * @property ListBox $disk * @property Label $note * @property Label $error * @property Button $ok * @property Button $cancel */final class DiskForm 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 $vm, string $mode): array    {        $cache = $c->cache;        $default = (string)$cache->field((string)$cache->poolRef(), 'default_SR', '');        $srs = [];        $free = [];        foreach ($cache->srs() as $ref => $sr) {            if (($sr['content_type'] ?? '') === 'iso' || !Menus::managed($cache, $ref) || Menus::attached($cache, $ref) === 0) {                continue;            }            $srs[] = ['ref' => $ref, 'name' => $cache->name($ref) . ' (' . Units::bytes((float)$sr['physical_size'] - (float)$sr['physical_utilisation']) . ' free)'];            foreach ((array)$sr['VDIs'] as $vdi) {                $d = $cache->get((string)$vdi);                if ($d !== null && (array)$d['VBDs'] === [] && empty($d['is_a_snapshot']) && empty($d['read_only'])) {                    $free[] = ['ref' => (string)$vdi, 'name' => $d['name_label'] . ' (' . Units::bytes((float)$d['virtual_size']) . ', ' . $cache->name($ref) . ')'];                }            }        }        usort($srs, fn ($a, $b) => ($b['ref'] === $default) <=> ($a['ref'] === $default));        $disks = count($cache->disksOf($vm));        return ['vm' => $vm, 'vmName' => $cache->name($vm), 'mode' => $mode, 'srs' => $srs, 'free' => $free, 'running' => $cache->field($vm, 'power_state') === 'Running',            'name' => $cache->name($vm) . ' ' . $disks];    }    protected function loaded(array $params = []): void    {        $this->params = $params;        $add = ($params['mode'] ?? 'add') === 'add';        $this->heading->text = $add ? 'Add Virtual Disk' : 'Attach Virtual Disk';        $this->where->text = "To VM '" . ($params['vmName'] ?? '') . "'";        $this->addPanel->visible = $add;        $this->attachPanel->visible = !$add;        $this->ok->text = $add ? 'Add' : 'Attach';        $this->name->text = (string)($params['name'] ?? 'disk');        $this->description->text = '';        $this->size->text = '20';        $this->sr->items = array_column($params['srs'] ?? [], 'name');        $this->sr->selected = ($params['srs'] ?? []) === [] ? -1 : 0;        $this->disk->items = array_column($params['free'] ?? [], 'name');        $this->disk->selected = ($params['free'] ?? []) === [] ? -1 : 0;        $this->note->text = !empty($params['running']) ? 'The VM is running: the disk is plugged in at once.' : '';        $this->error->text = !$add && ($params['free'] ?? []) === [] ? 'Every disk of the pool is in use.' : '';        if ($add) {            $this->setFocus($this->name);        }    }    public function onOkClick(mixed $sender = null): void    {        $vm = (string)($this->params['vm'] ?? '');        if (($this->params['mode'] ?? 'add') !== 'add') {            $disk = $this->params['free'][(int)$this->disk->selected] ?? null;            if ($disk === null) {                $this->error->text = 'Choose a disk.';                return;            }            $this->close(['attachDisk' => ['vm' => $vm, 'vdi' => $disk['ref']]]);            return;        }        $size = (float)str_replace(',', '.', trim($this->size->text));        $sr = $this->params['srs'][(int)$this->sr->selected] ?? null;        if (trim($this->name->text) === '') {            $this->error->text = 'Enter a name for the disk.';            return;        }        if ($size < 0.01 || $size > 65536) {            $this->error->text = 'The size is a number of GB, from 0.01 to 65536.';            return;        }        if ($sr === null) {            $this->error->text = 'There is no storage repository to put the disk on.';            return;        }        // bytes stay a float: 2 GB and more do not fit the browser's 32-bit integers        $this->close(['addDisk' => ['vm' => $vm, 'name' => trim($this->name->text), 'description' => $this->description->text, 'size' => floor($size * 1073741824.0), 'sr' => $sr['ref']]]);    }    public function onCancelClick(Button $sender): void    {        $this->close();    }}