From 5086b002635b4e9e5c7bd43b59686baa930adab3 Mon Sep 17 00:00:00 2001 From: Ryan Harper Date: Wed, 4 Nov 2015 09:50:58 -0600 Subject: [PATCH] Fetch manual configuration Collect and apply manual ipv4 interface configuration and update the model. Signed-off-by: Ryan Harper --- subiquity/models/network.py | 88 ++++++++++++++++--- subiquity/ui/views/network.py | 13 +-- .../views/network_configure_ipv4_interface.py | 36 ++++++-- 3 files changed, 106 insertions(+), 31 deletions(-) diff --git a/subiquity/models/network.py b/subiquity/models/network.py index 559e663d..0c5628f7 100644 --- a/subiquity/models/network.py +++ b/subiquity/models/network.py @@ -208,7 +208,7 @@ class NetworkModel(ModelPolicy): return False raise - def configure_iface(self, ifname): + def configure_iface_from_info(self, ifname): iface_info = self.network[ifname] log.debug('iface_info of {}:\n{}'.format(ifname, iface_info)) mac_address = iface_info['hardware']['attrs'].get('address') @@ -243,7 +243,7 @@ class NetworkModel(ModelPolicy): for ifname in self.network.keys(): if self.network[ifname]['type'] not in ignored and \ self.iface_is_up(ifname): - self.configure_iface(ifname) + self.configure_iface_from_info(ifname) return self.configured_interfaces @@ -260,15 +260,73 @@ class NetworkModel(ModelPolicy): log.debug("add_bond: {} as BondAction({})".format( ifname, action)) - def add_subnet(self, ifname, subnet): - if ifname not in self.configured_interfaces: - raise Exception('No such configured interface: {}'.format(ifname)) + def valid_ipv4_address(self, addr): + try: + ip = ipaddress.IPv4Address(addr) + except ipaddress.AddressValueError: + return False + return ip + + def valid_ipv4_network(self, subnet): + try: + nw = ipaddress.IPv4Network(subnet) + except (ipaddress.AddressValueError, + ipaddress.NetmaskValueError): + return False + + return nw + + def add_subnet(self, ifname, subnet_type, network=None, address=None, + gateway=None, nameserver=None, searchpath=None): + if ifname not in self.configured_interfaces: + raise ValueError('No such configured interface: {}'.format(ifname)) + + if subnet_type not in ['static', 'dhcp', 'dhcp6']: + raise ValueError(('Invalid subnet type ') + subnet_type) + + # network = 192.168.9.0/24 + # address = 192.168.9.212 + subnet = { + 'type': subnet_type, + } + + if subnet_type == 'static': + ipaddr = self.valid_ipv4_address(address) + if ipaddr is False: + raise ValueError(('Invalid IP address ') + address) + + ipnet = self.valid_ipv4_network(network) + if ipnet is False: + raise ValueError(('Invalid IP network ') + network) + + ip_network = ipaddress.IPv4Interface("{}/{}".format( + ipaddr.compressed, ipnet.prefixlen)) + subnet.update({'address': ip_network.with_prefixlen}) + + if gateway: + gw = self.valid_ipv4_address(gateway) + if gw is False: + raise ValueError(('Invalid gateway IP ') + gateway) + subnet.update({'gateway': gw.compressed}) + + if nameserver: + subnet.update({'dns_nameserver': nameserver}) + + if searchpath: + subnet.update({'dns_search': searchpath}) + + log.debug('Adding subnet:{}'.format(subnet)) action = self.configured_interfaces[ifname] - if 'subnets' in action: - action['subnets'].extend([subnet]) - else: - action['subnets'] = [subnet] + action.subnets.extend([subnet]) + + def remove_subnets(self, ifname): + if ifname not in self.configured_interfaces: + raise ValueError('No such configured interface: {}'.format(ifname)) + + log.debug('Removing subnets on iface: {}'.format(ifname)) + action = self.configured_interfaces[ifname] + action.subnets = [] def get_default_route(self): if self.default_gateway: @@ -318,5 +376,13 @@ class NetworkModel(ModelPolicy): return 'Unknown Model' def get_iface_info(self, iface): - ipinfo = SimpleInterface(self.network[iface]['ip']) - return (ipinfo, self.get_vendor(iface), self.get_model(iface)) + info = { + 'bonded': self.iface_is_bonded(iface), + 'bridged': self.iface_is_bridge_member(iface), + 'speed': self.iface_get_speed(iface), + 'vendor': self.get_vendor(iface), + 'model': self.get_mode(iface), + 'ip': SimpleInterface(self.network[iface]['ip']) + } + return info + diff --git a/subiquity/ui/views/network.py b/subiquity/ui/views/network.py index 8e2c4438..ba2c6857 100644 --- a/subiquity/ui/views/network.py +++ b/subiquity/ui/views/network.py @@ -75,18 +75,7 @@ class NetworkView(ViewPolicy): col_2 = [] for iface in ifaces: - ifinfo, iface_vendor, iface_model = self.model.get_iface_info( - iface) - bonded = self.model.iface_is_bonded(iface) - bridged = self.model.iface_is_bridge_member(iface) - speed = self.model.iface_get_speed(iface) - info = { - 'bonded': bonded, - 'bridged': bridged, - 'speed': speed, - 'vendor': iface_vendor, - 'model': iface_model, - } + info = self.model.get_iface_info(iface) log.debug('iface info:{}'.format(info)) template = '' if info['bonded']: diff --git a/subiquity/ui/views/network_configure_ipv4_interface.py b/subiquity/ui/views/network_configure_ipv4_interface.py index 46afd387..64539614 100644 --- a/subiquity/ui/views/network_configure_ipv4_interface.py +++ b/subiquity/ui/views/network_configure_ipv4_interface.py @@ -15,7 +15,7 @@ from urwid import Text, Pile, ListBox, Columns from subiquity.view import ViewPolicy -from subiquity.ui.buttons import done_btn, confirm_btn, cancel_btn +from subiquity.ui.buttons import done_btn, menu_btn, cancel_btn from subiquity.ui.utils import Color, Padding from subiquity.ui.interactive import StringEditor import logging @@ -28,9 +28,11 @@ class NetworkConfigureIPv4InterfaceView(ViewPolicy): self.model = model self.signal = signal self.iface = iface - self.gateway_input = StringEditor(caption="") - self.address_input = StringEditor(caption="") - self.subnet_input = StringEditor(caption="") + self.gateway_input = StringEditor(caption="") # FIXME: ipaddr_editor + self.address_input = StringEditor(caption="") # FIXME: ipaddr_editor + self.subnet_input = StringEditor(caption="") # FIXME: ipaddr_editor + self.nameserver_input = StringEditor(caption="") # FIXME: ipaddr_editor + self.searchpath_input = StringEditor(caption="") # FIXME: ipaddr_editor body = [ Padding.center_79(self._build_iface_inputs()), Padding.line_break(""), @@ -74,8 +76,8 @@ class NetworkConfigureIPv4InterfaceView(ViewPolicy): def _build_set_as_default_gw_button(self): ifaces = self.model.get_interfaces() if len(ifaces) > 1: - btn = confirm_btn(label="Set this as default gateway", - on_press=self.set_default_gateway) + btn = menu_btn(label="Set this as default gateway", + on_press=self.set_default_gateway) else: btn = Text("This will be your default gateway") return Pile([btn]) @@ -94,8 +96,26 @@ class NetworkConfigureIPv4InterfaceView(ViewPolicy): ] return Pile(buttons) - def done(self, result): - self.signal.emit_signal('menu:network:main') + def done(self, btn): + result = { + 'subnet_type': 'static', + 'network': self.subnet_input.value, + 'address': self.address_input.value, + 'gateway': self.gateway_input.value, + 'nameserver': self.nameserver_input.value, + 'searchpath': self.searchpath_input.value, + } + try: + self.model.remove_subnets(self.iface) + self.model.add_subnet(self.iface, **result) + except ValueError: + log.exception('Failed to manually configure interface') + self.model.configure_iface_from_info(self.iface) + # FIXME: set error message in UX ala identity + return + + # return + self.signal.prev_signal() def cancel(self, button): self.model.default_gateway = None