From 46c0d598ad4ad3587f9527449465e8ae1783dece Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 11 Jul 2018 16:06:32 +1200 Subject: [PATCH] first cut at a bond form that handles devices too --- subiquitycore/models/network.py | 8 +- subiquitycore/ui/views/network.py | 14 +--- .../network_configure_manual_interface.py | 76 +++++++++++++++---- 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/subiquitycore/models/network.py b/subiquitycore/models/network.py index 218f83df..24a6c28a 100644 --- a/subiquitycore/models/network.py +++ b/subiquitycore/models/network.py @@ -37,9 +37,8 @@ class NetDevAction(enum.Enum): EDIT_WLAN = _("Edit Wifi") EDIT_IPV4 = _("Edit IPv4") EDIT_IPV6 = _("Edit IPv6") + EDIT_BOND = _("Edit bond") ADD_VLAN = _("Add a VLAN tag") - ADD_BOND = _("Create a new bond") -# REMOVE_MASTER = _("Remove master") DELETE = _("Delete") @@ -86,13 +85,10 @@ class Networkdev: _supports_EDIT_WLAN = property(lambda self: self.type == "wlan") _supports_EDIT_IPV4 = True _supports_EDIT_IPV6 = True + _supports_EDIT_BOND = property(lambda self: self.is_bond_master) _supports_ADD_VLAN = property( lambda self: self.type != "vlan" and not self._net_info.bond['is_slave']) - _supports_ADD_BOND = property( - lambda self: not self._net_info.bond['is_slave']) - _supports_REMOVE_MASTER = property( - lambda self: self._net_info.bond['is_slave']) _supports_DELETE = property(lambda self: self.is_virtual) @property diff --git a/subiquitycore/ui/views/network.py b/subiquitycore/ui/views/network.py index 3e89ebc5..18e28fe7 100644 --- a/subiquitycore/ui/views/network.py +++ b/subiquitycore/ui/views/network.py @@ -51,8 +51,8 @@ from subiquitycore.ui.utils import ( Padding, ) from .network_configure_manual_interface import ( - AddBondStretchy, AddVlanStretchy, + BondStretchy, EditNetworkStretchy, ViewInterfaceInfo, ) @@ -144,8 +144,8 @@ class NetworkView(BaseView): _action_EDIT_WLAN = _stretchy_shower(NetworkConfigureWLANStretchy) _action_EDIT_IPV4 = _stretchy_shower(EditNetworkStretchy, 4) _action_EDIT_IPV6 = _stretchy_shower(EditNetworkStretchy, 6) + _action_EDIT_BOND = _stretchy_shower(BondStretchy) _action_ADD_VLAN = _stretchy_shower(AddVlanStretchy) - _action_ADD_BOND = _stretchy_shower(AddBondStretchy) def _action_DELETE(self, device): self.controller.rm_virtual_interface(device) @@ -157,14 +157,6 @@ class NetworkView(BaseView): def _cells_for_device(self, dev): dhcp = [] - if dev.dhcp4: - dhcp.append('v4') - if dev.dhcp6: - dhcp.append('v6') - if dhcp: - dhcp = ",".join(dhcp) - else: - dhcp = '-' addresses = [] for v in 4, 6: if dev.configured_ip_addresses_for_version(v): @@ -272,7 +264,7 @@ class NetworkView(BaseView): return rows def _create_bond(self, sender): - pass + self.show_stretchy_overlay(BondStretchy(self)) def show_network_error(self, action, info=None): self.error_showing = True diff --git a/subiquitycore/ui/views/network_configure_manual_interface.py b/subiquitycore/ui/views/network_configure_manual_interface.py index d83a7f0d..80513db7 100644 --- a/subiquitycore/ui/views/network_configure_manual_interface.py +++ b/subiquitycore/ui/views/network_configure_manual_interface.py @@ -344,39 +344,85 @@ _lacp_rates = [ class BondForm(Form): + def __init__(self, initial, all_netdev_names): + self.all_netdev_names = all_netdev_names + super().__init__(initial) + connect_signal(self.mode.widget, 'select', self._select_level) + self._select_level(None, self.mode.value) + name = StringField(_("Name:")) + devices = StringField(_("Devices: ")) mode = ChoiceField(_("Bond mode:"), choices=_bond_modes) xmit_hash_policy = ChoiceField( _("XMIT hash policy:"), choices=_xmit_hash_policies) lacp_rate = ChoiceField(_("LACP rate:"), choices=_lacp_rates) ok_label = _("Save") + def _select_level(self, sender, new_value): + self.xmit_hash_policy.enabled = new_value in _supports_xmit_hash_policy + self.lacp_rate.enabled = new_value in _supports_lacp_rate -class AddBondStretchy(Stretchy): + def validate_name(self): + name = self.name.value + if name in self.all_netdev_names: + return _('There is already a network device named "{}"').format( + name=name) + if len(name) == 0: + return _("Name cannot be empty") + if len(name) > 16: + return _("Name cannot be more than 16 characters long") - def __init__(self, parent, slave=None): + +class BondStretchy(Stretchy): + + def __init__(self, parent, existing=None): self.parent = parent - self.slave = slave - self.form = BondForm() - connect_signal(self.form.mode.widget, 'select', self._select_level) + self.existing = existing + all_netdev_names = { + device.name for device in parent.model.get_all_netdevs()} + if existing is None: + title = _('Create bond') + x = 0 + while True: + name = 'bond{}'.format(x) + if name not in all_netdev_names: + break + x += 1 + initial = { + 'name': name, + } + else: + title = _('Edit bond') + all_netdev_names.remove(existing.name) + params = existing._configuration['parameters'] + mode = params['mode'] + initial = { + 'devices': ','.join(existing._configuration['interfaces']), + 'name': existing.name, + 'mode': mode, + } + if mode in _supports_xmit_hash_policy: + initial['xmit_hash_policy'] = params['transmit-hash-policy'] + if mode in _supports_lacp_rate: + initial['lacp_rate'] = params['lacp-rate'] + self.form = BondForm(initial, all_netdev_names) connect_signal(self.form, 'submit', self.done) connect_signal(self.form, 'cancel', self.cancel) - self._select_level(None, 'balance-rr') super().__init__( - _('Create bond'), + title, [Pile(self.form.as_rows()), Text(""), self.form.buttons], 0, 0) - def _select_level(self, sender, new_value): - self.form.xmit_hash_policy.enabled = \ - new_value in _supports_xmit_hash_policy - self.form.lacp_rate.enabled = new_value in _supports_lacp_rate - def done(self, sender): - self.parent.remove_overlay() + if self.existing is not None: + self.parent.controller.rm_virtual_interface(self.existing) self.parent.controller.add_bond(self.form.as_data()) - self.parent.controller.add_master( - self.slave, master_name=self.form.name.value) + device_names = self.form.devices.value.split(',') + for device_name in device_names: + self.parent.controller.add_master( + self.parent.model.get_netdev_by_name(device_name), + master_name=self.form.name.value) + self.parent.remove_overlay() def cancel(self, sender=None): self.parent.remove_overlay()