Anmelden
DE
games/xencenter-xenadmin-xcp-jumphp / src / Form / NewNetworkForm.php · commit fb1b7c9
<?phpnamespace App\Form;use App\Model\Connection;use JumPHP\Gui\Button;use JumPHP\Gui\CheckBox;use JumPHP\Gui\ComboBox;use JumPHP\Gui\Container;use JumPHP\Gui\Form;use JumPHP\Gui\FormLoader;use JumPHP\Gui\Label;use JumPHP\Gui\TextBox;/** * The New Network wizard of XenCenter, on one page. What XAPI is asked (Feature\Storage\Actions::createNetwork): network.create * {name_label, name_description, MTU, other_config {automatic}}, then * - External: pool.create_VLAN(device, network, VLAN): a VLAN interface on that NIC of every server (VLAN 0: untagged); * - Single-server private: nothing more; * - Bonded: Bond.create(network, the PIFs of the NICs on each server, MAC of the first, mode, {}). * Closes with ['newNetwork' => [...]]. * * @property Label $where * @property ComboBox $kind * @property TextBox $name * @property TextBox $description * @property TextBox $mtu * @property Container $externalPanel * @property ComboBox $nic * @property TextBox $vlan * @property Container $privatePanel * @property Container $bondPanel * @property Container $bondNics * @property ComboBox $bondMode * @property CheckBox $auto * @property Label $error * @property Button $create * @property Button $cancel */final class NewNetworkForm extends Form{    public const TYPES = ['external', 'private', 'bond'];    public const MODES = ['balance-slb', 'active-backup', 'lacp'];    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> the NICs of the pool master (the same devices are used on every server) */    public static function paramsFor(Connection $c): array    {        $nics = [];        foreach ($c->cache->pifsOf((string)$c->cache->master()) as $pif) {            if (empty($pif['physical']) || (int)$pif['VLAN'] !== -1) {                continue;            }            $speed = (int)($c->cache->get((string)($pif['metrics'] ?? ''))['speed'] ?? 0);            $bonded = ($pif['bond_slave_of'] ?? 'OpaqueRef:NULL') !== 'OpaqueRef:NULL';            $nics[] = ['device' => (string)$pif['device'], 'label' => $pif['device'] . ($speed > 0 ? ' (' . ($speed >= 1000 ? ($speed / 1000) . ' Gbit/s' : "$speed Mbit/s") . ')' : '')                . (!empty($pif['management']) ? ', management' : '') . ($bonded ? ', bonded' : ''), 'bonded' => $bonded, 'management' => !empty($pif['management'])];        }        return ['server' => $c->name(), 'pool' => (string)$c->cache->poolRef(), 'nics' => $nics];    }    protected function loaded(array $params = []): void    {        $this->params = $params;        $this->where->text = "In '" . ($params['server'] ?? '') . "'";        $this->kind->selected = 0;        $this->name->text = '';        $this->description->text = '';        $this->mtu->text = '1500';        $this->vlan->text = '';        $this->nic->items = array_column($params['nics'] ?? [], 'label');        $this->nic->selected = 0;        $this->bondMode->selected = 0;        $this->auto->checked = true;        $this->bondNics->clear();        foreach ($params['nics'] ?? [] as $nic) {            // a NIC already in a bond, or the management one, is not offered            $this->bondNics->add(FormLoader::widget(['type' => 'checkbox', 'id' => 'bond:' . $nic['device'], 'text' => (string)$nic['device'],                'enabled' => !$nic['bonded'] && !$nic['management']]));        }        $this->error->text = '';        $this->onKindChange($this->kind, 0, '');        $this->setFocus($this->name);    }    public function networkType(): string    {        return self::TYPES[(int)$this->kind->selected] ?? 'external';    }    public function onKindChange(ComboBox $sender, int $index, string $item): void    {        $type = $this->networkType();        $this->externalPanel->visible = $type === 'external';        $this->privatePanel->visible = $type === 'private';        $this->bondPanel->visible = $type === 'bond';        $this->error->text = '';    }    /** @return list<string> the devices ticked for the bond */    public function bondMembers(): array    {        $out = [];        foreach ($this->params['nics'] ?? [] as $nic) {            $box = $this->widget('bond:' . $nic['device']);            if ($box instanceof CheckBox && $box->checked) {                $out[] = (string)$nic['device'];            }        }        return $out;    }    public function onCreateClick(mixed $sender = null): void    {        $type = $this->networkType();        $name = trim($this->name->text);        $mtu = trim($this->mtu->text);        if ($name === '') {            $this->error->text = 'Enter a name for the network.';            return;        }        if (!ctype_digit($mtu) || (int)$mtu < 68 || (int)$mtu > 9216) {            $this->error->text = 'The MTU is a number from 68 to 9216 (1500 usually, 9000 for jumbo frames).';            return;        }        $spec = ['pool' => $this->params['pool'] ?? '', 'type' => $type, 'name' => $name, 'description' => $this->description->text, 'mtu' => (int)$mtu,            'auto' => $this->auto->checked];        if ($type === 'external') {            $vlan = trim($this->vlan->text);            $nic = $this->params['nics'][(int)$this->nic->selected] ?? null;            if ($nic === null) {                $this->error->text = 'This server has no network card to put the VLAN on.';                return;            }            if ($vlan !== '' && (!ctype_digit($vlan) || (int)$vlan > 4094)) {                $this->error->text = 'The VLAN is a number from 0 to 4094.';                return;            }            $spec += ['device' => $nic['device'], 'vlan' => (int)$vlan];        } elseif ($type === 'bond') {            $members = $this->bondMembers();            if (count($members) < 2) {                $this->error->text = 'Choose two NICs or more to bond.';                return;            }            $spec += ['members' => $members, 'mode' => self::MODES[(int)$this->bondMode->selected] ?? 'balance-slb'];        }        $this->close(['newNetwork' => $spec]);    }    public function onCancelClick(Button $sender): void    {        $this->close();    }}