Network Status pages: added status pages

- implemented network status page which supports:
 * show IP address and netmask
 * show MAC address
 * show device name
 * show firewall zone name
 * show DNS server information
 * show default gateway
 * show wifi information
 * shows if connection is shared or not and if connection is the default connection

- when clicking on a cennection on the overview page go to the status page, not to the
  editing page

- ToDo: if connection is disabled and re-enabled again, no information are visible anymore (Bug)
This commit is contained in:
Daniel Steglich 2015-09-15 21:24:44 +00:00 committed by Sunil Mohan Adapa
parent 2050a503c7
commit c3e5753b52
5 changed files with 507 additions and 4 deletions

View File

@ -57,6 +57,82 @@ def index(request):
'connections': connections})
def show(request, uuid):
"""Serve connection information."""
try:
connection = network.get_connection(uuid)
except network.ConnectionNotFound:
messages.error(request, _('Cannot show connection: '
'Connection not found.'))
return redirect(reverse_lazy('networks:index'))
name = connection.get_interface_name()
connectiontype = connection.get_connection_type()
settings_ipv4 = connection.get_setting_ip4_config()
mac = network.get_mac_from_device(name)
interface = connection.get_interface_name()
if connectiontype == '802-11-wireless':
settings_wireless = connection.get_setting_wireless()
ssid = settings_wireless.get_ssid().get_data()
rate = network.get_wifi_rate(interface, ssid)
channel = network.get_wifi_channel(interface, ssid)
strength = network.get_wifi_signal(interface, ssid)
linkstate = True
else:
ssid = "None"
rate = 0
channel = 0
linkstate = network.get_linkstate_from_device(name)
strength = 0
ip = network.get_all_ip_from_device(name)
ip6 = network.get_all_ip6_from_device(name)
dns = network.get_namesever_from_device(name)
dns6 = network.get_namesever6_from_device(name)
gateway = network.get_gateway_from_device(name)
gateway6 = network.get_gateway6_from_device(name)
method = settings_ipv4.get_method()
zone = connection.get_setting_connection().get_zone()
active = network.connection_is_active(uuid)
if network.get_primary_connection().get_id() == connection.get_id():
primary = True
else:
primary = False
if not ip:
ip.append("0.0.0.0/0")
if not ip6:
ip6.append("::0/0")
return TemplateResponse(request, 'connection_show.html',
{'title': _('Show Connection information'),
'ip': ip,
'ip6': ip6,
'gateway': gateway,
'gateway6': gateway6,
'dns': dns,
'dns6': dns6,
'interface': interface,
'mac': mac,
'linkstate': linkstate,
'zone': zone,
'primary': primary,
'subsubmenu': subsubmenu,
'method': method,
'connectiontype': connectiontype,
'ssid': ssid,
'strength': strength,
'rate': rate,
'channel': channel,
'active': active,
'uuid': uuid,
'name': name})
def edit(request, uuid):
"""Serve connection editing form."""
try:

View File

