]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Sync periodic_task from oslo-incubator
authorMatt Riedemann <mriedem@us.ibm.com>
Thu, 29 May 2014 15:45:55 +0000 (08:45 -0700)
committerMatt Riedemann <mriedem@us.ibm.com>
Thu, 29 May 2014 18:33:07 +0000 (11:33 -0700)
This is more or less to get commit c63fd5a from oslo into the core
projects which have several periodic tasks.  Cinder has periodic tasks
to sync up volume state with the server and they don't have specific
spacing values set which can lead to non-deterministic spacing of when
the tasks run.

Note that this does not include the gettextutils and log dependencies
since there are not functional changes in those modules needed for the
periodic_task changes synced in *and* more importantly, the changes
to gettextutils and log require pervasive changes to cinder which
should happen when cinder integrates with the oslo-i18n library for
blueprint i18n--messages.

Further note that this does not include jsonutils due to some
issues introduced with a change for python 2.6 that impacts how strings
are encoded with simplejson. The details for that issue are in bug
1314129.  The jsonutils changes are not related to the periodic_task
changes being synced in so the dependency is not functionally required.

cinder.db.base.Base is also updated otherwise multiple inheritance
involving that class will not work, which impacts all of the classes
that extend cinder.manager.Manager which extends both cinder.db.Base
and PeriodicTasks, and commit 47c9d60 adds attributes to the __init__
for PeriodicTasks.  Nova had the same change with commit 5ae97ea.

Changes:

c63fd5a Make unspecified periodic spaced tasks run on default interval
f0dd798 Remove rendundant parentheses of cfg help strings
fcf517d Update oslo log messages with translation domains
051b9f3 Refactor unnecessary arithmetic ops in periodic_task
674cdaf Refactor if logic in periodic_task
b6b82c5 Use timestamp in periodic tasks
47c9d60 Don't share periodic_task instance data in a class attr
8b2b0b7 Use hacking import_exceptions for gettextutils._
c5a1088 Typos fix in db and periodic_task module
12bcdb7 Remove vim header

Related-Bug: #1319232

Change-Id: I13e8ac83bcd9e60a8eb05ed9cdfea00b9e5fb398

cinder/db/base.py
cinder/openstack/common/periodic_task.py

index 76fbc99aff225db24df333b11f0db6c24aa441cb..da51fdde13d7d2ec5d5f5df637d5299b095ba2ea 100644 (file)
@@ -34,6 +34,9 @@ class Base(object):
     """DB driver is injected in the init method."""
 
     def __init__(self, db_driver=None):
+        # NOTE(mriedem): Without this call, multiple inheritance involving
+        # the db Base class does not work correctly.
+        super(Base, self).__init__()
         if not db_driver:
             db_driver = CONF.db_driver
         self.db = importutils.import_module(db_driver)  # pylint: disable=C0103
index 44faab560be531200e354c7fa350e83e330ca66b..e5d32e39c867ebd8881ee127fb017020e6a33dc8 100644 (file)
@@ -1,5 +1,3 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
 #    not use this file except in compliance with the License. You may obtain
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import datetime
 import time
 
 from oslo.config import cfg
 import six
 
-from cinder.openstack.common.gettextutils import _  # noqa
+from cinder.openstack.common.gettextutils import _, _LE, _LI
 from cinder.openstack.common import log as logging
-from cinder.openstack.common import timeutils
 
 
 periodic_opts = [
     cfg.BoolOpt('run_external_periodic_tasks',
                 default=True,
-                help=('Some periodic tasks can be run in a separate process. '
-                      'Should we run them here?')),
+                help='Some periodic tasks can be run in a separate process. '
+                     'Should we run them here?'),
 ]
 
 CONF = cfg.CONF
@@ -48,8 +44,8 @@ def periodic_task(*args, **kwargs):
 
     This decorator can be used in two ways:
 
-        1. Without arguments '@periodic_task', this will be run on every cycle
-           of the periodic scheduler.
+        1. Without arguments '@periodic_task', this will be run on the default
+           interval of 60 seconds.
 
         2. With arguments:
            @periodic_task(spacing=N [, run_immediately=[True|False]])
