Skip to content

Commit 7c4cfda

Browse files
committed
[tests] Fixed failing tests and rebase completed
- Completed rebase. - Fixed failing tests to make sure it works on current version of openwisp_monitoring. - Updated settings of snmp_check acc to new openwisp_controller snmp credentials. - Formatted code and fixed all QA warnings.
1 parent b8056d8 commit 7c4cfda

File tree

8 files changed

+82
-27
lines changed

8 files changed

+82
-27
lines changed

openwisp_monitoring/check/classes/ping.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from openwisp_utils.utils import deep_merge_dicts
99

1010
from ... import settings as monitoring_settings
11+
from .. import settings as app_settings
1112
from ..exceptions import OperationalError
1213
from .base import BaseCheck
1314

openwisp_monitoring/check/classes/snmp_devicemonitoring.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
class Snmp(BaseCheck, MetricChartsMixin):
1919
def check(self, store=True):
2020
result = self.netengine_instance.to_dict()
21-
self._init_previous_data(data=getattr(self.related_object, 'data', {}))
21+
self._init_previous_data()
2222
self.related_object.data = result
2323
if store:
2424
self.store_result(result)
@@ -32,7 +32,7 @@ def store_result(self, data):
3232
device_data = DeviceData.objects.get(pk=pk)
3333
device_data.data = data
3434
device_data.save_data()
35-
self._write(pk, data)
35+
self._write(pk)
3636

3737
@cached_property
3838
def netengine_instance(self):
@@ -43,13 +43,14 @@ def netengine_instance(self):
4343
@cached_property
4444
def credential_instance(self):
4545
return Credentials.objects.filter(
46-
deviceconnection__device_id=self.related_object, connector__endswith='Snmp',
46+
deviceconnection__device_id=self.related_object,
47+
connector__endswith='OpenWRTSnmp',
4748
).last()
4849

4950
def _get_connnector(self):
5051
connectors = {
51-
'openwisp_controller.connection.connectors.snmp.Snmp': OpenWRT,
52-
'openwisp_controller.connection.connectors.airos.snmp.Snmp': AirOS,
52+
'openwisp_controller.connection.connectors.openwrt.snmp.OpenWRTSnmp': OpenWRT,
53+
'openwisp_controller.connection.connectors.airos.snmp.AirOsSnmp': AirOS,
5354
}
5455
try:
5556
return connectors.get(self.credential_instance.connector, OpenWRT)

openwisp_monitoring/check/settings.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
(
66
('openwisp_monitoring.check.classes.Ping', 'Ping'),
77
('openwisp_monitoring.check.classes.ConfigApplied', 'Configuration Applied'),
8-
('openwisp_monitoring.check.classes.Snmp', 'SNMP Device Monitoring',),
8+
(
9+
'openwisp_monitoring.check.classes.Snmp',
10+
'SNMP Device Monitoring',
11+
),
912
),
1013
)
1114
AUTO_PING = get_settings_value('AUTO_PING', True)
1215
AUTO_CONFIG_CHECK = get_settings_value('AUTO_DEVICE_CONFIG_CHECK', True)
1316
AUTO_SNMP = get_settings_value('AUTO_SNMP', False)
1417
MANAGEMENT_IP_ONLY = get_settings_value('MANAGEMENT_IP_ONLY', True)
18+
PING_CHECK_CONFIG = get_settings_value('PING_CHECK_CONFIG', {})

