Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[change] Respect disabled organizations #552 #554

Merged
merged 3 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions openwisp_monitoring/check/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ def perform_check(self, store=True):
"""
initiates check instance and calls its check method
"""
if (
hasattr(self.content_object, 'organization_id')
and self.content_object.organization.is_active is False
):
return
return self.check_instance.check(store=True)

def perform_check_delayed(self, duration=0):
Expand Down
10 changes: 10 additions & 0 deletions openwisp_monitoring/check/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,16 @@ def test_device_unknown_no_config_check(self):
self.assertEqual(Notification.objects.count(), 0)
self.assertIsNone(c2.perform_check())

def test_device_organization_disabled_check_not_performed(self):
self._create_config(
status='modified', organization=self._create_org(is_active=False)
)
self.assertEqual(Check.objects.count(), 3)
check = Check.objects.filter(check_type=self._CONFIG_APPLIED).first()
with patch(f'{self._CONFIG_APPLIED}.check') as mocked_check:
check.perform_check()
mocked_check.assert_not_called()

def test_config_check_problem_with_interval(self):
self._create_admin()
d = self._create_device(organization=self._create_org())
Expand Down
2 changes: 1 addition & 1 deletion openwisp_monitoring/device/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def get_inlines(self, request, obj=None):
for inline in inlines:
if not hasattr(inline, 'sortable_options'):
inline.sortable_options = {'disabled': True}
if not obj or obj._state.adding:
if not obj or obj._state.adding or obj.organization.is_active is False:
inlines.remove(CheckInline)
inlines.remove(MetricInline)
return inlines
Expand Down
12 changes: 8 additions & 4 deletions openwisp_monitoring/device/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,14 @@ class DeviceMetricView(
"""

model = DeviceData
queryset = DeviceData.objects.only(
'id',
'key',
).all()
queryset = (
DeviceData.objects.filter(organization__is_active=True)
.only(
'id',
'key',
)
.all()
)
serializer_class = serializers.Serializer
permission_classes = [DevicePermission]
schema = schema
Expand Down
13 changes: 13 additions & 0 deletions openwisp_monitoring/device/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def connect_device_signals(self):
DeviceLocation = load_model('geo', 'DeviceLocation')
Metric = load_model('monitoring', 'Metric')
Chart = load_model('monitoring', 'Chart')
Organization = load_model('openwisp_users', 'Organization')

post_save.connect(
self.device_post_save_receiver,
Expand Down Expand Up @@ -120,6 +121,11 @@ def connect_device_signals(self):
sender=DeviceLocation,
dispatch_uid='post_delete_devicelocation_invalidate_devicedata_cache',
)
post_save.connect(
self.organization_post_save_receiver,
sender=Organization,
dispatch_uid='post_save_organization_disabled_monitoring',
)

@classmethod
def device_post_save_receiver(cls, instance, created, **kwargs):
Expand All @@ -134,6 +140,13 @@ def device_post_delete_receiver(cls, instance, **kwargs):
instance.checks.all().delete()
instance.metrics.all().delete()

@classmethod
def organization_post_save_receiver(cls, instance, *args, **kwargs):
if instance.is_active is False:
from .tasks import handle_disabled_organization

handle_disabled_organization.delay(str(instance.id))

def device_recovery_detection(self):
if not app_settings.DEVICE_RECOVERY_DETECTION:
return
Expand Down
19 changes: 19 additions & 0 deletions openwisp_monitoring/device/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,25 @@ def is_metric_critical(metric):
return True
return False

@classmethod
def handle_disabled_organization(cls, organization_id):
"""
Clears the management IP of all devices belonging to a
disabled organization and set their monitoring status to 'unknown'.

Parameters:
organization_id (int): The ID of the disabled organization.

Returns:
None
"""
load_model('config', 'Device').objects.filter(
organization_id=organization_id
).update(management_ip='')
cls.objects.filter(device__organization_id=organization_id).update(
status='unknown'
)


class AbstractWifiClient(TimeStampedEditableModel):
id = None
Expand Down
6 changes: 6 additions & 0 deletions openwisp_monitoring/device/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,9 @@ def write_device_metrics(pk, data, time=None, current=False):
except DeviceData.DoesNotExist:
return
device_data.writer.write(data, time, current)


@shared_task(base=OpenwispCeleryTask)
def handle_disabled_organization(organization_id):
DeviceMonitoring = load_model('device_monitoring', 'DeviceMonitoring')
DeviceMonitoring.handle_disabled_organization(organization_id)
19 changes: 19 additions & 0 deletions openwisp_monitoring/device/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,25 @@ def test_device_add_view(self):
self.assertContains(r, '<h2>Map</h2>')
self.assertContains(r, '<h2>Credentials</h2>')

def test_device_disabled_organization_admin(self):
self.create_test_data()
device = Device.objects.first()
Check.objects.create(
name='Ping check',
check_type=CHECK_CLASSES[0][0],
content_object=device,
params={},
)
org = device.organization
org.is_active = False
org.save()
url = reverse('admin:config_device_change', args=[device.pk])
response = self.client.get(url)
self.assertContains(response, '<h2>Status</h2>')
self.assertContains(response, '<h2>Charts</h2>')
self.assertNotContains(response, '<h2>Checks</h2>')
self.assertNotContains(response, '<h2>AlertSettings</h2>')

def test_remove_invalid_interface(self):
d = self._create_device(organization=self._create_org())
dd = DeviceData(name='test-device', pk=d.pk)
Expand Down
9 changes: 9 additions & 0 deletions openwisp_monitoring/device/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,15 @@ def test_200_no_date_supplied(self):
r = self.client.post(url, netjson, content_type='application/json')
self.assertEqual(r.status_code, 200)

def test_404_disabled_organization(self):
org = self._create_org(is_active=False)
device = self._create_device(organization=org)
with self.assertNumQueries(2):
response = self._post_data(device.id, device.key, self._data())
self.assertEqual(response.status_code, 404)
self.assertEqual(self.metric_queryset.count(), 0)
self.assertEqual(self.chart_queryset.count(), 0)

def test_garbage_wireless_clients(self):
o = self._create_org()
d = self._create_device(organization=o)
Expand Down
14 changes: 14 additions & 0 deletions openwisp_monitoring/device/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,20 @@ def test_deleting_device_deletes_tsdb(self):
self.assertEqual(self._read_metric(ping1), [])
self.assertNotEqual(self._read_metric(ping2), [])

def test_handle_disabled_organization(self):
device_monitoring, _, _, _ = self._create_env()
device = device_monitoring.device
device.management_ip = '10.10.0.5'
device.save()
self.assertEqual(device_monitoring.status, 'ok')
org = device.organization
org.is_active = False
org.save(update_fields=['is_active'])
device_monitoring.refresh_from_db()
device.refresh_from_db()
self.assertEqual(device_monitoring.status, 'unknown')
self.assertEqual(device.management_ip, None)


class TestWifiClientSession(TestWifiClientSessionMixin, TestCase):
wifi_client_model = WifiClient
Expand Down
Loading