Skip to content

Commit

Permalink
Implement disk space alerts. Closes #756.
Browse files Browse the repository at this point in the history
  • Loading branch information
onyxfish committed Jun 18, 2012
1 parent 1445895 commit 647159a
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 20 deletions.
18 changes: 18 additions & 0 deletions client/utils.py
@@ -0,0 +1,18 @@
#!/usr/bin/env python

import os

def get_total_disk_space(p):
"""
Calculate the total disk space of the device on which a given file path resides.
"""
s = os.statvfs(p)
return s.f_frsize * s.f_blocks

def get_free_disk_space(p):
"""
Returns the number of free bytes on the drive that ``p`` is on
"""
s = os.statvfs(p)
return s.f_frsize * s.f_bavail

27 changes: 7 additions & 20 deletions client/views.py
Expand Up @@ -14,6 +14,7 @@
from livesettings import config_value from livesettings import config_value
from tastypie.serializers import Serializer from tastypie.serializers import Serializer


from client import utils
from panda.api.category import CategoryResource from panda.api.category import CategoryResource
from panda.models import ActivityLog, Category, Dataset, SearchLog, UserProxy from panda.models import ActivityLog, Category, Dataset, SearchLog, UserProxy


Expand Down Expand Up @@ -49,20 +50,6 @@ def index(request):
}) })
}) })


def _get_total_disk_space(p):
"""
Calculate the total disk space of the device on which a given file path resides.
"""
s = os.statvfs(p)
return s.f_frsize * s.f_blocks

def _get_free_disk_space(p):
"""
Returns the number of free bytes on the drive that ``p`` is on
"""
s = os.statvfs(p)
return s.f_frsize * s.f_bavail

def dashboard(request): def dashboard(request):
""" """
Render HTML for dashboard/metrics view. Render HTML for dashboard/metrics view.
Expand Down Expand Up @@ -143,22 +130,22 @@ def dashboard(request):
upload_disk = os.stat(settings.MEDIA_ROOT).st_dev upload_disk = os.stat(settings.MEDIA_ROOT).st_dev
indices_disk = os.stat(settings.SOLR_DIRECTORY).st_dev indices_disk = os.stat(settings.SOLR_DIRECTORY).st_dev


root_disk_total = _get_total_disk_space('/') root_disk_total = utils.get_total_disk_space('/')
root_disk_free = _get_free_disk_space('/') root_disk_free = utils.get_free_disk_space('/')
root_disk_percent_used = 100 - (float(root_disk_free) / root_disk_total * 100) root_disk_percent_used = 100 - (float(root_disk_free) / root_disk_total * 100)


if upload_disk != root_disk: if upload_disk != root_disk:
upload_disk_total = _get_total_disk_space(settings.MEDIA_ROOT) upload_disk_total = utils.get_total_disk_space(settings.MEDIA_ROOT)
upload_disk_free = _get_free_disk_space(settings.MEDIA_ROOT) upload_disk_free = utils.get_free_disk_space(settings.MEDIA_ROOT)
upload_disk_percent_used = 100 - (float(upload_disk_free) / upload_disk_total * 100) upload_disk_percent_used = 100 - (float(upload_disk_free) / upload_disk_total * 100)
else: else:
upload_disk_total = None upload_disk_total = None
upload_disk_free = None upload_disk_free = None
upload_disk_percent_used = None upload_disk_percent_used = None


if indices_disk != root_disk: if indices_disk != root_disk:
indices_disk_total = _get_total_disk_space(settings.SOLR_DIRECTORY) indices_disk_total = utils.get_total_disk_space(settings.SOLR_DIRECTORY)
indices_disk_free = _get_free_disk_space(settings.SOLR_DIRECTORY) indices_disk_free = utils.get_free_disk_space(settings.SOLR_DIRECTORY)
indices_disk_percent_used = 100 - (float(indices_disk_free) / indices_disk_total * 100) indices_disk_percent_used = 100 - (float(indices_disk_free) / indices_disk_total * 100)
else: else:
indices_disk_total = None indices_disk_total = None
Expand Down
4 changes: 4 additions & 0 deletions config/settings.py
Expand Up @@ -143,6 +143,10 @@
'run_subscriptions': { 'run_subscriptions': {
'task': 'panda.tasks.cron.run_subscriptions', 'task': 'panda.tasks.cron.run_subscriptions',
'schedule': crontab(minute=30, hour=2) 'schedule': crontab(minute=30, hour=2)
},
'run_admin_alerts': {
'task': 'panda.tasks.cron.run_admin_alerts',
'schedule': crontab(minute=0, hour=4)
} }
} }


Expand Down
1 change: 1 addition & 0 deletions panda/tasks/__init__.py
Expand Up @@ -8,6 +8,7 @@
from panda.tasks.purge_data import PurgeDataTask from panda.tasks.purge_data import PurgeDataTask
from panda.tasks.purge_orphaned_uploads import PurgeOrphanedUploadsTask from panda.tasks.purge_orphaned_uploads import PurgeOrphanedUploadsTask
from panda.tasks.reindex import ReindexTask from panda.tasks.reindex import ReindexTask
from panda.tasks.run_admin_alerts import RunAdminAlertsTask
from panda.tasks.run_subscriptions import RunSubscriptionsTask from panda.tasks.run_subscriptions import RunSubscriptionsTask


