Merge pull request #154 from CanonicalLtd/mwhudson/wifi-ui
Add a basic UI for entering wifi config details.
This commit is contained in:
commit
e608362b34
|
@ -29,7 +29,8 @@ from subiquitycore.ui.views import (NetworkView,
|
|||
NetworkSetDefaultRouteView,
|
||||
NetworkBondInterfacesView,
|
||||
NetworkConfigureInterfaceView,
|
||||
NetworkConfigureIPv4InterfaceView)
|
||||
NetworkConfigureIPv4InterfaceView,
|
||||
NetworkConfigureWLANView)
|
||||
from subiquitycore.ui.views.network import ApplyingConfigWidget
|
||||
from subiquitycore.ui.dummy import DummyView
|
||||
from subiquitycore.controller import BaseController
|
||||
|
@ -289,6 +290,14 @@ class NetworkController(BaseController):
|
|||
self.signal,
|
||||
iface))
|
||||
|
||||
def network_configure_wlan_interface(self, iface):
|
||||
self.model.prev_signal = ('Back to configure interface menu',
|
||||
'network:configure-interface-menu',
|
||||
'network_configure_interface')
|
||||
self.ui.set_header("Network interface {} manual IPv4 "
|
||||
"configuration".format(iface))
|
||||
self.ui.set_body(NetworkConfigureWLANView(self.model, self.signal, iface))
|
||||
|
||||
def network_configure_ipv6_interface(self, iface):
|
||||
self.model.prev_signal = ('Back to configure interface menu',
|
||||
'network:configure-interface-menu',
|
||||
|
|
|
@ -43,6 +43,8 @@ class Networkdev():
|
|||
self.search_domains = []
|
||||
self.nameservers = []
|
||||
self.gateway = None
|
||||
self.essid = None
|
||||
self.wpa_psk = None
|
||||
|
||||
def configure(self, probe_info=None):
|
||||
log.debug('Configuring iface {}'.format(self.ifname))
|
||||
|
@ -53,6 +55,9 @@ class Networkdev():
|
|||
def configure_from_info(self):
|
||||
log.debug('configuring netdev from info source')
|
||||
|
||||
if self.iftype == 'wlan':
|
||||
self.essid = self.probe_info.raw['essid']
|
||||
|
||||
ip_info = self.probe_info.ip
|
||||
|
||||
sources = ip_info.get('sources', None)
|
||||
|
@ -113,6 +118,15 @@ class Networkdev():
|
|||
if self.iftype == 'bond':
|
||||
result[self.ifname]['interfaces'] = self.probe_info.bond['slaves']
|
||||
|
||||
if self.iftype == 'wlan':
|
||||
if self.essid is not None:
|
||||
aps = result[self.ifname]['access-points'] = {}
|
||||
ap = aps[self.essid] = {
|
||||
'mode': 'infrastructure',
|
||||
}
|
||||
if self.wpa_psk is not None:
|
||||
ap['password'] = self.wpa_psk
|
||||
|
||||
return result
|
||||
|
||||
@property
|
||||
|
@ -284,7 +298,10 @@ class NetworkModel(BaseModel):
|
|||
'network_configure_interface'),
|
||||
('Network configure ipv4 interface',
|
||||
base_signal + ':configure-ipv4-interface',
|
||||
'network_configure_ipv4_interface')
|
||||
'network_configure_ipv4_interface'),
|
||||
('Network configure wlan interface',
|
||||
base_signal + ':configure-wlan-interface',
|
||||
'network_configure_wlan_interface'),
|
||||
]
|
||||
|
||||
additional_options = [
|
||||
|
@ -640,15 +657,20 @@ class NetworkModel(BaseModel):
|
|||
}
|
||||
ethernets = {}
|
||||
bonds = {}
|
||||
wifis = {}
|
||||
for iface in self.devices.values():
|
||||
if iface.iftype == 'eth':
|
||||
ethernets.update(iface.render())
|
||||
if iface.iftype == 'bond':
|
||||
bonds.update(iface.render())
|
||||
if iface.iftype == 'wlan':
|
||||
wifis.update(iface.render())
|
||||
if any(ethernets):
|
||||
config['network']['ethernets'] = ethernets
|
||||
if any(bonds):
|
||||
config['network']['bonds'] = bonds
|
||||
if any(wifis):
|
||||
config['network']['wifis'] = wifis
|
||||
|
||||
routes = self.get_default_route()
|
||||
nw_routes = []
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
from .network import NetworkView # NOQA
|
||||
from .network_default_route import NetworkSetDefaultRouteView # NOQA
|
||||
from .network_configure_interface import NetworkConfigureInterfaceView # NOQA
|
||||
from .network_configure_interface import NetworkConfigureInterfaceView, NetworkConfigureWLANView # NOQA
|
||||
from .network_configure_ipv4_interface import NetworkConfigureIPv4InterfaceView # NOQA
|
||||
from .network_bond_interfaces import NetworkBondInterfacesView # NOQA
|
||||
from .welcome import CoreWelcomeView as WelcomeView # NOQA
|
||||
|
|
|
@ -177,6 +177,12 @@ class NetworkView(BaseView):
|
|||
col_1.append(Text(""))
|
||||
col_2.append(Color.info_primary(Text(template)))
|
||||
|
||||
if interface.iftype == 'wlan':
|
||||
if interface.essid is not None:
|
||||
col_2.append(Text("Associated to '" + interface.essid + "'"))
|
||||
else:
|
||||
col_2.append(Text("Not associated."))
|
||||
|
||||
# Other device info (MAC, vendor/model, speed)
|
||||
info = self.model.get_iface_info(iface)
|
||||
hwaddr = self.model.get_hw_addr(iface)
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from urwid import Text, Pile, ListBox
|
||||
from urwid import Text, Pile, ListBox, Columns
|
||||
from subiquitycore.view import BaseView
|
||||
from subiquitycore.ui.buttons import done_btn, menu_btn
|
||||
from subiquitycore.ui.buttons import cancel_btn, done_btn, menu_btn
|
||||
from subiquitycore.ui.interactive import PasswordEditor, StringEditor
|
||||
from subiquitycore.ui.utils import Color, Padding
|
||||
import logging
|
||||
|
||||
|
@ -28,11 +29,28 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
self.signal = signal
|
||||
self.iface = iface
|
||||
self.iface_obj = self.model.get_interface(iface)
|
||||
self._build_widgets()
|
||||
super().__init__(ListBox(self._build_body()))
|
||||
|
||||
def _build_widgets(self):
|
||||
self.ipv4_info = Pile(self._build_gateway_ipv4_info())
|
||||
self.ipv4_method = Pile(self._build_ipv4_method_buttons())
|
||||
self.ipv6_info = Pile(self._build_gateway_ipv6_info())
|
||||
self.ipv6_method = Pile(self._build_ipv6_method_buttons())
|
||||
body = [
|
||||
if self.iface_obj.type == 'wlan':
|
||||
self.wifi_info = Pile(self._build_wifi_info())
|
||||
self.wifi_method = Pile(self._build_wifi_config())
|
||||
|
||||
|
||||
def _build_body(self):
|
||||
body = []
|
||||
if self.iface_obj.type == 'wlan':
|
||||
body.extend([
|
||||
Padding.center_79(self.wifi_info),
|
||||
Padding.center_79(self.wifi_method),
|
||||
Padding.line_break(""),
|
||||
])
|
||||
body.extend([
|
||||
Padding.center_79(self.ipv4_info),
|
||||
Padding.center_79(self.ipv4_method),
|
||||
Padding.line_break(""),
|
||||
|
@ -41,8 +59,8 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
Padding.center_79(self.ipv6_method),
|
||||
Padding.line_break(""),
|
||||
Padding.fixed_10(self._build_buttons())
|
||||
]
|
||||
super().__init__(ListBox(body))
|
||||
])
|
||||
return body
|
||||
|
||||
def _build_gateway_ipv4_info(self):
|
||||
addresses = self.iface_obj.ipv4_addresses
|
||||
|
@ -140,6 +158,17 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
|
||||
return buttons
|
||||
|
||||
|
||||
def _build_wifi_info(self):
|
||||
if self.iface_obj.essid is not None:
|
||||
return [Text("Will associate with '%s'" % (self.iface_obj.essid,))]
|
||||
else:
|
||||
return [Text("No access point configured.")]
|
||||
|
||||
def _build_wifi_config(self):
|
||||
return [Padding.left_40(menu_btn(label="Configure WIFI settings",
|
||||
on_press=self.show_wlan_configuration))]
|
||||
|
||||
def _build_buttons(self):
|
||||
done = done_btn(on_press=self.done)
|
||||
|
||||
|
@ -172,6 +201,10 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
self.iface_obj.dhcp6 = True
|
||||
self.update_interface()
|
||||
|
||||
def show_wlan_configuration(self, btn):
|
||||
self.signal.emit_signal(
|
||||
'menu:network:main:configure-wlan-interface', self.iface)
|
||||
|
||||
def show_ipv4_configuration(self, btn):
|
||||
self.signal.emit_signal(
|
||||
'menu:network:main:configure-ipv4-interface', self.iface)
|
||||
|
@ -184,3 +217,65 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
|
||||
def done(self, result):
|
||||
self.signal.prev_signal()
|
||||
|
||||
|
||||
class NetworkConfigureWLANView(BaseView):
|
||||
def __init__(self, model, signal, iface):
|
||||
self.model = model
|
||||
self.signal = signal
|
||||
self.iface = iface
|
||||
self.iface_obj = self.model.get_interface(iface)
|
||||
self.essid_input = StringEditor(caption="")
|
||||
self.psk_input = PasswordEditor(caption="")
|
||||
self.body = [
|
||||
Padding.center_79(self._build_iface_inputs()),
|
||||
Padding.line_break(""),
|
||||
Padding.fixed_10(self._build_buttons())
|
||||
]
|
||||
super().__init__(ListBox(self.body))
|
||||
|
||||
def _build_iface_inputs(self):
|
||||
col = [
|
||||
Padding.center_79(Color.info_minor(Text("Only open or WPA2/PSK networks are supported at this time."))),
|
||||
Padding.line_break(""),
|
||||
Columns(
|
||||
[
|
||||
("weight", 0.2, Text("Network name:")),
|
||||
("weight", 0.3,
|
||||
Color.string_input(self.essid_input,
|
||||
focus_map="string_input focus")),
|
||||
], dividechars=2
|
||||
),
|
||||
Columns(
|
||||
[
|
||||
("weight", 0.2, Text("Password:")),
|
||||
("weight", 0.3,
|
||||
Color.string_input(self.psk_input,
|
||||
focus_map="string_input focus")),
|
||||
], dividechars=2
|
||||
),
|
||||
]
|
||||
return Pile(col)
|
||||
|
||||
def _build_buttons(self):
|
||||
cancel = Color.button(cancel_btn(on_press=self.cancel),
|
||||
focus_map='button focus')
|
||||
done = Color.button(done_btn(on_press=self.done),
|
||||
focus_map='button focus')
|
||||
|
||||
buttons = [done, cancel]
|
||||
return Pile(buttons, focus_item=done)
|
||||
|
||||
def done(self, btn):
|
||||
if self.iface_obj.essid is None and self.essid_input.value:
|
||||
# Turn DHCP4 on by default when specifying an ESSID for the first time...
|
||||
self.iface_obj.dhcp4 = True
|
||||
if self.essid_input.value:
|
||||
self.iface_obj.essid = self.essid_input.value
|
||||
else:
|
||||
self.iface_obj.essid = None
|
||||
self.iface_obj.wpa_psk = self.psk_input.value
|
||||
self.signal.prev_signal()
|
||||
|
||||
def cancel(self, btn):
|
||||
self.signal.prev_signal()
|
||||
|
|
Loading…
Reference in New Issue