This commit is contained in:
Dimitri John Ledkov 2018-06-28 10:53:45 +01:00
parent 173eac79a5
commit 92c53b29ae
4 changed files with 91 additions and 2 deletions

View File

@ -237,6 +237,21 @@ class NetworkController(BaseController, TaskWatcher):
netplan_config_file_name = '00-snapd-config.yaml' netplan_config_file_name = '00-snapd-config.yaml'
return os.path.join(self.root, 'etc/netplan', netplan_config_file_name) return os.path.join(self.root, 'etc/netplan', netplan_config_file_name)
def add_vlan(self, device, vlan):
cmd = ['ip', 'link', 'add', 'name', '%s.%s' % (device.name, vlan),
'link', device.name, 'type', 'vlan', 'id', str(vlan)]
try:
run_command(cmd, check=True)
except:
self.ui.frame.body.show_network_error('add-vlan')
def rm_virtual_interface(self, device):
cmd = ['ip', 'link', 'delete', 'dev', device.name]
try:
run_command(cmd, check=True)
except:
self.ui.frame.body.show_network_error('rm-dev')
def network_finish(self, config): def network_finish(self, config):
log.debug("network config: \n%s", log.debug("network config: \n%s",
yaml.dump(sanitize_config(config), default_flow_style=False)) yaml.dump(sanitize_config(config), default_flow_style=False))

View File