@@ -80,18 +76,18 @@ def periodic_task(*args, **kwargs):
         if f._periodic_immediate:
             f._periodic_last_run = None
         else:
-            f._periodic_last_run = timeutils.utcnow()
+            f._periodic_last_run = time.time()
         return f
 
     # NOTE(sirp): The `if` is necessary to allow the decorator to be used with
-    # and without parens.
+    # and without parents.
     #
-    # In the 'with-parens' case (with kwargs present), this function needs to
+    # In the 'with-parents' case (with kwargs present), this function needs to
     # return a decorator function since the interpreter will invoke it like:
     #
     #   periodic_task(*args, **kwargs)(f)
     #
-    # In the 'without-parens' case, the original function will be passed
+    # In the 'without-parents' case, the original function will be passed
     # in as the first argument, like:
     #
     #   periodic_task(f)
@@ -115,11 +111,6 @@ class _PeriodicTasksMeta(type):
         except AttributeError:
             cls._periodic_tasks = []
 
-        try:
-            cls._periodic_last_run = cls._periodic_last_run.copy()
-        except AttributeError:
-            cls._periodic_last_run = {}
-
         try:
             cls._periodic_spacing = cls._periodic_spacing.copy()
         except AttributeError:
@@ -131,28 +122,33 @@ class _PeriodicTasksMeta(type):
                 name = task.__name__
 
                 if task._periodic_spacing < 0:
-                    LOG.info(_('Skipping periodic task %(task)s because '
-                               'its interval is negative'),
+                    LOG.info(_LI('Skipping periodic task %(task)s because '
+                                 'its interval is negative'),
                              {'task': name})
                     continue
                 if not task._periodic_enabled:
-                    LOG.info(_('Skipping periodic task %(task)s because '
-                               'it is disabled'),
+                    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 every pass
+                # be run on the default interval to avoid running too
+                # frequently.
                 if task._periodic_spacing == 0:
-                    task._periodic_spacing = None
+                    task._periodic_spacing = DEFAULT_INTERVAL
 
                 cls._periodic_tasks.append((name, task))
                 cls._periodic_spacing[name] = task._periodic_spacing
-                cls._periodic_last_run[name] = task._periodic_last_run
 
 
 @six.add_metaclass(_PeriodicTasksMeta)
 class PeriodicTasks(object):
+    def __init__(self):
+        super(PeriodicTasks, self).__init__()
+        self._periodic_last_run = {}
+        for name, task in self._periodic_tasks:
+            self._periodic_last_run[name] = task._periodic_last_run
 
     def run_periodic_tasks(self, context, raise_on_error=False):
         """Tasks to be run at a periodic interval."""
@@ -160,30 +156,27 @@ class PeriodicTasks(object):
         for task_name, task in self._periodic_tasks:
             full_task_name = '.'.join([self.__class__.__name__, task_name])
 
-            now = timeutils.utcnow()
             spacing = self._periodic_spacing[task_name]
             last_run = self._periodic_last_run[task_name]
 
             # If a periodic task is _nearly_ due, then we'll run it early
-            if spacing is not None and last_run is not None:
-                due = last_run + datetime.timedelta(seconds=spacing)
-                if not timeutils.is_soon(due, 0.2):
-                    idle_for = min(idle_for, timeutils.delta_seconds(now, due))
+            idle_for = min(idle_for, spacing)
+            if last_run is not None:
+                delta = last_run + spacing - time.time()
+                if delta > 0.2:
+                    idle_for = min(idle_for, delta)
                     continue
 
-            if spacing is not None:
-                idle_for = min(idle_for, spacing)
-
-            LOG.debug(_("Running periodic task %(full_task_name)s"),
+            LOG.debug("Running periodic task %(full_task_name)s",
                       {"full_task_name": full_task_name})
-            self._periodic_last_run[task_name] = timeutils.utcnow()
+            self._periodic_last_run[task_name] = time.time()
 
             try:
                 task(self, context)
             except Exception as e:
                 if raise_on_error:
                     raise
-                LOG.exception(_("Error during %(full_task_name)s: %(e)s"),
+                LOG.exception(_LE("Error during %(full_task_name)s: %(e)s"),
                               {"full_task_name": full_task_name, "e": e})
             time.sleep(0)