Skip to content

Commit

Permalink
[feature] Added more interface properties to device status
Browse files Browse the repository at this point in the history
Closes #77
  • Loading branch information
nemesifier authored and nepython committed Aug 7, 2020
1 parent 164b3f4 commit b29a359
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 17 deletions.
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ OpenWISP 2 monitoring module (Work in progress).
Available Features
------------------

* Collects and displays `device status <#device-status>`_ information like Uptime, RAM status, CPU load averages,
Interface addresses, WiFi interface status and associated clients, Neighbors information,
DHCP Leases, Disk/Flash status
* Collects and displays `device status <#device-status>`_ information like uptime, RAM status, CPU load averages,
Interface properties and addresses, WiFi interface status and associated clients,
Neighbors information, DHCP Leases, Disk/Flash status
* Collection of monitoring information in a timeseries database (currently only influxdb is supported)
* Monitoring charts for uptime, packet loss, round trip time (latency), associated wifi clients, interface traffic,
RAM usage, CPU load, flash/disk usage
Expand Down
13 changes: 13 additions & 0 deletions openwisp_monitoring/device/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,20 @@
"required": ["name"],
"properties": {
"name": {"type": "string"},
"type": {"type": "string"},
"uptime": {"type": "integer"},
"up": {"type": "boolean"},
"mac": {"type": "string"},
"mtu": {"type": "integer"},
"txqueuelen": {"type": "integer"},
"speed": {"type": "string"},
"multicast": {"type": "boolean"},
"bridge_members": {
"type": "array",
"items": {"type": "string"},
"additionalItems": False,
},
"stp": {"type": "boolean"},
"statistics": {
"type": "object",
"properties": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,23 @@ <h2>{% trans 'Storage' %}</h2>
{% for interface in device_data.interfaces %}
<div class="inline-group">
<h2>{% trans 'Interface status' %}: {{ interface.name }}</h2>
{% if interface.wireless %}
{% if interface.mac %}
<div class="form-row">
<label>{% trans 'MAC Address' %}:</label>
<div class="readonly">
{{ interface.mac }}
</div>
</div>
{% endif %}
{% if interface.type %}
<div class="form-row">
<label>{% trans 'Type' %}:</label>
<div class="readonly">
{% trans 'Wireless' %}
{{ interface.type }}
</div>
</div>
{% endif %}
{% if interface.wireless %}
<div class="form-row">
<label>{% trans 'Mode' %}:</label>
<div class="readonly">
Expand Down Expand Up @@ -170,6 +180,65 @@ <h2>{% trans 'Interface status' %}: {{ interface.name }}</h2>
{{ interface.wireless.clients|length }}
</div>
</div>
{% endif %}
{% endif %}
{% if interface.type == 'ethernet' and interface.speed %}
<div class="form-row">
<label>{% trans 'Speed' %}:</label>
<div class="readonly">
{{ interface.speed }}
</div>
</div>
{% endif %}
{% if interface.bridge_members %}
<div class="form-row">
<label>{% trans 'Bridge Members' %}:</label>
<div class="readonly">
{{ interface.bridge_members|join:", " }}
</div>
</div>
{% endif %}
{% if interface.stp != None %}
<div class="form-row">
<label>{% trans 'Spanning Tree Protocol' %}:</label>
<div class="readonly">
<img src="{% static '/admin/img/' %}icon-{{ interface.stp|yesno:'yes,no,no' }}.svg">
</div>
</div>
{% endif %}
{% if interface.up != None %}
<div class="form-row">
<label>{% trans 'Up' %}:</label>
<div class="readonly">
<img src="{% static '/admin/img/' %}icon-{{ interface.up|yesno:'yes,no,no' }}.svg">
</div>
</div>
{% endif %}
{% if interface.multicast != None %}
<div class="form-row">
<label>{% trans 'Multicast' %}:</label>
<div class="readonly">
<img src="{% static '/admin/img/' %}icon-{{ interface.multicast|yesno:'yes,no,no' }}.svg">
</div>
</div>
{% endif %}
{% if interface.mtu %}
<div class="form-row">
<label>{% trans 'MTU' %}:</label>
<div class="readonly">
{{ interface.mtu }}
</div>
</div>
{% endif %}
{% if interface.txqueuelen != None %}
<div class="form-row">
<label>{% trans 'Transmit Queue Length' %}:</label>
<div class="readonly">
{{ interface.txqueuelen }}
</div>
</div>
{% endif %}
{% if interface.wireless and interface.wireless.clients %}
<table class="wifi-clients">
<thead>
<tr>
Expand Down Expand Up @@ -226,7 +295,6 @@ <h2>{% trans 'Interface status' %}: {{ interface.name }}</h2>
{% endfor %}
</table>
{% endif %}
{% endif %}
{% if interface.addresses %}
<table class="addresses">
<thead>
Expand Down
12 changes: 12 additions & 0 deletions openwisp_monitoring/device/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ def _data(self):
'interfaces': [
{
'name': 'wlan0',
'type': 'wireless',
'up': True,
'mac': '44:d1:fa:4b:38:43',
'txqueuelen': 1000,
'multicast': True,
'mtu': 1500,
'statistics': {
'rx_bytes': 324,
'tx_bytes': 145,
Expand Down Expand Up @@ -183,6 +189,12 @@ def _data(self):
},
{
'name': 'wlan1',
'type': 'wireless',
'up': True,
'mac': '44:d1:fa:4b:38:44',
'txqueuelen': 1000,
'multicast': True,
'mtu': 1500,
'statistics': {
'rx_bytes': 2275,
'tx_bytes': 826,
Expand Down
40 changes: 40 additions & 0 deletions openwisp_monitoring/device/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,46 @@ def test_wifi_clients_admin(self):
self.assertEqual(r1.status_code, 200)
self.assertContains(r1, '00:ee:ad:34:f5:3b')

def test_interface_properties_admin(self):
self._login_admin()
dd = self.create_test_adata(no_resources=True)
url = reverse('admin:config_device_change', args=[dd.id])
r1 = self.client.get(url, follow=True)
self.assertEqual(r1.status_code, 200)
self.assertContains(r1, '44:d1:fa:4b:38:44')
self.assertContains(r1, 'Transmit Queue Length')
self.assertContains(r1, 'Up')
self.assertContains(r1, 'Multicast')
self.assertContains(r1, 'MTU')

def test_interface_bridge_admin(self):
self._login_admin()
d = self._create_device(organization=self._create_org())
dd = DeviceData(name='test-device', pk=d.pk)
data = self._data()
del data['resources']
self._post_data(
d.id,
d.key,
{
'type': 'DeviceMonitoring',
'interfaces': [
{
'name': 'br-lan',
'type': 'bridge',
'bridge_members': ['tap0', 'wlan0', 'wlan1'],
'stp': True,
}
],
},
)
url = reverse('admin:config_device_change', args=[dd.id])
r1 = self.client.get(url, follow=True)
self.assertEqual(r1.status_code, 200)
self.assertContains(r1, 'Bridge Members')
self.assertContains(r1, 'tap0, wlan0, wlan1')
self.assertContains(r1, 'Spanning Tree Protocol')

def test_uuid_bug(self):
dd = self.create_test_adata(no_resources=True)
uuid = str(dd.pk).replace('-', '')
Expand Down
41 changes: 30 additions & 11 deletions openwisp_monitoring/device/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,22 +165,14 @@ def test_garbage_wireless_clients(self):
d = self._create_device(organization=o)
garbage_interfaces = [
{'name': 'garbage1', 'wireless': {'clients': {}}},
{
'name': 'garbage2',
'wireless': {'clients': [{'what?': 'mac missing'}]},
},
{'name': 'garbage3', 'wireless': {}}
{'name': 'garbage2', 'wireless': {'clients': [{'what?': 'mac missing'}]}},
{'name': 'garbage3', 'wireless': {}},
]
for garbage_interface in garbage_interfaces:
interface = self._data()['interfaces'][0]
interface.update(garbage_interface)
r = self._post_data(
d.id,
d.key,
{
'type': 'DeviceMonitoring',
'interfaces': [interface]
}
d.id, d.key, {'type': 'DeviceMonitoring', 'interfaces': [interface]}
)
with self.subTest(garbage_interface):
self.assertEqual(r.status_code, 400)
Expand Down Expand Up @@ -409,3 +401,30 @@ def test_get_device_status_200(self):
self.assertIn('data', r.data)
self.assertIsInstance(r.data['data'], dict)
self.assertEqual(dd.data, r.data['data'])

def test_garbage_interface_properties(self):
o = self._create_org()
d = self._create_device(organization=o)
garbage_interfaces = [
{'type': 1},
{'uptime': 'string'},
{'up': 'up'},
{'mac': 1},
{'mtu': 'string'},
{'txqueuelen': 'string'},
{'speed': 0},
{'multicast': 1},
{'type': 'bridge', 'bridge_members': [1, 2]},
{'stp': 1},
]
number = 1
for garbage_interface in garbage_interfaces:
interface = self._data()['interfaces'][0]
interface.update(garbage_interface)
interface['name'] = f'garbage{number}'
r = self._post_data(
d.id, d.key, {'type': 'DeviceMonitoring', 'interfaces': [interface]}
)
number += 1
with self.subTest(garbage_interface):
self.assertEqual(r.status_code, 400)

0 comments on commit b29a359

Please sign in to comment.