From 47177c6b58fa84f2d1359eb520d5af5608c1818f Mon Sep 17 00:00:00 2001 From: Andy McKay Date: Fri, 12 Nov 2010 13:52:00 -0800 Subject: [PATCH] add in cronjob to delete from tmp (bug 603338) --- apps/cronjobs/__init__.py | 7 ++++ apps/cronjobs/management/__init__.py | 0 apps/cronjobs/management/commands/__init__.py | 0 apps/cronjobs/management/commands/cron.py | 40 +++++++++++++++++++ apps/jetpack/cron.py | 32 +++++++++++++++ apps/jetpack/tests/xpibuild_tests.py | 24 ++++++++++- settings.py | 3 +- 7 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 apps/cronjobs/__init__.py create mode 100644 apps/cronjobs/management/__init__.py create mode 100644 apps/cronjobs/management/commands/__init__.py create mode 100644 apps/cronjobs/management/commands/cron.py create mode 100644 apps/jetpack/cron.py diff --git a/apps/cronjobs/__init__.py b/apps/cronjobs/__init__.py new file mode 100644 index 00000000..25cd8c4a --- /dev/null +++ b/apps/cronjobs/__init__.py @@ -0,0 +1,7 @@ +registered = {} + + +def register(f): + """Decorator to add the function to the cronjob library.""" + registered[f.__name__] = f + return f diff --git a/apps/cronjobs/management/__init__.py b/apps/cronjobs/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/cronjobs/management/commands/__init__.py b/apps/cronjobs/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/cronjobs/management/commands/cron.py b/apps/cronjobs/management/commands/cron.py new file mode 100644 index 00000000..6c565fd6 --- /dev/null +++ b/apps/cronjobs/management/commands/cron.py @@ -0,0 +1,40 @@ +import sys + +from django.conf import settings +from django.core.management.base import BaseCommand + +import commonware.log + +import cronjobs + +log = commonware.log.getLogger('z.cron') + + +class Command(BaseCommand): + help = 'Run a script, often a cronjob' + args = '[name args...]' + + def handle(self, *args, **opts): + # Load up all the cron scripts. + for app in settings.INSTALLED_APPS: + try: + __import__('%s.cron' % app) + except ImportError: + pass + + registered = cronjobs.registered + + if not args: + log.error("Cron called but doesn't know what to do.") + print 'Try one of these:\n%s' % '\n'.join(sorted(registered)) + sys.exit(1) + + script, args = args[0], args[1:] + if script not in registered: + log.error("Cron called with unrecognized command: %s %s" % (script, args)) + print 'Unrecognized name: %s' % script + sys.exit(1) + + log.info("Beginning job: %s %s" % (script, args)) + registered[script](*args) + log.info("Ending job: %s %s" % (script, args)) diff --git a/apps/jetpack/cron.py b/apps/jetpack/cron.py new file mode 100644 index 00000000..716c5915 --- /dev/null +++ b/apps/jetpack/cron.py @@ -0,0 +1,32 @@ +import os +import shutil +import stat +import time + +from django.conf import settings + +import commonware +import cronjobs + +length = 60 * 60 * 24 # one day +log = commonware.log.getLogger('z.cron') + + +def find_files(): + files = [] + tmp_dir = os.path.dirname(settings.SDKDIR_PREFIX) + for filename in os.listdir(tmp_dir): + full = os.path.join(tmp_dir, filename) + + if full.startswith(settings.SDKDIR_PREFIX): + files.append(full) + return files + + +@cronjobs.register +def clean_tmp(length=length): + older = time.time() - length + for filename in find_files(): + if (os.stat(filename)[stat.ST_MTIME] < older): + shutil.rmtree(filename) + log.info('Deleted: %s' % filename) diff --git a/apps/jetpack/tests/xpibuild_tests.py b/apps/jetpack/tests/xpibuild_tests.py index 9ea04cf0..2a0235a6 100644 --- a/apps/jetpack/tests/xpibuild_tests.py +++ b/apps/jetpack/tests/xpibuild_tests.py @@ -3,13 +3,14 @@ import simplejson from utils.test import TestCase +from nose.tools import eq_ from django.contrib.auth.models import User from django.conf import settings -from jetpack.models import Package, PackageRevision, Module +from jetpack.models import Module, Package, PackageRevision, SDK from jetpack.xpi_utils import sdk_copy, xpi_build - +from jetpack.cron import find_files, clean_tmp class XPIBuildTest(TestCase): @@ -216,3 +217,22 @@ def test_xpi_with_dependency(self): self.failUnless(os.path.isfile('%s/packages/%s/%s.xpi' % ( self.SDKDIR, self.addon.get_unique_package_name(), self.addon.name))) + + def test_xpi_clean(self): + """Test that we clean up the /tmp directory correctly.""" + sdk = SDK.objects.create(version='0.8', + core_lib_id=6, + dir='jetpack-sdk-0.8') + rev = Package.objects.get(id=4).revisions.all()[0] + rev.sdk = sdk + rev.save() + + # Clean out /tmp directory. + [ shutil.rmtree(full) for full in find_files() ] + assert not find_files() + rev.build_xpi() + + # There should be one directory in the /tmp directory now. + eq_(len(find_files()), 1) + clean_tmp(length=0) + assert not find_files() diff --git a/settings.py b/settings.py index 9e0d532c..8e8f73e9 100644 --- a/settings.py +++ b/settings.py @@ -234,7 +234,8 @@ 'amo', # currently addons.mozilla.org authentication 'jetpack', # Jetpack functionality 'api', # API browser - 'tutorial' # Load tutorial templates + 'tutorial', # Load tutorial templates + 'cronjobs', ] # Which from above apps should be removed if in PRODUCTION