@ -0,0 +1,186 @@
{% extends "base.html" %}
{% comment %}
#
# 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/>.
#
# ToDo: if connection is disabled, no information are visible anymore (Bug)
{% endcomment %}
{% block page_head %}
<style type="text/css">
.list-group-item .btn {
margin: -5px 0;
}
</style>
{% endblock %}
{% load bootstrap %}
{% block content %}
{% if active %}
<h3>Physical Link Information</h3>
{% if linkstate and connectiontype == "802-3-ethernet" %}
<span class='label label-success'>cable is connected</span>
<br/><br/>
{% elif connectiontype == "802-3-ethernet" %}
<span class='label label-warning'>please check cable</span>
<br/><br/>
{% endif %}
<div class="row">
<div class="col-sm-6">
<div class="list-group">
{% if connectiontype == "802-11-wireless" %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">SSID</span>
<span class="connection-type-label pull-right">{{ ssid }}</span>
</div>
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">Speed</span>
<span class="connection-type-label pull-right">{{ rate }}</span>
</div>
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">Signal</span>
<span class="connection-type-label pull-right">
<span class="btn btn-primary btn-xs pull-right">
{{ strength }}%
</span>
</span>
</div>
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">Channel</span>
<span class="connection-type-label pull-right">{{ channel }}</span>
</div>
{% endif %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">MAC adress</span>
<span class="connection-type-label pull-right">{{ mac }}</span>
</div>
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">Interface</span>
<span class="connection-type-label pull-right">{{ interface }}</span>
</div>
</div>
</div>
</div>
<h3>IP Address Information</h3>
<div class="row">
<div class="col-sm-6">
<div class="list-group">
{% for addr in ip %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">IPv4 Address</span>
<span class="connection-type-label pull-right">{{ addr }}
</span>
</div>
{% endfor %}
{% for addr in ip6 %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">IPv6 Address</span>
<span class="connection-type-label pull-right">{{ addr }}
</span>
</div>
{% endfor %}
{% for server in dns %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">DNS Server</span>
<span class="connection-type-label pull-right">{{ server }}</span>
</div>
{% endfor %}
{% for server in dns6 %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">DNS Server</span>
<span class="connection-type-label pull-right">{{ server }}</span>
</div>
{% endfor %}
{% if gateway %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">IPv4 Default Gateway</span>
<span class="connection-type-label pull-right">{{ gateway }}</span>
</div>
{% endif %}
{% if gateway6 %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">IPv6 Default Gateway</span>
<span class="connection-type-label pull-right">{{ gateway6 }}</span>
</div>
{% endif %}
{% if method == "shared" %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">DHCP Server</span>
<span class="connection-type-label pull-right">enabled</span>
</div>
{% elif method == "auto" %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">IP Method</span>
<span class="connection-type-label pull-right">{{ method }}
</span>
</div>
{% endif %}
{% if primary %}
<div class="list-group-item clearfix">
<span class="connection-type-label pull-left">Default Connection</span>
<span class="connection-type-label pull-right">
<span class='label label-success'>yes</span>
</span>
</div>
{% endif %}
</div>
</div>
</div>
<h3>Security Information</h3>
{% if zone == "internal" %}
Firewall: <span class='label label-success'>{{ zone }}</span><br/><br/>
INFO: This interface should be connected to local network. <br/>
If you connect this interface to a public
network, others may have access to your data.
{% elif zone == "external" %}
Firewall: <span class='label label-warning'>{{ zone }}</span><br/><br/>
INFO: This interface should be connected to your internet upstream
connection
{% else %}
Firewall: <span class='label label-danger'>{{ zone }}</span><br/><br/>
WARNING: This interface is not assigned to a zone which is maintained by
freedombox
{% endif %}
{% else %}
This connections is not active. Please activate connection.
{% endif %}
<br/><hr>
<a href="{% url 'networks:edit' uuid %}"
class="btn btn-primary"
role="button" title="Edit connection">
Edit
</a>
{% if active %}
<a href="{% url 'networks:deactivate' uuid %}"
class="btn btn-default"
role="button" title="Deactivate connection">
Deactivate
</a>
{% else %}
<a href="{% url 'networks:activate' uuid %}"
class="btn btn-default"
role="button" title="Deactivate connection">
Activate
</a>
{% endif %}
<a href="{% url 'networks:delete' uuid %}"
class="btn btn-default"
role="button" title="Delete connection">
Delete
</a>
{% endblock %}

View File

@ -22,7 +22,7 @@
{% block page_head %}
<style type="text/css">
.connection-edit-label {
.connection-show-label {
display: inline-block;
width: 40%;
}
@ -58,9 +58,9 @@
aria-hidden="true"></span>
</a>
<a class="connection-edit-label"
href="{% url 'networks:edit' connection.uuid %}"
title="Edit connection {{ connection.name }}">
<a class="connection-show-label"
href="{% url 'networks:show' connection.uuid %}"
title="Show connection {{ connection.name }}">
{{ connection.name }}
</a>

View File

@ -25,6 +25,8 @@ from django.conf.urls import patterns, url
urlpatterns = patterns(
'plinth.modules.networks.networks',
url(r'^sys/networks/$', 'index', name='index'),
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/show/$',
'show', name='show'),
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/edit/$',
'edit', name='edit'),
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/activate/$',

View File

@ -76,6 +76,245 @@ def get_interface_list(device_type):
return interfaces
def get_ip_from_device(devicename):
"""
Get the first ip address from the network interface.
will return "0.0.0.0" if no ip address is assiged.
IP address is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
ip = "0.0.0.0"
device = nm.Client.new(None).get_device_by_iface(devicename)
ip4_config = device.get_ip4_config()
if ip4_config:
addresses = ip4_config.get_addresses()
if addresses:
ip = addresses.__getitem__(0).get_address()
return ip
def get_ip6_from_device(devicename):
"""
Get the first ip address from the network interface.
will return "0.0.0.0" if no ip address is assiged.
IP address is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
ip = "0.0.0.0"
device = nm.Client.new(None).get_device_by_iface(devicename)
ip6_config = device.get_ip6_config()
if ip6_config:
addresses = ip6_config.get_addresses()
if addresses:
ip = addresses.__getitem__(0).get_address()
return ip
def get_all_ip_from_device(devicename):
"""
Get all ipv4 addresses from device
IP address is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
ip = []
device = nm.Client.new(None).get_device_by_iface(devicename)
ip4_config = device.get_ip4_config()
if ip4_config:
addresses = ip4_config.get_addresses()
for address in addresses:
netmask = str(address.get_prefix())
ip.append(str(address.get_address() + "/" + netmask))
return ip
def get_all_ip6_from_device(devicename):
"""
Get all ipv6 addresses from device
IP address is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
ip = []
device = nm.Client.new(None).get_device_by_iface(devicename)
ip6_config = device.get_ip6_config()
if ip6_config:
addresses = ip6_config.get_addresses()
for address in addresses:
netmask = str(address.get_prefix())
ip.append(str(address.get_address() + "/" + netmask))
return ip
def get_namesever_from_device(devicename):
"""
Get all nameservers which are reachable via this device.
Nameservers is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
nameservers = ""
device = nm.Client.new(None).get_device_by_iface(devicename)
ip4_config = device.get_ip4_config()
if ip4_config:
nameservers = ip4_config.get_nameservers()
return nameservers
def get_namesever6_from_device(devicename):
"""
Get all nameservers which are reachable via this device.
Nameservers is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
nameservers = ""
device = nm.Client.new(None).get_device_by_iface(devicename)
ip6_config = device.get_ip6_config()
if ip6_config:
nameservers = ip6_config.get_nameservers()
return nameservers
def get_gateway_from_device(devicename):
"""
Get the default Gateway for this device.
gateway is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
gateway = ""
device = nm.Client.new(None).get_device_by_iface(devicename)
ip4_config = device.get_ip4_config()
if ip4_config:
gateway = device.get_ip4_config().get_gateway()
return gateway
def get_gateway6_from_device(devicename):
"""
Get the default Gateway for this device.
gateway is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
gateway = ""
device = nm.Client.new(None).get_device_by_iface(devicename)
ip6_config = device.get_ip6_config()
if ip6_config:
gateway = device.get_ip6_config().get_gateway()
return gateway
def get_linkstate_from_device(devicename):
"""
Get the physical link state from this device (carrier detected)
link state is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
linkstate = False
device = nm.Client.new(None).get_device_by_iface(devicename)
ip4_config = device.get_ip4_config()
if ip4_config:
linkstate = device.get_carrier()
return linkstate
def get_mac_from_device(devicename):
"""
Get the MAC address of the network interface.
MAC address is a optional information, will not raise a exception
if no information could be returned.
ToDo: will not work when connection is or previously was inactive
"""
mac = "00:00:00:00:00:00"
device = nm.Client.new(None).get_device_by_iface(devicename)
ip4_config = device.get_ip4_config()
if ip4_config:
mac = device.get_hw_address()
return mac
def connection_is_active(connection_uuid):
"""
Return True if connection is active
Return False if connection is inactive
"""
client = nm.Client.new(None)
for connection in client.get_active_connections():
if connection.get_uuid() == connection_uuid:
return True
return False
def get_primary_connection():
"""return the name of the primary (aka internet) connection"""
return nm.Client.new(None).get_primary_connection()
def get_wifi_signal(devicename, ssid):
"""Get the wifi signal strenght form a particular SSID"""
signal = 0
device = nm.Client.new(None).get_device_by_iface(devicename)
for ap in device.get_access_points():
if ap.get_ssid().get_data() == ssid:
signal = ap.get_strength()
return signal
def get_wifi_rate(devicename, ssid):
"""Get the wifi bitrate form a particular SSID"""
device = nm.Client.new(None).get_device_by_iface(devicename)
rate = device.get_bitrate() / 1000
rate = str(str(rate) + "Mbit/s")
return rate
def get_wifi_channel(devicename, ssid):
"""Get the wifi channeö form a particular SSID"""
channel = 0
device = nm.Client.new(None).get_device_by_iface(devicename)
for ap in device.get_access_points():
if ap.get_ssid().get_data() == ssid:
frequency = ap.get_frequency()
frequency = frequency / 1000
"""
Hard coded list of wifi frequencys and their corresponding channel numbers.
ToDo: search for a better solution! Even 5GHz is not included yet.
Only the plain frequency will show up on 5GHz AP's.
"""
if frequency == 2.412:
channel = 1
elif frequency == 2.417:
channel = 2
elif frequency == 2.422:
channel = 3
elif frequency == 2.427:
channel = 4
elif frequency == 2.432:
channel = 5
elif frequency == 2.437:
channel = 6
elif frequency == 2.442:
channel = 7
elif frequency == 2.447:
channel = 8
elif frequency == 2.452:
channel = 9
elif frequency == 2.457:
channel = 10
elif frequency == 2.462:
channel = 11
else:
channel = str(str(frequency) + "GHz")
return channel
def get_connection_list():
"""Get a list of active and available connections."""
active_uuids = []