James Valleroy d9491d5762
diagnostics: Run daily check and notify on failures
- One notification is shown with a count of the highest severity issues.

- Un-dismiss the notification, so it is shown even if previously dismissed.

- Add link to see the results, which are stored in a global variable.

- Add a lock for running_task.

Tests:

- Notification with 2 warnings shown on stable container due, to packages not
  upgraded.

- Change the firewalld default zone to public. After the next run, the
  notification changes to an error, and shows 1 failure.

Helps #2366.

Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
2023-10-07 04:52:08 +09:00

76 lines
2.2 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""
FreedomBox app for running diagnostics.
"""
import logging
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.decorators.http import require_POST
from plinth.app import App
from plinth.modules import diagnostics
from plinth.views import AppView
logger = logging.getLogger(__name__)
class DiagnosticsView(AppView):
"""Diagnostics app page."""
app_id = 'diagnostics'
template_name = 'diagnostics.html'
def post(self, request):
"""Start diagnostics."""
with diagnostics.running_task_lock:
if not diagnostics.running_task:
diagnostics.start_task()
return HttpResponseRedirect(reverse('diagnostics:index'))
def get_context_data(self, **kwargs):
"""Return additional context for rendering the template."""
with diagnostics.running_task_lock:
is_task_running = diagnostics.running_task is not None
with diagnostics.results_lock:
results = diagnostics.current_results
context = super().get_context_data(**kwargs)
context['has_diagnostics'] = False
context['is_task_running'] = is_task_running
context['results'] = results
context['refresh_page_sec'] = 3 if is_task_running else None
return context
@require_POST
def diagnose_app(request, app_id):
"""Return diagnostics for a particular app."""
try:
app = App.get(app_id)
except KeyError:
raise Http404('App does not exist')
app_name = app.info.name or app_id
diagnosis = None
diagnosis_exception = None
try:
diagnosis = app.diagnose()
except Exception as exception:
logger.exception('Error running %s diagnostics - %s', app_id,
exception)
diagnosis_exception = str(exception)
return TemplateResponse(
request, 'diagnostics_app.html', {
'title': _('Diagnostic Test'),
'app_name': app_name,
'results': diagnosis,
'exception': diagnosis_exception,
})