]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Sync periodic_task module from oslo-incubator
authorJay S. Bryant <jsbryant@us.ibm.com>
Sun, 15 Feb 2015 02:24:56 +0000 (20:24 -0600)
committerJay S. Bryant <jsbryant@us.ibm.com>
Sun, 15 Feb 2015 02:34:21 +0000 (20:34 -0600)
We have a need in Cinder to now be able to dynamically
add periodic tasks.  This sync brings in new functionality
that supports that.

Current HEAD in OSLO:
---------------------
commit 03143669d2c996f7c20d2d75f6c67827d2db216a
Date:   Tue Feb 10 11:59:45 2015 -0500
Update policy.py status in MAINTAINERS

Changes merged with this patch:
---------------------
2aacb111 Change oslo.config to oslo_config
2fbf5065 Remove oslo.log code and clean up versionutils API
fbd77a7b Allow overriding name for periodic tasks
9896e0e1 Separate add_periodic_task from the metaclass __init__

Change-Id: If39ce7baddd6ad5325afcd504bab8ac305da939d

cinder/openstack/common/periodic_task.py

index f05bca10bdc6ca4a5f43840ec9746471aaff9566..c9d4f8973e5251cf4c170ea8e561f44ba929ba35 100644 (file)
@@ -12,6 +12,7 @@
 #    under the License.
 
 import copy
+import logging
 import random
 import time
 
@@ -19,7 +20,6 @@ from oslo.config import cfg
 import six
 
 from cinder.openstack.common._i18n import _, _LE, _LI
-from cinder.openstack.common import log as logging
 
 
 periodic_opts = [
@@ -55,14 +55,15 @@ def periodic_task(*args, **kwargs):
            interval of 60 seconds.
 
         2. With arguments:
-           @periodic_task(spacing=N [, run_immediately=[True|False]])
+           @periodic_task(spacing=N [, run_immediately=[True|False]]
+           [, name=[None|"string"])
            this will be run on approximately every N seconds. If this number is
            negative the periodic task will be disabled. If the run_immediately
            argument is provided and has a value of 'True', the first run of the
            task will be shortly after task scheduler starts.  If
            run_immediately is omitted or set to 'False', the first time the
            task runs will be approximately N seconds after the task scheduler
-           starts.
+           starts. If name is not provided, __name__ of function is used.
     """
     def decorator(f):
         # Test for old style invocation
@@ -76,6 +77,7 @@ def periodic_task(*args, **kwargs):
             f._periodic_enabled = False
         else:
             f._periodic_enabled = kwargs.pop('enabled', True)
+        f._periodic_name = kwargs.pop('name', f.__name__)
 
         # Control frequency
         f._periodic_spacing = kwargs.pop('spacing', 0)
@@ -105,6 +107,36 @@ def periodic_task(*args, **kwargs):
 
 
 class _PeriodicTasksMeta(type):
+    def _add_periodic_task(cls, task):
+        """Add a periodic task to the list of periodic tasks.
+
+        The task should already be decorated by @periodic_task.
+
+        :return: whether task was actually enabled
+        """
+        name = task._periodic_name
+
+        if task._periodic_spacing < 0:
+            LOG.info(_LI('Skipping periodic task %(task)s because '
+                         'its interval is negative'),
+                     {'task': name})
+            return False
+        if not task._periodic_enabled:
+            LOG.info(_LI('Skipping periodic task %(task)s because '
+                         'it is disabled'),
+                     {'task': name})
+            return False
+
+        # A periodic spacing of zero indicates that this task should
+        # be run on the default interval to avoid running too
+        # frequently.
+        if task._periodic_spacing == 0:
+            task._periodic_spacing = DEFAULT_INTERVAL
+
+        cls._periodic_tasks.append((name, task))
+        cls._periodic_spacing[name] = task._periodic_spacing
+        return True
+
     def __init__(cls, names, bases, dict_):
         """Metaclass that allows us to collect decorated periodic tasks."""
         super(_PeriodicTasksMeta, cls).__init__(names, bases, dict_)
@@ -125,28 +157,7 @@ class _PeriodicTasksMeta(type):
 
         for value in cls.__dict__.values():
             if getattr(value, '_periodic_task', False):
-                task = value
-                name = task.__name__
-
-                if task._periodic_spacing < 0:
-                    LOG.info(_LI('Skipping periodic task %(task)s because '
-                                 'its interval is negative'),
-                             {'task': name})
-                    continue
-                if not task._periodic_enabled:
-                    LOG.info(_LI('Skipping periodic task %(task)s because '
-                                 'it is disabled'),
-                             {'task': name})
-                    continue
-
-                # A periodic spacing of zero indicates that this task should
-                # be run on the default interval to avoid running too
-                # frequently.
-                if task._periodic_spacing == 0:
-                    task._periodic_spacing = DEFAULT_INTERVAL
-
-                cls._periodic_tasks.append((name, task))
-                cls._periodic_spacing[name] = task._periodic_spacing
+                cls._add_periodic_task(value)
 
 
 def _nearest_boundary(last_run, spacing):
@@ -178,6 +189,15 @@ class PeriodicTasks(object):
         for name, task in self._periodic_tasks:
             self._periodic_last_run[name] = task._periodic_last_run
 
+    def add_periodic_task(self, task):
+        """Add a periodic task to the list of periodic tasks.
+
+        The task should already be decorated by @periodic_task.
+        """
+        if self.__class__._add_periodic_task(task):
+            self._periodic_last_run[task._periodic_name] = (
+                task._periodic_last_run)
+
     def run_periodic_tasks(self, context, raise_on_error=False):
         """Tasks to be run at a periodic interval."""
         idle_for = DEFAULT_INTERVAL