@ -23,6 +23,7 @@ from subiquitycore import netplan
NETDEV_IGNORED_IFACE_NAMES = ['lo'] NETDEV_IGNORED_IFACE_NAMES = ['lo']
NETDEV_IGNORED_IFACE_TYPES = ['bridge', 'tun', 'tap', 'dummy', 'sit'] NETDEV_IGNORED_IFACE_TYPES = ['bridge', 'tun', 'tap', 'dummy', 'sit']
NETDEV_WHITELIST_IFACE_TYPES = ['vlan']
log = logging.getLogger('subiquitycore.models.network') log = logging.getLogger('subiquitycore.models.network')
@ -45,6 +46,11 @@ class Networkdev:
def __init__(self, net_info, configuration): def __init__(self, net_info, configuration):
self._net_info = net_info self._net_info = net_info
self._configuration = configuration self._configuration = configuration
if self.type == 'vlan':
# probably should parse /proc/self/net/vlan/config instead
link, vid = self.name.split('.')
self._configuration['id'] = int(vid)
self._configuration['link'] = link
def render(self): def render(self):
if self.configured_ip_addresses or self.dhcp4 or self.dhcp6: if self.configured_ip_addresses or self.dhcp4 or self.dhcp6:
@ -98,6 +104,10 @@ class Networkdev:
def is_bonded(self): def is_bonded(self):
return self.is_bond_master or self.is_bond_slave return self.is_bond_master or self.is_bond_slave
@property
def is_virtual(self):
return self._net_info.is_virtual
@property @property
def speed(self): def speed(self):
'''string'ify and bucketize iface speed: '''string'ify and bucketize iface speed:
@ -337,7 +347,7 @@ class NetworkModel(object):
return return
if link.name in NETDEV_IGNORED_IFACE_NAMES: if link.name in NETDEV_IGNORED_IFACE_NAMES:
return return
if link.is_virtual: if link.is_virtual and link.type not in NETDEV_WHITELIST_IFACE_TYPES:
return return
config = self.config.config_for_device(link) config = self.config.config_for_device(link)
log.debug("new_link %s %s with config %s", log.debug("new_link %s %s with config %s",
@ -465,6 +475,7 @@ class NetworkModel(object):
ethernets = {} ethernets = {}
bonds = {} bonds = {}
wifis = {} wifis = {}
vlans = {}
for dev in self.devices.values(): for dev in self.devices.values():
if dev.type == 'eth': if dev.type == 'eth':
ethernets.update(dev.render()) ethernets.update(dev.render())
@ -472,12 +483,16 @@ class NetworkModel(object):
bonds.update(dev.render()) bonds.update(dev.render())
if dev.type == 'wlan': if dev.type == 'wlan':
wifis.update(dev.render()) wifis.update(dev.render())
if dev.type == 'vlan':
vlans.update(dev.render())
if any(ethernets): if any(ethernets):
config['network']['ethernets'] = ethernets config['network']['ethernets'] = ethernets
if any(bonds): if any(bonds):
config['network']['bonds'] = bonds config['network']['bonds'] = bonds
if any(wifis): if any(wifis):
config['network']['wifis'] = wifis config['network']['wifis'] = wifis
if any(vlans):
config['network']['vlans'] = vlans
nw_routes = [] nw_routes = []
if self.default_v4_gateway: if self.default_v4_gateway:

View File

@ -44,7 +44,7 @@ from subiquitycore.ui.utils import (
make_action_menu_row, make_action_menu_row,
Padding, Padding,
) )
from .network_configure_manual_interface import EditNetworkStretchy from .network_configure_manual_interface import EditNetworkStretchy, AddVlanStretchy
from .network_configure_wlan_interface import NetworkConfigureWLANStretchy from .network_configure_wlan_interface import NetworkConfigureWLANStretchy
from subiquitycore.view import BaseView from subiquitycore.view import BaseView
@ -149,6 +149,12 @@ class NetworkView(BaseView):
def _action_edit_ipv6(self, device): def _action_edit_ipv6(self, device):
self.show_stretchy_overlay(EditNetworkStretchy(self, device, 6)) self.show_stretchy_overlay(EditNetworkStretchy(self, device, 6))
def _action_add_vlan(self, device):
self.show_stretchy_overlay(AddVlanStretchy(self, device))
def _action_rm_dev(self, device):
self.controller.rm_virtual_interface(device)
def _action(self, sender, action, device): def _action(self, sender, action, device):
m = getattr(self, '_action_{}'.format(action)) m = getattr(self, '_action_{}'.format(action))
m(device) m(device)
@ -199,6 +205,10 @@ class NetworkView(BaseView):
("Edit IPv4", True, 'edit_ipv4', True), ("Edit IPv4", True, 'edit_ipv4', True),
("Edit IPv6", True, 'edit_ipv6', True), ("Edit IPv6", True, 'edit_ipv6', True),
] ]
if dev.type != 'vlan':
actions.append((_("Add a VLAN tag"), True, 'add_vlan', True))
if dev.is_virtual:
actions.append((_("Delete"), True, 'rm_dev', True))
menu = ActionMenu(actions) menu = ActionMenu(actions)
connect_signal(menu, 'action', self._action, dev) connect_signal(menu, 'action', self._action, dev)
rows.append(make_action_menu_row([ rows.append(make_action_menu_row([
@ -244,6 +254,10 @@ class NetworkView(BaseView):
self.error.set_text("Downing network interfaces failed.") self.error.set_text("Downing network interfaces failed.")
elif action == 'canceled': elif action == 'canceled':
self.error.set_text("Network configuration canceled.") self.error.set_text("Network configuration canceled.")
elif action == 'add-vlan':
self.error.set_text("Failed to add a VLAN tag.")
elif action == 'rm-dev':
self.error.set_text("Failed to delete a virtual interface.")
else: else:
self.error.set_text("An unexpected error has occurred; " self.error.set_text("An unexpected error has occurred; "
"please verify your settings.") "please verify your settings.")

View File

@ -235,3 +235,48 @@ class EditNetworkStretchy(Stretchy):
def cancel(self, sender=None): def cancel(self, sender=None):
self.parent.remove_overlay() self.parent.remove_overlay()
class VlanForm(Form):
def __init__(self, parent, device):
self.parent = parent
self.device = device
super().__init__()
vlan = StringField(_("VLAN ID:"))
def clean_vlan(self, value):
try:
vlanid = int(value)
except ValueError:
vlanid = None
if vlanid is None or vlanid < 1 or vlanid > 4095:
raise ValueError(
_("VLAN ID must be between 1 and 4095"))
return vlanid
def validate_vlan(self):
new_name = '%s.%s' % (self.device.name, self.vlan.value)
if new_name in self.parent.model.devices_by_name:
return _("%s already exists") % new_name
class AddVlanStretchy(Stretchy):
def __init__(self, parent, device):
self.parent = parent
self.device = device
self.form = VlanForm(parent, device)
connect_signal(self.form, 'submit', self.done)
connect_signal(self.form, 'cancel', self.cancel)
super().__init__(
_('Add a VLAN tag'),
[Pile(self.form.as_rows()), Text(""), self.form.buttons],
0, 0)
def done(self, sender):
self.parent.remove_overlay()
self.parent.controller.add_vlan(self.device, self.form.vlan.value)
def cancel(self, sender=None):
self.parent.remove_overlay()