TASKS_BY_TYPE = { TASKS_BY_TYPE = {
Expand Down
92 changes: 92 additions & 0 deletions panda/tasks/run_admin_alerts.py
@@ -0,0 +1,92 @@
#!/usr/bin/env python

import logging
import os

from celery.task import Task
from django.conf import settings
from django.template import Context
from livesettings import config_value

from client.utils import get_total_disk_space, get_free_disk_space
from panda.utils.mail import send_mail
from panda.utils.notifications import get_email_subject_template, get_email_body_template

class RunAdminAlertsTask(Task):
"""
Notify administrators of anything which requires their attention (disk space, etc).
"""
name = 'panda.tasks.cron.run_admin_alerts'

def run(self, *args, **kwargs):
from panda.models import UserProxy

log = logging.getLogger(self.name)
log.info('Running admin alerts')

# Disk space
root_disk = os.stat('/').st_dev
upload_disk = os.stat(settings.MEDIA_ROOT).st_dev
indices_disk = os.stat(settings.SOLR_DIRECTORY).st_dev

root_disk_total = get_total_disk_space('/')
root_disk_free = get_free_disk_space('/')
root_disk_percent_used = 100 - (float(root_disk_free) / root_disk_total * 100)

if upload_disk != root_disk:
upload_disk_total = get_total_disk_space(settings.MEDIA_ROOT)
upload_disk_free = get_free_disk_space(settings.MEDIA_ROOT)
upload_disk_percent_used = 100 - (float(upload_disk_free) / upload_disk_total * 100)
else:
upload_disk_total = None
upload_disk_free = None
upload_disk_percent_used = None

if indices_disk != root_disk:
indices_disk_total = get_total_disk_space(settings.SOLR_DIRECTORY)
indices_disk_free = get_free_disk_space(settings.SOLR_DIRECTORY)
indices_disk_percent_used = 100 - (float(indices_disk_free) / indices_disk_total * 100)
else:
indices_disk_total = None
indices_disk_free = None
indices_disk_percent_used = None

notify = False

for free in (root_disk_free, upload_disk_free, indices_disk_free):
if free is None:
continue

if free < settings.PANDA_AVAILABLE_SPACE_WARN:
notify = True

if notify:
context = Context({
'root_disk': root_disk,
'upload_disk': upload_disk,
'indices_disk': indices_disk,
'root_disk_total': root_disk_total,
'root_disk_free': root_disk_free,
'root_disk_percent_used': root_disk_percent_used,
'upload_disk_total': upload_disk_total,
'upload_disk_free': upload_disk_free,
'upload_disk_percent_used': upload_disk_percent_used,
'indices_disk_total': indices_disk_total,
'indices_disk_free': indices_disk_free,
'indices_disk_percent_used': indices_disk_percent_used,
'settings': settings,
'site_domain': config_value('DOMAIN', 'SITE_DOMAIN')
})

# Don't HTML escape plain-text emails
context.autoescape = False

email_subject = get_email_subject_template('disk_space_alert').render(context)
email_message = get_email_body_template('disk_space_alert').render(context)

recipients = UserProxy.objects.filter(is_superuser=True, is_active=True)

send_mail(email_subject.strip(), email_message, [r.email for r in recipients])

log.info('Finished running admin alerts')

6 changes: 6 additions & 0 deletions panda/templates/notifications/disk_space_alert/email_body.txt
@@ -0,0 +1,6 @@
{% if root_disk_free < settings.PANDA_AVAILABLE_SPACE_WARN %}* The drive containing your PANDA application is {% if root_disk_free < settings.PANDA_AVAILABLE_SPACE_CRITICAL %}CRITICALLY {% endif %}low on disk space: {{ root_disk_free|filesizeformat }} remains ({{ root_disk_percent_used|floatformat }}% full){% endif %}
{% if upload_disk_total != None and upload_disk_free < settings.PANDA_AVAILABLE_SPACE_WARN %}* The drive containing your PANDA's uploads is {% if upload_disk_free < settings.PANDA_AVAILABLE_SPACE_CRITICAL %}CRITICALLY {% endif %}low on disk space: {{ upload_disk_free|filesizeformat }} remains ({{ upload_disk_percent_used|floatformat }}% full){% endif %}
{% if indices_disk_total and indices_disk_free < settings.PANDA_AVAILABLE_SPACE_WARN %}* The drive containing your PANDA's search indices ({{ indices_disk }}) is {% if indices_disk_free < settings.PANDA_AVAILABLE_SPACE_CRITICAL %}CRITICALLY {% endif %}low on disk space: {{ indices_disk_free|filesizeformat }} remains ({{ indices_disk_percent_used|floatformat }}% full){% endif %}

Your can always check your current disk usage on your PANDA Dashboard:
http://{{ site_domain }}/#dashboard
@@ -0,0 +1 @@
Low disk space!

0 comments on commit 647159a

Please sign in to comment.