mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-20 10:34:30 +00:00
Rename network module to networks.
Move networkmanager helper functions into a new file. Add some network tests.
This commit is contained in:
parent
c6a2e6abd7
commit
9b201a2daf
@ -1 +0,0 @@
|
|||||||
plinth.modules.network
|
|
||||||
1
data/etc/plinth/modules-enabled/networks
Normal file
1
data/etc/plinth/modules-enabled/networks
Normal file
@ -0,0 +1 @@
|
|||||||
|
plinth.modules.networks
|
||||||
@ -1,435 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is part of Plinth.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# 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 dbus.exceptions import DBusException
|
|
||||||
from django.contrib import messages
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.core.urlresolvers import reverse_lazy
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
from django.template.response import TemplateResponse
|
|
||||||
from gettext import gettext as _
|
|
||||||
import NetworkManager
|
|
||||||
import uuid
|
|
||||||
import urllib
|
|
||||||
|
|
||||||
from .forms import CONNECTION_TYPE_NAMES, ConnectionTypeSelectForm, \
|
|
||||||
AddEthernetForm, AddWifiForm
|
|
||||||
from plinth import cfg
|
|
||||||
|
|
||||||
|
|
||||||
subsubmenu = [{'url': reverse_lazy('network:index'),
|
|
||||||
'text': _('Network Connections')},
|
|
||||||
{'url': reverse_lazy('network:add'),
|
|
||||||
'text': _('Add Connection')}]
|
|
||||||
|
|
||||||
|
|
||||||
def init():
|
|
||||||
"""Initialize the Network module."""
|
|
||||||
menu = cfg.main_menu.get('system:index')
|
|
||||||
menu.add_urlname(_('Network'), 'glyphicon-signal', 'network:index', 18)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def index(request):
|
|
||||||
"""Show connection list."""
|
|
||||||
connections = get_connection_list()
|
|
||||||
|
|
||||||
return TemplateResponse(request, 'connections_list.html',
|
|
||||||
{'title': _('Network Connections'),
|
|
||||||
'subsubmenu': subsubmenu,
|
|
||||||
'connections': connections})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def edit(request, conn_id):
|
|
||||||
"""Serve connection editing form."""
|
|
||||||
form = None
|
|
||||||
name = urllib.parse.unquote_plus(conn_id)
|
|
||||||
form_data = {'name': name}
|
|
||||||
|
|
||||||
conn = get_connection(name)
|
|
||||||
if not conn:
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
_('Cannot edit connection: %s not found.') % name)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
settings = conn.GetSettings()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
if settings['connection']['type'] == '802-11-wireless':
|
|
||||||
form = AddWifiForm(request.POST)
|
|
||||||
else:
|
|
||||||
form = AddEthernetForm(request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
name = form.cleaned_data['name']
|
|
||||||
ipv4_method = form.cleaned_data['ipv4_method']
|
|
||||||
ipv4_address = form.cleaned_data['ipv4_address']
|
|
||||||
|
|
||||||
if settings['connection']['type'] == '802-3-ethernet':
|
|
||||||
_edit_ethernet_connection(conn, name, ipv4_method, ipv4_address)
|
|
||||||
elif settings['connection']['type'] == '802-11-wireless':
|
|
||||||
ssid = form.cleaned_data['ssid']
|
|
||||||
_edit_wifi_connection(conn, name, ssid, ipv4_method, ipv4_address)
|
|
||||||
else:
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
_('Cannot edit connection %s: '
|
|
||||||
'Connection type not supported.') % name)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
else:
|
|
||||||
form_data['ipv4_method'] = settings['ipv4']['method']
|
|
||||||
|
|
||||||
if settings['ipv4']['addresses']:
|
|
||||||
form_data['ipv4_address'] = settings['ipv4']['addresses'][0][0]
|
|
||||||
|
|
||||||
if settings['connection']['type'] == '802-11-wireless':
|
|
||||||
form_data['ssid'] = settings['802-11-wireless']['ssid']
|
|
||||||
form = AddWifiForm(form_data)
|
|
||||||
else:
|
|
||||||
form = AddEthernetForm(form_data)
|
|
||||||
|
|
||||||
return TemplateResponse(request, 'connections_edit.html',
|
|
||||||
{'title': _('Edit Connection'),
|
|
||||||
'subsubmenu': subsubmenu,
|
|
||||||
'form': form})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def activate(request, conn_id):
|
|
||||||
"""Activate the connection."""
|
|
||||||
name = urllib.parse.unquote_plus(conn_id)
|
|
||||||
|
|
||||||
try:
|
|
||||||
_activate_connection(name)
|
|
||||||
except ConnectionNotFound as cnf:
|
|
||||||
messages.error(request, cnf)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
except DeviceNotFound as dnf:
|
|
||||||
messages.error(request, dnf)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
|
|
||||||
messages.success(request, _('Activated connection %s.') % name)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def deactivate(request, conn_id):
|
|
||||||
"""Deactivate the connection."""
|
|
||||||
name = urllib.parse.unquote_plus(conn_id)
|
|
||||||
try:
|
|
||||||
_deactivate_connection(name)
|
|
||||||
messages.success(request, _('Deactivated connection %s.') % name)
|
|
||||||
except ConnectionNotFound as cnf:
|
|
||||||
messages.error(request, cnf)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add(request):
|
|
||||||
"""Serve the connection type selection form."""
|
|
||||||
form = None
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
form = ConnectionTypeSelectForm(request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
conn_type = form.cleaned_data['conn_type']
|
|
||||||
if conn_type == '802-3-ethernet':
|
|
||||||
return redirect(reverse_lazy('network:add_ethernet'))
|
|
||||||
elif conn_type == '802-11-wireless':
|
|
||||||
return redirect(reverse_lazy('network:add_wifi'))
|
|
||||||
else:
|
|
||||||
form = ConnectionTypeSelectForm()
|
|
||||||
return TemplateResponse(request, 'connections_type_select.html',
|
|
||||||
{'title': _('Add Connection'),
|
|
||||||
'subsubmenu': subsubmenu,
|
|
||||||
'form': form})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_ethernet(request):
|
|
||||||
"""Serve ethernet connection create form."""
|
|
||||||
form = None
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
form = AddEthernetForm(request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
name = form.cleaned_data['name']
|
|
||||||
ipv4_method = form.cleaned_data['ipv4_method']
|
|
||||||
ipv4_address = form.cleaned_data['ipv4_address']
|
|
||||||
|
|
||||||
_add_ethernet_connection(name, ipv4_method, ipv4_address)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
else:
|
|
||||||
form = AddEthernetForm()
|
|
||||||
|
|
||||||
return TemplateResponse(request, 'connections_create.html',
|
|
||||||
{'title': _('Editing New Ethernet Connection'),
|
|
||||||
'subsubmenu': subsubmenu,
|
|
||||||
'form': form})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_wifi(request):
|
|
||||||
"""Serve wifi connection create form."""
|
|
||||||
form = None
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
form = AddWifiForm(request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
name = form.cleaned_data['name']
|
|
||||||
ssid = form.cleaned_data['ssid']
|
|
||||||
ipv4_method = form.cleaned_data['ipv4_method']
|
|
||||||
ipv4_address = form.cleaned_data['ipv4_address']
|
|
||||||
|
|
||||||
_add_wifi_connection(name, ssid, ipv4_method, ipv4_address)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
else:
|
|
||||||
form = AddWifiForm()
|
|
||||||
|
|
||||||
return TemplateResponse(request, 'connections_create.html',
|
|
||||||
{'title': _('Editing New Wi-Fi Connection'),
|
|
||||||
'subsubmenu': subsubmenu,
|
|
||||||
'form': form})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def delete(request, conn_id):
|
|
||||||
"""Handle deleting connections, showing a confirmation dialog first.
|
|
||||||
|
|
||||||
On GET, display a confirmation page.
|
|
||||||
On POST, delete the connection.
|
|
||||||
"""
|
|
||||||
name = urllib.parse.unquote_plus(conn_id)
|
|
||||||
if request.method == 'POST':
|
|
||||||
try:
|
|
||||||
_delete_connection(name)
|
|
||||||
except ConnectionNotFound as cnf:
|
|
||||||
messages.error(request, cnf)
|
|
||||||
else:
|
|
||||||
messages.success(request, _('Connection %s deleted.') % name)
|
|
||||||
return redirect(reverse_lazy('network:index'))
|
|
||||||
|
|
||||||
return TemplateResponse(request, 'connections_delete.html',
|
|
||||||
{'title': _('Delete Connection'),
|
|
||||||
'subsubmenu': subsubmenu,
|
|
||||||
'name': name})
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectionNotFound(Exception):
|
|
||||||
def __init__(self, msg):
|
|
||||||
self.msg = msg
|
|
||||||
def __str__(self):
|
|
||||||
return self.msg
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceNotFound(Exception):
|
|
||||||
def __init__(self, msg):
|
|
||||||
self.msg = msg
|
|
||||||
def __str__(self):
|
|
||||||
return self.msg
|
|
||||||
|
|
||||||
|
|
||||||
def get_connection_list():
|
|
||||||
"""Get a list of active and available connections."""
|
|
||||||
connections = []
|
|
||||||
active = []
|
|
||||||
|
|
||||||
for conn in NetworkManager.NetworkManager.ActiveConnections:
|
|
||||||
try:
|
|
||||||
settings = conn.Connection.GetSettings()['connection']
|
|
||||||
except DBusException:
|
|
||||||
# DBusException can be thrown here if the index is quickly loaded
|
|
||||||
# after a connection is deactivated.
|
|
||||||
continue
|
|
||||||
active.append(settings['id'])
|
|
||||||
|
|
||||||
for conn in NetworkManager.Settings.ListConnections():
|
|
||||||
settings = conn.GetSettings()['connection']
|
|
||||||
# Display a friendly type name if known.
|
|
||||||
conn_type = CONNECTION_TYPE_NAMES.get(settings['type'],
|
|
||||||
settings['type'])
|
|
||||||
connections.append({
|
|
||||||
'name': settings['id'],
|
|
||||||
'id': urllib.parse.quote_plus(settings['id']),
|
|
||||||
'type': conn_type,
|
|
||||||
'is_active': settings['id'] in active,
|
|
||||||
})
|
|
||||||
connections.sort(key=lambda x: x['is_active'], reverse=True)
|
|
||||||
return connections
|
|
||||||
|
|
||||||
|
|
||||||
def get_connection(name):
|
|
||||||
"""Returns connection with id matching name.
|
|
||||||
Returns None if not found.
|
|
||||||
"""
|
|
||||||
connections = NetworkManager.Settings.ListConnections()
|
|
||||||
connections = dict([(x.GetSettings()['connection']['id'], x)
|
|
||||||
for x in connections])
|
|
||||||
return connections.get(name)
|
|
||||||
|
|
||||||
|
|
||||||
def get_active_connection(name):
|
|
||||||
"""Returns active connection with id matching name.
|
|
||||||
Returns None if not found.
|
|
||||||
"""
|
|
||||||
connections = NetworkManager.NetworkManager.ActiveConnections
|
|
||||||
connections = dict([(x.Connection.GetSettings()['connection']['id'], x)
|
|
||||||
for x in connections])
|
|
||||||
return connections.get(name)
|
|
||||||
|
|
||||||
|
|
||||||
def _edit_ethernet_connection(conn, name, ipv4_method, ipv4_address):
|
|
||||||
settings = conn.GetSettings()
|
|
||||||
|
|
||||||
new_settings = {
|
|
||||||
'connection': {
|
|
||||||
'id': name,
|
|
||||||
'type': settings['connection']['type'],
|
|
||||||
'uuid': settings['connection']['uuid'],
|
|
||||||
},
|
|
||||||
'802-3-ethernet': {},
|
|
||||||
'ipv4': {'method': ipv4_method},
|
|
||||||
}
|
|
||||||
if ipv4_method == 'manual' and ipv4_address:
|
|
||||||
new_settings['ipv4']['addresses'] = [
|
|
||||||
(ipv4_address,
|
|
||||||
24, # CIDR prefix length
|
|
||||||
'0.0.0.0')] # gateway
|
|
||||||
|
|
||||||
conn.Update(new_settings)
|
|
||||||
|
|
||||||
|
|
||||||
def _edit_wifi_connection(conn, name, ssid, ipv4_method, ipv4_address):
|
|
||||||
settings = conn.GetSettings()
|
|
||||||
|
|
||||||
new_settings = {
|
|
||||||
'connection': {
|
|
||||||
'id': name,
|
|
||||||
'type': settings['connection']['type'],
|
|
||||||
'uuid': settings['connection']['uuid'],
|
|
||||||
},
|
|
||||||
'802-11-wireless': {
|
|
||||||
'ssid': ssid,
|
|
||||||
},
|
|
||||||
'ipv4': {'method': ipv4_method},
|
|
||||||
}
|
|
||||||
if ipv4_method == 'manual' and ipv4_address:
|
|
||||||
new_settings['ipv4']['addresses'] = [
|
|
||||||
(ipv4_address,
|
|
||||||
24, # CIDR prefix length
|
|
||||||
'0.0.0.0')] # gateway
|
|
||||||
|
|
||||||
conn.Update(new_settings)
|
|
||||||
|
|
||||||
|
|
||||||
def _activate_connection(name):
|
|
||||||
# Find the connection
|
|
||||||
conn = get_connection(name)
|
|
||||||
if not conn:
|
|
||||||
raise ConnectionNotFound(
|
|
||||||
_('Failed to activate connection %s: '
|
|
||||||
'Connection not found.') % name)
|
|
||||||
|
|
||||||
# Find a suitable device
|
|
||||||
ctype = conn.GetSettings()['connection']['type']
|
|
||||||
if ctype == 'vpn':
|
|
||||||
for dev in NetworkManager.NetworkManager.GetDevices():
|
|
||||||
if (dev.State == NetworkManager.NM_DEVICE_STATE_ACTIVATED
|
|
||||||
and dev.Managed):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise DeviceNotFound(
|
|
||||||
_('Failed to activate connection %s: '
|
|
||||||
'No suitable device is available.') % name)
|
|
||||||
else:
|
|
||||||
dtype = {
|
|
||||||
'802-11-wireless': NetworkManager.NM_DEVICE_TYPE_WIFI,
|
|
||||||
'802-3-ethernet': NetworkManager.NM_DEVICE_TYPE_ETHERNET,
|
|
||||||
'gsm': NetworkManager.NM_DEVICE_TYPE_MODEM,
|
|
||||||
}.get(ctype, ctype)
|
|
||||||
|
|
||||||
for dev in NetworkManager.NetworkManager.GetDevices():
|
|
||||||
if (dev.DeviceType == dtype
|
|
||||||
and dev.State == NetworkManager.NM_DEVICE_STATE_DISCONNECTED):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise DeviceNotFound(
|
|
||||||
_('Failed to activate connection %s: '
|
|
||||||
'No suitable device is available.') % name)
|
|
||||||
|
|
||||||
NetworkManager.NetworkManager.ActivateConnection(conn, dev, "/")
|
|
||||||
|
|
||||||
|
|
||||||
def _deactivate_connection(name):
|
|
||||||
active = get_active_connection(name)
|
|
||||||
if active:
|
|
||||||
NetworkManager.NetworkManager.DeactivateConnection(active)
|
|
||||||
else:
|
|
||||||
raise ConnectionNotFound(
|
|
||||||
_('Failed to deactivate connection %s: '
|
|
||||||
'Connection not found.') % name)
|
|
||||||
|
|
||||||
|
|
||||||
def _add_ethernet_connection(name, ipv4_method, ipv4_address):
|
|
||||||
conn = {
|
|
||||||
'connection': {
|
|
||||||
'id': name,
|
|
||||||
'type': '802-3-ethernet',
|
|
||||||
'uuid': str(uuid.uuid4()),
|
|
||||||
},
|
|
||||||
'802-3-ethernet': {},
|
|
||||||
'ipv4': {'method': ipv4_method},
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipv4_method == 'manual':
|
|
||||||
conn['ipv4']['addresses'] = [
|
|
||||||
(ipv4_address,
|
|
||||||
24, # CIDR prefix length
|
|
||||||
'0.0.0.0')] # gateway
|
|
||||||
|
|
||||||
NetworkManager.Settings.AddConnection(conn)
|
|
||||||
|
|
||||||
|
|
||||||
def _add_wifi_connection(name, ssid, ipv4_method, ipv4_address):
|
|
||||||
conn = {
|
|
||||||
'connection': {
|
|
||||||
'id': name,
|
|
||||||
'type': '802-11-wireless',
|
|
||||||
'uuid': str(uuid.uuid4()),
|
|
||||||
},
|
|
||||||
'802-11-wireless': {
|
|
||||||
'ssid': ssid,
|
|
||||||
},
|
|
||||||
'ipv4': {'method': ipv4_method},
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipv4_method == 'manual':
|
|
||||||
conn['ipv4']['addresses'] = [
|
|
||||||
(ipv4_address,
|
|
||||||
24, # CIDR prefix length
|
|
||||||
'0.0.0.0')] # gateway
|
|
||||||
|
|
||||||
NetworkManager.Settings.AddConnection(conn)
|
|
||||||
|
|
||||||
|
|
||||||
def _delete_connection(name):
|
|
||||||
conn = get_connection(name)
|
|
||||||
if not conn:
|
|
||||||
raise ConnectionNotFound(
|
|
||||||
_('Failed to delete connection %s: '
|
|
||||||
'Connection not found.') % name)
|
|
||||||
conn.Delete()
|
|
||||||
@ -19,9 +19,9 @@
|
|||||||
Plinth module to interface with network-manager
|
Plinth module to interface with network-manager
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from . import network
|
from . import networks
|
||||||
from .network import init
|
from .networks import init
|
||||||
|
|
||||||
__all__ = ['network', 'init']
|
__all__ = ['networks', 'init']
|
||||||
|
|
||||||
depends = ['plinth.modules.system']
|
depends = ['plinth.modules.system']
|
||||||
@ -18,18 +18,14 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
|
||||||
|
from plinth import network
|
||||||
CONNECTION_TYPE_NAMES = {
|
|
||||||
'802-3-ethernet': 'Ethernet',
|
|
||||||
'802-11-wireless': 'Wi-Fi',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectionTypeSelectForm(forms.Form):
|
class ConnectionTypeSelectForm(forms.Form):
|
||||||
"""Form to select type for new connection."""
|
"""Form to select type for new connection."""
|
||||||
conn_type = forms.ChoiceField(
|
conn_type = forms.ChoiceField(
|
||||||
label=_('Connection Type'),
|
label=_('Connection Type'),
|
||||||
choices=[(k, v) for k, v in CONNECTION_TYPE_NAMES.items()])
|
choices=[(k, v) for k, v in network.CONNECTION_TYPE_NAMES.items()])
|
||||||
|
|
||||||
|
|
||||||
class AddEthernetForm(forms.Form):
|
class AddEthernetForm(forms.Form):
|
||||||
227
plinth/modules/networks/networks.py
Normal file
227
plinth/modules/networks/networks.py
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# 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 dbus.exceptions import DBusException
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.core.urlresolvers import reverse_lazy
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.template.response import TemplateResponse
|
||||||
|
from gettext import gettext as _
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
from .forms import ConnectionTypeSelectForm, AddEthernetForm, AddWifiForm
|
||||||
|
from plinth import cfg
|
||||||
|
from plinth import network
|
||||||
|
|
||||||
|
|
||||||
|
subsubmenu = [{'url': reverse_lazy('networks:index'),
|
||||||
|
'text': _('Network Connections')},
|
||||||
|
{'url': reverse_lazy('networks:add'),
|
||||||
|
'text': _('Add Connection')}]
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
"""Initialize the Networks module."""
|
||||||
|
menu = cfg.main_menu.get('system:index')
|
||||||
|
menu.add_urlname(_('Networks'), 'glyphicon-signal', 'networks:index', 18)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def index(request):
|
||||||
|
"""Show connection list."""
|
||||||
|
connections = network.get_connection_list()
|
||||||
|
|
||||||
|
return TemplateResponse(request, 'connections_list.html',
|
||||||
|
{'title': _('Network Connections'),
|
||||||
|
'subsubmenu': subsubmenu,
|
||||||
|
'connections': connections})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def edit(request, conn_id):
|
||||||
|
"""Serve connection editing form."""
|
||||||
|
form = None
|
||||||
|
name = urllib.parse.unquote_plus(conn_id)
|
||||||
|
form_data = {'name': name}
|
||||||
|
|
||||||
|
conn = network.get_connection(name)
|
||||||
|
if not conn:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_('Cannot edit connection: %s not found.') % name)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
settings = conn.GetSettings()
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
if settings['connection']['type'] == '802-11-wireless':
|
||||||
|
form = AddWifiForm(request.POST)
|
||||||
|
else:
|
||||||
|
form = AddEthernetForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
name = form.cleaned_data['name']
|
||||||
|
ipv4_method = form.cleaned_data['ipv4_method']
|
||||||
|
ipv4_address = form.cleaned_data['ipv4_address']
|
||||||
|
|
||||||
|
if settings['connection']['type'] == '802-3-ethernet':
|
||||||
|
network.edit_ethernet_connection(conn, name, ipv4_method, ipv4_address)
|
||||||
|
elif settings['connection']['type'] == '802-11-wireless':
|
||||||
|
ssid = form.cleaned_data['ssid']
|
||||||
|
network.edit_wifi_connection(conn, name, ssid, ipv4_method, ipv4_address)
|
||||||
|
else:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_('Cannot edit connection %s: '
|
||||||
|
'Connection type not supported.') % name)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
else:
|
||||||
|
form_data['ipv4_method'] = settings['ipv4']['method']
|
||||||
|
|
||||||
|
if settings['ipv4']['addresses']:
|
||||||
|
form_data['ipv4_address'] = settings['ipv4']['addresses'][0][0]
|
||||||
|
|
||||||
|
if settings['connection']['type'] == '802-11-wireless':
|
||||||
|
form_data['ssid'] = settings['802-11-wireless']['ssid']
|
||||||
|
form = AddWifiForm(form_data)
|
||||||
|
else:
|
||||||
|
form = AddEthernetForm(form_data)
|
||||||
|
|
||||||
|
return TemplateResponse(request, 'connections_edit.html',
|
||||||
|
{'title': _('Edit Connection'),
|
||||||
|
'subsubmenu': subsubmenu,
|
||||||
|
'form': form})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def activate(request, conn_id):
|
||||||
|
"""Activate the connection."""
|
||||||
|
name = urllib.parse.unquote_plus(conn_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
network.activate_connection(name)
|
||||||
|
except network.ConnectionNotFound as cnf:
|
||||||
|
messages.error(request, cnf)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
except network.DeviceNotFound as dnf:
|
||||||
|
messages.error(request, dnf)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
|
||||||
|
messages.success(request, _('Activated connection %s.') % name)
|
||||||
|
return redirect(reverse_lazy('network:index'))
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def deactivate(request, conn_id):
|
||||||
|
"""Deactivate the connection."""
|
||||||
|
name = urllib.parse.unquote_plus(conn_id)
|
||||||
|
try:
|
||||||
|
network.deactivate_connection(name)
|
||||||
|
messages.success(request, _('Deactivated connection %s.') % name)
|
||||||
|
except network.ConnectionNotFound as cnf:
|
||||||
|
messages.error(request, cnf)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add(request):
|
||||||
|
"""Serve the connection type selection form."""
|
||||||
|
form = None
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = ConnectionTypeSelectForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
conn_type = form.cleaned_data['conn_type']
|
||||||
|
if conn_type == '802-3-ethernet':
|
||||||
|
return redirect(reverse_lazy('networks:add_ethernet'))
|
||||||
|
elif conn_type == '802-11-wireless':
|
||||||
|
return redirect(reverse_lazy('networks:add_wifi'))
|
||||||
|
else:
|
||||||
|
form = ConnectionTypeSelectForm()
|
||||||
|
return TemplateResponse(request, 'connections_type_select.html',
|
||||||
|
{'title': _('Add Connection'),
|
||||||
|
'subsubmenu': subsubmenu,
|
||||||
|
'form': form})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_ethernet(request):
|
||||||
|
"""Serve ethernet connection create form."""
|
||||||
|
form = None
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = AddEthernetForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
name = form.cleaned_data['name']
|
||||||
|
ipv4_method = form.cleaned_data['ipv4_method']
|
||||||
|
ipv4_address = form.cleaned_data['ipv4_address']
|
||||||
|
|
||||||
|
network.add_ethernet_connection(name, ipv4_method, ipv4_address)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
else:
|
||||||
|
form = AddEthernetForm()
|
||||||
|
|
||||||
|
return TemplateResponse(request, 'connections_create.html',
|
||||||
|
{'title': _('Editing New Ethernet Connection'),
|
||||||
|
'subsubmenu': subsubmenu,
|
||||||
|
'form': form})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_wifi(request):
|
||||||
|
"""Serve wifi connection create form."""
|
||||||
|
form = None
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = AddWifiForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
name = form.cleaned_data['name']
|
||||||
|
ssid = form.cleaned_data['ssid']
|
||||||
|
ipv4_method = form.cleaned_data['ipv4_method']
|
||||||
|
ipv4_address = form.cleaned_data['ipv4_address']
|
||||||
|
|
||||||
|
network.add_wifi_connection(name, ssid, ipv4_method, ipv4_address)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
else:
|
||||||
|
form = AddWifiForm()
|
||||||
|
|
||||||
|
return TemplateResponse(request, 'connections_create.html',
|
||||||
|
{'title': _('Editing New Wi-Fi Connection'),
|
||||||
|
'subsubmenu': subsubmenu,
|
||||||
|
'form': form})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def delete(request, conn_id):
|
||||||
|
"""Handle deleting connections, showing a confirmation dialog first.
|
||||||
|
|
||||||
|
On GET, display a confirmation page.
|
||||||
|
On POST, delete the connection.
|
||||||
|
"""
|
||||||
|
name = urllib.parse.unquote_plus(conn_id)
|
||||||
|
if request.method == 'POST':
|
||||||
|
try:
|
||||||
|
network.delete_connection(name)
|
||||||
|
except network.ConnectionNotFound as cnf:
|
||||||
|
messages.error(request, cnf)
|
||||||
|
else:
|
||||||
|
messages.success(request, _('Connection %s deleted.') % name)
|
||||||
|
return redirect(reverse_lazy('networks:index'))
|
||||||
|
|
||||||
|
return TemplateResponse(request, 'connections_delete.html',
|
||||||
|
{'title': _('Delete Connection'),
|
||||||
|
'subsubmenu': subsubmenu,
|
||||||
|
'name': name})
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<input type="submit" class="btn btn-md btn-primary"
|
<input type="submit" class="btn btn-md btn-primary"
|
||||||
value="Delete {{ name }}"/>
|
value="Delete {{ name }}"/>
|
||||||
|
|
||||||
<a href="{% url 'network:index' %}" role="button"
|
<a href="{% url 'networks:index' %}" role="button"
|
||||||
class="btn btn-md btn-primary">Cancel</a>
|
class="btn btn-md btn-primary">Cancel</a>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
{% for conn in connections %}
|
{% for conn in connections %}
|
||||||
<div class="list-group-item clearfix">
|
<div class="list-group-item clearfix">
|
||||||
<a href="{% url 'network:delete' conn.id %}"
|
<a href="{% url 'networks:delete' conn.id %}"
|
||||||
class="btn btn-default btn-sm pull-right"
|
class="btn btn-default btn-sm pull-right"
|
||||||
role="button" title="Delete connection {{ conn.name }}">
|
role="button" title="Delete connection {{ conn.name }}">
|
||||||
<span class="glyphicon glyphicon-trash"
|
<span class="glyphicon glyphicon-trash"
|
||||||
@ -51,7 +51,7 @@
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="connection-edit-label"
|
<a class="connection-edit-label"
|
||||||
href="{% url 'network:edit' conn.id %}"
|
href="{% url 'networks:edit' conn.id %}"
|
||||||
title="Edit connection {{ conn.name }}">
|
title="Edit connection {{ conn.name }}">
|
||||||
{{ conn.name }}
|
{{ conn.name }}
|
||||||
</a>
|
</a>
|
||||||
@ -67,7 +67,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'network:deactivate' conn.id %}">
|
<a href="{% url 'networks:deactivate' conn.id %}">
|
||||||
Deactivate
|
Deactivate
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -82,7 +82,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'network:activate' conn.id %}">
|
<a href="{% url 'networks:activate' conn.id %}">
|
||||||
Activate
|
Activate
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -23,17 +23,17 @@ from django.conf.urls import patterns, url
|
|||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = patterns(
|
||||||
'plinth.modules.network.network',
|
'plinth.modules.networks.networks',
|
||||||
url(r'^sys/network/$', 'index', name='index'),
|
url(r'^sys/networks/$', 'index', name='index'),
|
||||||
url(r'^sys/network/(?P<conn_id>[\w.@+-]+)/edit/$',
|
url(r'^sys/networks/(?P<conn_id>[\w.@+-]+)/edit/$',
|
||||||
'edit', name='edit'),
|
'edit', name='edit'),
|
||||||
url(r'^sys/network/(?P<conn_id>[\w.@+-]+)/activate/$',
|
url(r'^sys/networks/(?P<conn_id>[\w.@+-]+)/activate/$',
|
||||||
'activate', name='activate'),
|
'activate', name='activate'),
|
||||||
url(r'^sys/network/(?P<conn_id>[\w.@+-]+)/deactivate/$',
|
url(r'^sys/networks/(?P<conn_id>[\w.@+-]+)/deactivate/$',
|
||||||
'deactivate', name='deactivate'),
|
'deactivate', name='deactivate'),
|
||||||
url(r'^sys/network/add/$', 'add', name='add'),
|
url(r'^sys/networks/add/$', 'add', name='add'),
|
||||||
url(r'^sys/network/add/ethernet/$', 'add_ethernet', name='add_ethernet'),
|
url(r'^sys/networks/add/ethernet/$', 'add_ethernet', name='add_ethernet'),
|
||||||
url(r'^sys/network/add/wifi/$', 'add_wifi', name='add_wifi'),
|
url(r'^sys/networks/add/wifi/$', 'add_wifi', name='add_wifi'),
|
||||||
url(r'^sys/network/(?P<conn_id>[\w.@+-]+)/delete/$',
|
url(r'^sys/networks/(?P<conn_id>[\w.@+-]+)/delete/$',
|
||||||
'delete', name='delete'),
|
'delete', name='delete'),
|
||||||
)
|
)
|
||||||
237
plinth/network.py
Normal file
237
plinth/network.py
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Helper functions for working with network manager.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from gettext import gettext as _
|
||||||
|
import NetworkManager
|
||||||
|
import uuid
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
|
||||||
|
CONNECTION_TYPE_NAMES = {
|
||||||
|
'802-3-ethernet': 'Ethernet',
|
||||||
|
'802-11-wireless': 'Wi-Fi',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionNotFound(Exception):
|
||||||
|
def __init__(self, msg):
|
||||||
|
self.msg = msg
|
||||||
|
def __str__(self):
|
||||||
|
return self.msg
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceNotFound(Exception):
|
||||||
|
def __init__(self, msg):
|
||||||
|
self.msg = msg
|
||||||
|
def __str__(self):
|
||||||
|
return self.msg
|
||||||
|
|
||||||
|
|
||||||
|
def get_connection_list():
|
||||||
|
"""Get a list of active and available connections."""
|
||||||
|
connections = []
|
||||||
|
active = []
|
||||||
|
|
||||||
|
for conn in NetworkManager.NetworkManager.ActiveConnections:
|
||||||
|
try:
|
||||||
|
settings = conn.Connection.GetSettings()['connection']
|
||||||
|
except DBusException:
|
||||||
|
# DBusException can be thrown here if the connection list is loaded
|
||||||
|
# quickly after a connection is deactivated.
|
||||||
|
continue
|
||||||
|
active.append(settings['id'])
|
||||||
|
|
||||||
|
for conn in NetworkManager.Settings.ListConnections():
|
||||||
|
settings = conn.GetSettings()['connection']
|
||||||
|
# Display a friendly type name if known.
|
||||||
|
conn_type = CONNECTION_TYPE_NAMES.get(settings['type'],
|
||||||
|
settings['type'])
|
||||||
|
connections.append({
|
||||||
|
'name': settings['id'],
|
||||||
|
'id': urllib.parse.quote_plus(settings['id']),
|
||||||
|
'type': conn_type,
|
||||||
|
'is_active': settings['id'] in active,
|
||||||
|
})
|
||||||
|
connections.sort(key=lambda x: x['is_active'], reverse=True)
|
||||||
|
return connections
|
||||||
|
|
||||||
|
|
||||||
|
def get_connection(name):
|
||||||
|
"""Returns connection with id matching name.
|
||||||
|
Returns None if not found.
|
||||||
|
"""
|
||||||
|
connections = NetworkManager.Settings.ListConnections()
|
||||||
|
connections = dict([(x.GetSettings()['connection']['id'], x)
|
||||||
|
for x in connections])
|
||||||
|
return connections.get(name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_connection(name):
|
||||||
|
"""Returns active connection with id matching name.
|
||||||
|
Returns None if not found.
|
||||||
|
"""
|
||||||
|
connections = NetworkManager.NetworkManager.ActiveConnections
|
||||||
|
connections = dict([(x.Connection.GetSettings()['connection']['id'], x)
|
||||||
|
for x in connections])
|
||||||
|
return connections.get(name)
|
||||||
|
|
||||||
|
|
||||||
|
def edit_ethernet_connection(conn, name, ipv4_method, ipv4_address):
|
||||||
|
settings = conn.GetSettings()
|
||||||
|
|
||||||
|
new_settings = {
|
||||||
|
'connection': {
|
||||||
|
'id': name,
|
||||||
|
'type': settings['connection']['type'],
|
||||||
|
'uuid': settings['connection']['uuid'],
|
||||||
|
},
|
||||||
|
'802-3-ethernet': {},
|
||||||
|
'ipv4': {'method': ipv4_method},
|
||||||
|
}
|
||||||
|
if ipv4_method == 'manual' and ipv4_address:
|
||||||
|
new_settings['ipv4']['addresses'] = [
|
||||||
|
(ipv4_address,
|
||||||
|
24, # CIDR prefix length
|
||||||
|
'0.0.0.0')] # gateway
|
||||||
|
|
||||||
|
conn.Update(new_settings)
|
||||||
|
|
||||||
|
|
||||||
|
def edit_wifi_connection(conn, name, ssid, ipv4_method, ipv4_address):
|
||||||
|
settings = conn.GetSettings()
|
||||||
|
|
||||||
|
new_settings = {
|
||||||
|
'connection': {
|
||||||
|
'id': name,
|
||||||
|
'type': settings['connection']['type'],
|
||||||
|
'uuid': settings['connection']['uuid'],
|
||||||
|
},
|
||||||
|
'802-11-wireless': {
|
||||||
|
'ssid': ssid,
|
||||||
|
},
|
||||||
|
'ipv4': {'method': ipv4_method},
|
||||||
|
}
|
||||||
|
if ipv4_method == 'manual' and ipv4_address:
|
||||||
|
new_settings['ipv4']['addresses'] = [
|
||||||
|
(ipv4_address,
|
||||||
|
24, # CIDR prefix length
|
||||||
|
'0.0.0.0')] # gateway
|
||||||
|
|
||||||
|
conn.Update(new_settings)
|
||||||
|
|
||||||
|
|
||||||
|
def activate_connection(name):
|
||||||
|
# Find the connection
|
||||||
|
conn = get_connection(name)
|
||||||
|
if not conn:
|
||||||
|
raise ConnectionNotFound(
|
||||||
|
_('Failed to activate connection %s: '
|
||||||
|
'Connection not found.') % name)
|
||||||
|
|
||||||
|
# Find a suitable device
|
||||||
|
ctype = conn.GetSettings()['connection']['type']
|
||||||
|
if ctype == 'vpn':
|
||||||
|
for dev in NetworkManager.NetworkManager.GetDevices():
|
||||||
|
if (dev.State == NetworkManager.NM_DEVICE_STATE_ACTIVATED
|
||||||
|
and dev.Managed):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise DeviceNotFound(
|
||||||
|
_('Failed to activate connection %s: '
|
||||||
|
'No suitable device is available.') % name)
|
||||||
|
else:
|
||||||
|
dtype = {
|
||||||
|
'802-11-wireless': NetworkManager.NM_DEVICE_TYPE_WIFI,
|
||||||
|
'802-3-ethernet': NetworkManager.NM_DEVICE_TYPE_ETHERNET,
|
||||||
|
'gsm': NetworkManager.NM_DEVICE_TYPE_MODEM,
|
||||||
|
}.get(ctype, ctype)
|
||||||
|
|
||||||
|
for dev in NetworkManager.NetworkManager.GetDevices():
|
||||||
|
if (dev.DeviceType == dtype
|
||||||
|
and dev.State == NetworkManager.NM_DEVICE_STATE_DISCONNECTED):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise DeviceNotFound(
|
||||||
|
_('Failed to activate connection %s: '
|
||||||
|
'No suitable device is available.') % name)
|
||||||
|
|
||||||
|
NetworkManager.NetworkManager.ActivateConnection(conn, dev, "/")
|
||||||
|
|
||||||
|
|
||||||
|
def deactivate_connection(name):
|
||||||
|
active = get_active_connection(name)
|
||||||
|
if active:
|
||||||
|
NetworkManager.NetworkManager.DeactivateConnection(active)
|
||||||
|
else:
|
||||||
|
raise ConnectionNotFound(
|
||||||
|
_('Failed to deactivate connection %s: '
|
||||||
|
'Connection not found.') % name)
|
||||||
|
|
||||||
|
|
||||||
|
def add_ethernet_connection(name, ipv4_method, ipv4_address):
|
||||||
|
conn = {
|
||||||
|
'connection': {
|
||||||
|
'id': name,
|
||||||
|
'type': '802-3-ethernet',
|
||||||
|
'uuid': str(uuid.uuid4()),
|
||||||
|
},
|
||||||
|
'802-3-ethernet': {},
|
||||||
|
'ipv4': {'method': ipv4_method},
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipv4_method == 'manual' and ipv4_address:
|
||||||
|
conn['ipv4']['addresses'] = [
|
||||||
|
(ipv4_address,
|
||||||
|
24, # CIDR prefix length
|
||||||
|
'0.0.0.0')] # gateway
|
||||||
|
|
||||||
|
NetworkManager.Settings.AddConnection(conn)
|
||||||
|
|
||||||
|
|
||||||
|
def add_wifi_connection(name, ssid, ipv4_method, ipv4_address):
|
||||||
|
conn = {
|
||||||
|
'connection': {
|
||||||
|
'id': name,
|
||||||
|
'type': '802-11-wireless',
|
||||||
|
'uuid': str(uuid.uuid4()),
|
||||||
|
},
|
||||||
|
'802-11-wireless': {
|
||||||
|
'ssid': ssid,
|
||||||
|
},
|
||||||
|
'ipv4': {'method': ipv4_method},
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipv4_method == 'manual' and ipv4_address:
|
||||||
|
conn['ipv4']['addresses'] = [
|
||||||
|
(ipv4_address,
|
||||||
|
24, # CIDR prefix length
|
||||||
|
'0.0.0.0')] # gateway
|
||||||
|
|
||||||
|
NetworkManager.Settings.AddConnection(conn)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_connection(name):
|
||||||
|
conn = get_connection(name)
|
||||||
|
if not conn:
|
||||||
|
raise ConnectionNotFound(
|
||||||
|
_('Failed to delete connection %s: '
|
||||||
|
'Connection not found.') % name)
|
||||||
|
conn.Delete()
|
||||||
72
plinth/tests/test_network.py
Normal file
72
plinth/tests/test_network.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from plinth import network
|
||||||
|
|
||||||
|
|
||||||
|
class TestNetwork(unittest.TestCase):
|
||||||
|
"""Verify that the network module performs as expected."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
network.add_ethernet_connection(
|
||||||
|
'plinth_test_eth', 'auto', '')
|
||||||
|
network.add_wifi_connection(
|
||||||
|
'plinth_test_wifi', 'plinthtestwifi', 'auto', '')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
network.delete_connection('plinth_test_eth')
|
||||||
|
network.delete_connection('plinth_test_wifi')
|
||||||
|
|
||||||
|
def test_get_connection_list(self):
|
||||||
|
"""Check that we can get a list of available connections."""
|
||||||
|
connections = network.get_connection_list()
|
||||||
|
self.assertTrue('plinth_test_eth' in [x['name'] for x in connections])
|
||||||
|
self.assertTrue('plinth_test_wifi' in [x['name'] for x in connections])
|
||||||
|
|
||||||
|
def test_get_connection(self):
|
||||||
|
"""Check that we can get a connection by name."""
|
||||||
|
conn = network.get_connection('plinth_test_eth')
|
||||||
|
self.assertEqual(
|
||||||
|
conn.GetSettings()['connection']['id'], 'plinth_test_eth')
|
||||||
|
|
||||||
|
conn = network.get_connection('plinth_test_wifi')
|
||||||
|
self.assertEqual(
|
||||||
|
conn.GetSettings()['connection']['id'], 'plinth_test_wifi')
|
||||||
|
|
||||||
|
def test_edit_ethernet_connection(self):
|
||||||
|
"""Check that we can update an ethernet connection."""
|
||||||
|
conn = network.get_connection('plinth_test_eth')
|
||||||
|
network.edit_ethernet_connection(
|
||||||
|
conn, 'plinth_test_eth', 'manual', '169.254.0.1')
|
||||||
|
conn = network.get_connection('plinth_test_eth')
|
||||||
|
self.assertEqual(conn.GetSettings()['ipv4']['method'], 'manual')
|
||||||
|
|
||||||
|
def test_edit_wifi_connection(self):
|
||||||
|
"""Check that we can update a wifi connection."""
|
||||||
|
conn = network.get_connection('plinth_test_wifi')
|
||||||
|
network.edit_wifi_connection(
|
||||||
|
conn, 'plinth_test_wifi', 'plinthtestwifi2', 'auto', '')
|
||||||
|
conn = network.get_connection('plinth_test_wifi')
|
||||||
|
self.assertEqual(conn.GetSettings()['802-11-wireless']['ssid'], 'plinthtestwifi2')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Loading…
x
Reference in New Issue
Block a user