openwisp_monitoring/check/tasks.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ def auto_create_snmp_devicemonitoring(
112112
Check = check_model or get_check_model()
113113
devicemonitoring_path = 'openwisp_monitoring.check.classes.Snmp'
114114
has_check = Check.objects.filter(
115-
object_id=object_id, content_type__model='device', check=devicemonitoring_path
115+
object_id=object_id,
116+
content_type__model='device',
117+
check_type=devicemonitoring_path,
116118
).exists()
117119
# create new check only if necessary
118120
if has_check:
@@ -121,7 +123,7 @@ def auto_create_snmp_devicemonitoring(
121123
ct = content_type_model.objects.get(app_label=app_label, model=model)
122124
check = Check(
123125
name='SNMP Device Monitoring',
124-
check=devicemonitoring_path,
126+
check_type=devicemonitoring_path,
125127
content_type=ct,
126128
object_id=object_id,
127129
)

openwisp_monitoring/check/tests/test_models.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ def test_check_class(self):
5454
)
5555
self.assertEqual(c.check_class, ConfigApplied)
5656
with self.subTest('Test DeviceMonitoring check Class'):
57-
c = Check(name='Snmp class check', check=self._SNMP_DEVICEMONITORING,)
57+
c = Check(
58+
name='Snmp class check',
59+
check_type=self._SNMP_DEVICEMONITORING,
60+
)
5861
self.assertEqual(c.check_class, Snmp)
5962

6063
def test_base_check_class(self):
@@ -92,7 +95,7 @@ def test_check_instance(self):
9295
with self.subTest('Test DeviceMonitoring check instance'):
9396
c = Check(
9497
name='DeviceMonitoring class check',
95-
check=self._SNMP_DEVICEMONITORING,
98+
check_type=self._SNMP_DEVICEMONITORING,
9699
content_object=obj,
97100
params={},
98101
)
@@ -254,7 +257,7 @@ def test_device_unreachable_no_config_check(self):
254257
d = self.device_model.objects.first()
255258
d.monitoring.update_status('critical')
256259
self.assertEqual(Check.objects.count(), 2)
257-
c2 = Check.objects.filter(check=self._CONFIG_APPLIED).first()
260+
c2 = Check.objects.filter(check_type=self._CONFIG_APPLIED).first()
258261
c2.perform_check()
259262
self.assertEqual(Metric.objects.count(), 0)
260263
self.assertIsNone(c2.perform_check())
@@ -265,7 +268,7 @@ def test_device_unknown_no_config_check(self):
265268
d = self.device_model.objects.first()
266269
d.monitoring.update_status('unknown')
267270
self.assertEqual(Check.objects.count(), 2)
268-
c2 = Check.objects.filter(check=self._CONFIG_APPLIED).first()
271+
c2 = Check.objects.filter(check_type=self._CONFIG_APPLIED).first()
269272
c2.perform_check()
270273
self.assertEqual(Metric.objects.count(), 0)
271274
self.assertEqual(Notification.objects.count(), 0)

openwisp_monitoring/check/tests/test_ping.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ def test_auto_chart_disabled(self, *args):
265265
device = self._create_device(organization=self._create_org())
266266
device.last_ip = '127.0.0.1'
267267
device.save()
268-
check = Check.objects.filter(check=self._PING).first()
268+
check = Check.objects.filter(check_type=self._PING).first()
269269
self.assertEqual(Chart.objects.count(), 0)
270270
check.perform_check()
271271
self.assertEqual(Chart.objects.count(), 0)

openwisp_monitoring/check/tests/test_snmp.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ class TestSnmp(CreateConnectionsMixin, TestDeviceMonitoringMixin, TransactionTes
2020
def test_snmp_perform_check(self):
2121
device = self._create_device()
2222
device.management_ip = '192.168.1.1'
23-
check = Check(check=self._SNMPDEVICEMONITORING, content_object=device)
23+
check = Check(
24+
name='SNMP check',
25+
check_type=self._SNMPDEVICEMONITORING,
26+
content_object=device,
27+
)
2428
with patch(
2529
'openwisp_monitoring.check.classes.snmp_devicemonitoring.OpenWRT'
2630
) as p:
@@ -31,11 +35,15 @@ def test_snmp_perform_check(self):
3135
def test_snmp_perform_check_with_credentials(self):
3236
device = self._create_device()
3337
device.management_ip = '192.168.1.1'
34-
check = Check(check=self._SNMPDEVICEMONITORING, content_object=device)
38+
check = Check(
39+
name='SNMP check',
40+
check_type=self._SNMPDEVICEMONITORING,
41+
content_object=device,
42+
)
3543
params = {'community': 'public', 'agent': 'my-agent', 'port': 161}
3644
cred = self._create_credentials(
3745
params=params,
38-
connector='openwisp_controller.connection.connectors.snmp.Snmp',
46+
connector='openwisp_controller.connection.connectors.openwrt.snmp.OpenWRTSnmp',
3947
)
4048
self._create_device_connection(
4149
credentials=cred, device=device, update_strategy=UPDATE_STRATEGIES[1][0]

openwisp_monitoring/device/api/views.py

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from pytz.exceptions import UnknownTimeZoneError
1919
from rest_framework import serializers, status
2020
from rest_framework.generics import GenericAPIView
21+
from rest_framework.permissions import BasePermission
2122
from rest_framework.response import Response
2223
from swapper import load_model
2324

@@ -36,6 +37,7 @@
3637

3738
logger = logging.getLogger(__name__)
3839
Chart = load_model('monitoring', 'Chart')
40+
Check = load_model('check', 'Check')
3941
Metric = load_model('monitoring', 'Metric')
4042
AlertSettings = load_model('monitoring', 'AlertSettings')
4143
Device = load_model('config', 'Device')
@@ -44,22 +46,28 @@
4446
Location = load_model('geo', 'Location')
4547

4648

47-
class DevicePermission(BasePermission):
49+
class DevicePermission(BasePermission): # noqa
4850
def has_object_permission(self, request, view, obj):
4951
return request.query_params.get('key') == obj.key
5052

5153

5254
class MetricChartsMixin:
53-
def _write(self, pk, data=None):
55+
def _write(self, pk, time=None, current=False):
5456
"""
5557
write metrics to database
5658
"""
57-
if data is None:
58-
# saves raw device data
59+
# If object not of type check ie. It is DeviceData
60+
if not hasattr(self, 'check_instance'):
5961
self.instance.save_data()
6062
data = self.instance.data
63+
device_extra_tags = self._get_extra_tags(self.instance)
64+
# Get data attribute from DeviceData object
65+
else:
66+
devicedata_instance = DeviceData.objects.get(pk=pk)
67+
data = getattr(devicedata_instance, 'data', {})
68+
device_extra_tags = self._get_extra_tags(devicedata_instance)
69+
6170
ct = ContentType.objects.get_for_model(Device)
62-
device_extra_tags = self._get_extra_tags(self.instance)
6371
for interface in data.get('interfaces', []):
6472
ifname = interface['name']
6573
extra_tags = Metric._sort_dict(device_extra_tags)
@@ -358,13 +366,19 @@ def _create_access_tech_chart(self, metric):
358366
chart.full_clean()
359367
chart.save()
360368

361-
def _init_previous_data(self, data=None):
369+
def _init_previous_data(self):
362370
"""
363371
makes NetJSON interfaces of previous
364372
snapshots more easy to access
365373
"""
366-
if data is None:
374+
375+
# If object not of type check
376+
if not hasattr(self, 'check_instance'):
367377
data = self.instance.data or {}
378+
# Get data attribute from Device object
379+
else:
380+
data = getattr(self.related_object, 'data', {})
381+
368382
if data:
369383
data = deepcopy(data)
370384
data['interfaces_dict'] = {}
@@ -375,7 +389,7 @@ def _init_previous_data(self, data=None):
375389

376390
class DeviceMetricView(GenericAPIView, MetricChartsMixin):
377391
model = DeviceData
378-
queryset = DeviceData.objects.all()
392+
queryset = DeviceData.objects.select_related('devicelocation').all()
379393
serializer_class = serializers.Serializer
380394
permission_classes = [DevicePermission]
381395
schema = schema
@@ -421,13 +435,21 @@ def _get_charts_data(self, charts, time, timezone):
421435
# prepare chart dict
422436
try:
423437
chart_dict = chart.read(time=time, x_axys=x_axys, timezone=timezone)
438+
if not chart_dict['traces']:
439+
continue
424440
chart_dict['description'] = chart.description
425-
chart_dict['title'] = chart.title.format(metric=chart.metric)
441+
chart_dict['title'] = chart.title.format(
442+
metric=chart.metric, **chart.metric.tags
443+
)
426444
chart_dict['type'] = chart.type
427445
chart_dict['unit'] = chart.unit
428446
chart_dict['summary_labels'] = chart.summary_labels
429447
chart_dict['colors'] = chart.colors
430448
chart_dict['colorscale'] = chart.colorscale
449+
for attr in ['fill', 'xaxis', 'yaxis']:
450+
value = getattr(chart, attr)
451+
if value:
452+
chart_dict[attr] = value
431453
except InvalidChartConfigException:
432454
logger.exception(f'Skipped chart for metric {chart.metric}')
433455
continue
@@ -492,14 +514,28 @@ def post(self, request, pk):
492514
except ValidationError as e:
493515
logger.info(e.message)
494516
return Response(e.message, status=status.HTTP_400_BAD_REQUEST)
517+
time_obj = request.query_params.get(
518+
'time', now().utcnow().strftime('%d-%m-%Y_%H:%M:%S.%f')
519+
)
520+
current = request.query_params.get('current', False)
521+
try:
522+
time = datetime.strptime(time_obj, '%d-%m-%Y_%H:%M:%S.%f').replace(
523+
tzinfo=UTC
524+
)
525+
except ValueError:
526+
return Response({'detail': _('Incorrect time format')}, status=400)
495527
try:
496528
# write data
497-
self._write(self.instance.pk)
529+
self._write(self.instance.pk, time=time)
498530
except ValidationError as e:
499531
logger.info(e.message_dict)
500532
return Response(e.message_dict, status=status.HTTP_400_BAD_REQUEST)
501533
device_metrics_received.send(
502-
sender=self.model, instance=self.instance, request=request
534+
sender=self.model,
535+
instance=self.instance,
536+
request=request,
537+
time=time,
538+
current=current,
503539
)
504540
return Response(None)
505541

0 commit comments

Comments
 (0)