diff --git a/plinth/modules/networks/forms.py b/plinth/modules/networks/forms.py index 3467895c5..a5fda1c8c 100644 --- a/plinth/modules/networks/forms.py +++ b/plinth/modules/networks/forms.py @@ -20,6 +20,9 @@ from django.core import validators from gettext import gettext as _ from plinth import network +from gi.repository import NM as nm + +DEFAULT_SELECT_MSG = 'please select' class ConnectionTypeSelectForm(forms.Form): @@ -32,7 +35,17 @@ class ConnectionTypeSelectForm(forms.Form): class AddEthernetForm(forms.Form): """Form to create a new ethernet connection.""" + interfaces = network.get_interface_list(nm.DeviceType.ETHERNET) + interfaces_list = (('', DEFAULT_SELECT_MSG), ) + for interface, mac in interfaces.items(): + displaystring = str(interface + ' (' + mac + ')') + newentry = interfaces_list + ((interface, displaystring), ) + interfaces_list = newentry + name = forms.CharField(label=_('Connection Name')) + interface = forms.ChoiceField( + label=_('Physical Interface'), + choices=interfaces_list) zone = forms.ChoiceField( label=_('Firewall Zone'), help_text=_('The firewall zone will control which services are \ @@ -48,10 +61,26 @@ available over this interfaces. Select Internal only for trusted networks.'), validators=[validators.validate_ipv4_address], required=False) + def clean(self): + """ validate the form fields """ + cleaned_data = super(forms.Form, self).clean() + if DEFAULT_SELECT_MSG == cleaned_data.get('interface'): + raise forms.ValidationError('Please select a interface to be used') + class AddWifiForm(forms.Form): """Form to create a new wifi connection.""" + interfaces = network.get_interface_list(nm.DeviceType.WIFI) + interfaces_list = (('', DEFAULT_SELECT_MSG), ) + for interface, mac in interfaces.items(): + displaystring = str(interface + ' (' + mac + ')') + newentry = interfaces_list + ((interface, displaystring), ) + interfaces_list = newentry + name = forms.CharField(label=_('Connection Name')) + interface = forms.ChoiceField( + label=_('Physical interface'), + choices=interfaces_list) zone = forms.ChoiceField( label=_('Firewall Zone'), help_text=_('The firewall zone will control which services are \ @@ -86,3 +115,9 @@ Point.')) label=_('Address'), validators=[validators.validate_ipv4_address], required=False) + + def clean(self): + """ validate the form fields """ + cleaned_data = super(forms.Form, self).clean() + if DEFAULT_SELECT_MSG == cleaned_data.get('interface'): + raise forms.ValidationError('Please select a interface to be used') diff --git a/plinth/modules/networks/networks.py b/plinth/modules/networks/networks.py index f18eb7c56..8aebc50ab 100644 --- a/plinth/modules/networks/networks.py +++ b/plinth/modules/networks/networks.py @@ -78,12 +78,13 @@ def edit(request, uuid): zone = form.cleaned_data['zone'] ipv4_method = form.cleaned_data['ipv4_method'] ipv4_address = form.cleaned_data['ipv4_address'] + interface = form.cleaned_data['interface'] if connection.get_connection_type() == '802-3-ethernet': network.edit_ethernet_connection( connection, name, zone, - ipv4_method, ipv4_address) + ipv4_method, ipv4_address, interface) elif connection.get_connection_type() == '802-11-wireless': ssid = form.cleaned_data['ssid'] mode = form.cleaned_data['mode'] @@ -93,7 +94,7 @@ def edit(request, uuid): network.edit_wifi_connection( connection, name, zone, ssid, mode, auth_mode, passphrase, - ipv4_method, ipv4_address) + ipv4_method, ipv4_address, interface) return redirect(reverse_lazy('networks:index')) else: @@ -109,6 +110,8 @@ def edit(request, uuid): except KeyError: form_data['zone'] = 'external' + form_data['interface'] = connection.get_interface_name() + form_data['ipv4_method'] = settings_ipv4.get_method() if settings_ipv4.get_num_addresses(): @@ -215,10 +218,11 @@ def add_ethernet(request): zone = form.cleaned_data['zone'] ipv4_method = form.cleaned_data['ipv4_method'] ipv4_address = form.cleaned_data['ipv4_address'] + interface = form.cleaned_data['interface'] network.add_ethernet_connection( name, zone, - ipv4_method, ipv4_address) + ipv4_method, ipv4_address, interface) return redirect(reverse_lazy('networks:index')) else: form = AddEthernetForm() @@ -253,11 +257,12 @@ def add_wifi(request, ssid=None): passphrase = form.cleaned_data['passphrase'] ipv4_method = form.cleaned_data['ipv4_method'] ipv4_address = form.cleaned_data['ipv4_address'] + interface = form.cleaned_data['interface'] network.add_wifi_connection( name, zone, ssid, mode, auth_mode, passphrase, - ipv4_method, ipv4_address) + ipv4_method, ipv4_address, interface) return redirect(reverse_lazy('networks:index')) else: if form_data: diff --git a/plinth/network.py b/plinth/network.py index a6aa0bc2a..cd4730058 100644 --- a/plinth/network.py +++ b/plinth/network.py @@ -64,6 +64,15 @@ def _commit_callback(connection, error, data=None): del data +def get_interface_list(type): + """Get a list of Linux devices which are available on this system""" + interfaces = {} + for device in nm.Client.new(None).get_devices(): + if device.get_device_type() == type: + interfaces[device.get_iface()] = device.get_hw_address() + return interfaces + + def get_connection_list(): """Get a list of active and available connections.""" active_uuids = [] @@ -118,7 +127,7 @@ def get_active_connection(connection_uuid): def _update_common_settings(connection, connection_uuid, name, type_, zone, - ipv4_method, ipv4_address): + ipv4_method, ipv4_address, interface): """Create/edit basic settings for network manager connections.""" if not connection: connection = nm.SimpleConnection.new() @@ -133,7 +142,7 @@ def _update_common_settings(connection, connection_uuid, name, type_, zone, settings.set_property(nm.SETTING_CONNECTION_TYPE, type_) settings.set_property(nm.SETTING_CONNECTION_ZONE, zone) settings.set_property(nm.SETTING_CONNECTION_UUID, connection_uuid) - + settings.set_property(nm.SETTING_CONNECTION_INTERFACE_NAME, interface) # IPv4 settings = connection.get_setting_ip4_config() if not settings: @@ -156,12 +165,13 @@ def _update_common_settings(connection, connection_uuid, name, type_, zone, def _update_ethernet_settings(connection, connection_uuid, name, zone, - ipv4_method, ipv4_address): + ipv4_method, ipv4_address, interface): """Create/edit ethernet settings for network manager connections.""" type_ = '802-3-ethernet' connection = _update_common_settings(connection, connection_uuid, name, - type_, zone, ipv4_method, ipv4_address) + type_, zone, ipv4_method, + ipv4_address, interface) # Ethernet settings = connection.get_setting_wired() @@ -172,36 +182,39 @@ def _update_ethernet_settings(connection, connection_uuid, name, zone, return connection -def add_ethernet_connection(name, zone, ipv4_method, ipv4_address): +def add_ethernet_connection(name, zone, ipv4_method, ipv4_address, interface): """Add an automatic ethernet connection in network manager. Return the UUID for the connection. """ connection_uuid = str(uuid.uuid4()) connection = _update_ethernet_settings( - None, connection_uuid, name, zone, ipv4_method, ipv4_address) + None, connection_uuid, name, zone, ipv4_method, + ipv4_address, interface) client = nm.Client.new(None) client.add_connection_async(connection, True, None, _callback, None) return connection_uuid def edit_ethernet_connection(connection, name, zone, ipv4_method, - ipv4_address): + ipv4_address, interface): """Edit an existing ethernet connection in network manager.""" _update_ethernet_settings( connection, connection.get_uuid(), name, zone, ipv4_method, - ipv4_address) + ipv4_address, interface) connection.commit_changes(True) def _update_wifi_settings(connection, connection_uuid, name, zone, ssid, mode, - auth_mode, passphrase, ipv4_method, ipv4_address): + auth_mode, passphrase, ipv4_method, + ipv4_address, interface): """Create/edit wifi settings for network manager connections.""" type_ = '802-11-wireless' key_mgmt = 'wpa-psk' connection = _update_common_settings(connection, connection_uuid, name, - type_, zone, ipv4_method, ipv4_address) + type_, zone, ipv4_method, + ipv4_address, interface) # Wireless settings = connection.get_setting_wireless() @@ -229,7 +242,7 @@ def _update_wifi_settings(connection, connection_uuid, name, zone, ssid, mode, def add_wifi_connection(name, zone, ssid, mode, auth_mode, passphrase, - ipv4_method, ipv4_address): + ipv4_method, ipv4_address, interface): """Add an automatic Wi-Fi connection in network manager. Return the UUID for the connection. @@ -237,7 +250,7 @@ def add_wifi_connection(name, zone, ssid, mode, auth_mode, passphrase, connection_uuid = str(uuid.uuid4()) connection = _update_wifi_settings( None, connection_uuid, name, zone, ssid, mode, auth_mode, passphrase, - ipv4_method, ipv4_address) + ipv4_method, ipv4_address, interface) client = nm.Client.new(None) client.add_connection_async(connection, True, None, _callback, None) return connection_uuid @@ -245,11 +258,11 @@ def add_wifi_connection(name, zone, ssid, mode, auth_mode, passphrase, def edit_wifi_connection(connection, name, zone, ssid, mode, auth_mode, passphrase, - ipv4_method, ipv4_address): + ipv4_method, ipv4_address, interface): """Edit an existing wifi connection in network manager.""" _update_wifi_settings( connection, connection.get_uuid(), name, zone, ssid, mode, auth_mode, - passphrase, ipv4_method, ipv4_address) + passphrase, ipv4_method, ipv4_address, interface) connection.commit_changes(True)