Reuse 'periodic_task' from oslo_service

Remove Manila code related to 'periodic_tasks' and reuse it from 'oslo_service'
library.

Also, add call of parent's '__init__' method for 'manila.db.base.Base' class.
It is required for proper work of multiple inheritance where this class is
inherited. And remove it from inheritance by 'manila.network.neutron.api.API'
class as redundant.

Change-Id: I138fc2f475f8858788a9ab00f84ab9ee167a95c5
This commit is contained in:
Valeriy Ponomaryov 2015-07-20 19:11:20 +03:00
parent 8d0c93d3d7
commit 48221b0f4c
5 changed files with 12 additions and 94 deletions

View File

@ -31,6 +31,7 @@ class Base(object):
"""DB driver is injected in the init method."""
def __init__(self, db_driver=None):
super(Base, self).__init__()
if not db_driver:
db_driver = CONF.db_driver
self.db = importutils.import_module(db_driver) # pylint: disable=C0103

View File

@ -53,10 +53,9 @@ This module provides Manager, a base class for managers.
from oslo_config import cfg
from oslo_log import log
import six
from oslo_service import periodic_task
from manila.db import base
from manila.i18n import _LE
from manila.scheduler import rpcapi as scheduler_rpcapi
from manila import version
@ -64,69 +63,12 @@ CONF = cfg.CONF
LOG = log.getLogger(__name__)
def periodic_task(*args, **kwargs):
"""Decorator to indicate that a method is a periodic task.
This decorator can be used in two ways:
1. Without arguments '@periodic_task', this will be run on every tick
of the periodic scheduler.
2. With arguments, @periodic_task(ticks_between_runs=N), this will be
run on every N ticks of the periodic scheduler.
"""
def decorator(f):
f._periodic_task = True
f._ticks_between_runs = kwargs.pop('ticks_between_runs', 0)
return f
# NOTE(sirp): The `if` is necessary to allow the decorator to be used with
# and without parens.
#
# In the 'with-parens' 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 as the first argument, like:
#
# periodic_task(f)
if kwargs:
return decorator
else:
return decorator(args[0])
class PeriodicTasks(periodic_task.PeriodicTasks):
def __init__(self):
super(PeriodicTasks, self).__init__(CONF)
class ManagerMeta(type):
def __init__(cls, names, bases, dict_):
"""Metaclass that allows us to collect decorated periodic tasks."""
super(ManagerMeta, cls).__init__(names, bases, dict_)
# NOTE(sirp): if the attribute is not present then we must be the base
# class, so, go ahead an initialize it. If the attribute is present,
# then we're a subclass so make a copy of it so we don't step on our
# parent's toes.
try:
cls._periodic_tasks = cls._periodic_tasks[:]
except AttributeError:
cls._periodic_tasks = []
try:
cls._ticks_to_skip = cls._ticks_to_skip.copy()
except AttributeError:
cls._ticks_to_skip = {}
for value in cls.__dict__.values():
if getattr(value, '_periodic_task', False):
task = value
name = task.__name__
cls._periodic_tasks.append((name, task))
cls._ticks_to_skip[name] = task._ticks_between_runs
@six.add_metaclass(ManagerMeta)
class Manager(base.Base):
class Manager(base.Base, PeriodicTasks):
@property
def RPC_API_VERSION(self):
@ -153,29 +95,7 @@ class Manager(base.Base):
def periodic_tasks(self, context, raise_on_error=False):
"""Tasks to be run at a periodic interval."""
for task_name, task in self._periodic_tasks:
full_task_name = '.'.join([self.__class__.__name__, task_name])
ticks_to_skip = self._ticks_to_skip[task_name]
if ticks_to_skip > 0:
LOG.debug("Skipping %(full_task_name)s, %(ticks_to_skip)s"
" ticks left until next run",
{'full_task_name': full_task_name,
'ticks_to_skip': ticks_to_skip})
self._ticks_to_skip[task_name] -= 1
continue
self._ticks_to_skip[task_name] = task._ticks_between_runs
LOG.debug("Running periodic task %(full_task_name)s",
{'full_task_name': full_task_name})
try:
task(self, context)
except Exception as e:
if raise_on_error:
raise
LOG.exception(_LE("Error during %(full_task_name)s: %(e)s"),
{'full_task_name': full_task_name, 'e': e})
return self.run_periodic_tasks(context, raise_on_error=raise_on_error)
def init_host(self):
"""Handle initialization if this is a standalone service.
@ -215,7 +135,7 @@ class SchedulerDependentManager(Manager):
"""Remember these capabilities to send on next periodic update."""
self.last_capabilities = capabilities
@periodic_task
@periodic_task.periodic_task
def _publish_service_capabilities(self, context):
"""Pass data back to the scheduler at a periodic interval."""
if self.last_capabilities:

View File

@ -20,7 +20,6 @@ from oslo_config import cfg
from oslo_log import log
from manila import context
from manila.db import base
from manila import exception
from manila.i18n import _LE
from manila.network.neutron import constants as neutron_constants
@ -78,14 +77,13 @@ CONF = cfg.CONF
LOG = log.getLogger(__name__)
class API(base.Base):
class API(object):
"""API for interacting with the neutron 2.x API.
:param configuration: instance of config or config group.
"""
def __init__(self, config_group_name=None):
super(API, self).__init__()
self.config_group_name = config_group_name or 'DEFAULT'
CONF.register_opts(neutron_opts, group=self.config_group_name)
self.configuration = getattr(CONF, self.config_group_name, CONF)

View File

@ -24,6 +24,7 @@ import datetime
from oslo_config import cfg
from oslo_log import log
from oslo_serialization import jsonutils
from oslo_service import periodic_task
from oslo_utils import excutils
from oslo_utils import importutils
from oslo_utils import timeutils
@ -578,7 +579,7 @@ class ShareManager(manager.SchedulerDependentManager):
"deletion of last share.", share_server['id'])
self.delete_share_server(context, share_server)
@manager.periodic_task(ticks_between_runs=600 / CONF.periodic_interval)
@periodic_task.periodic_task(spacing=600)
def delete_free_share_servers(self, ctxt):
if not (self.driver.driver_handles_share_servers and
self.configuration.automatic_share_server_cleanup):
@ -702,7 +703,7 @@ class ShareManager(manager.SchedulerDependentManager):
context, access_id, {'state': access_ref.STATE_ERROR})
self.db.share_access_delete(context, access_id)
@manager.periodic_task
@periodic_task.periodic_task(spacing=CONF.periodic_interval)
def _report_driver_status(self, context):
LOG.info(_LI('Updating share status'))
share_stats = self.driver.get_share_stats(refresh=True)

View File

@ -30,7 +30,6 @@ class ManagerTestCase(test.TestCase):
db_driver = 'fake_driver'
fake_manager = manager.Manager(host, db_driver)
self.assertTrue(hasattr(fake_manager, '_periodic_tasks'))
self.assertTrue(hasattr(fake_manager, '_ticks_to_skip'))
self.assertTrue(hasattr(fake_manager, 'additional_endpoints'))
self.assertTrue(hasattr(fake_manager, 'host'))
self.assertTrue(hasattr(fake_manager, 'periodic_tasks'))
@ -51,7 +50,6 @@ class SchedulerDependentManagerTestCase(test.TestCase):
fake_sched_manager = manager.SchedulerDependentManager(
host, db_driver, service_name)
self.assertTrue(hasattr(fake_sched_manager, '_periodic_tasks'))
self.assertTrue(hasattr(fake_sched_manager, '_ticks_to_skip'))
self.assertTrue(hasattr(fake_sched_manager, 'additional_endpoints'))
self.assertTrue(hasattr(fake_sched_manager, 'host'))
self.assertTrue(hasattr(fake_sched_manager, 'periodic_tasks'))