def _collect_periodic_tasks(self, admin_context): """Collect driver-specific periodic tasks. Conductor periodic tasks accept context argument, driver periodic tasks accept this manager and context. We have to ensure that the same driver interface class is not traversed twice, otherwise we'll have several instances of the same task. :param admin_context: Administrator context to pass to tasks. """ LOG.debug('Collecting periodic tasks') # collected callables periodic_task_callables = [] # list of visited classes to avoid adding the same tasks twice periodic_task_classes = set() def _collect_from(obj, args): """Collect tasks from the given object. :param obj: the object to collect tasks from. :param args: a tuple of arguments to pass to tasks. """ if obj and obj.__class__ not in periodic_task_classes: for name, member in inspect.getmembers(obj): if periodics.is_periodic(member): LOG.debug('Found periodic task %(owner)s.%(member)s', { 'owner': obj.__class__.__name__, 'member': name }) periodic_task_callables.append((member, args, {})) periodic_task_classes.add(obj.__class__) # First, collect tasks from the conductor itself _collect_from(self, (admin_context, )) # Second, collect tasks from hardware interfaces for ifaces in driver_factory.all_interfaces().values(): for iface in ifaces.values(): _collect_from(iface, args=(self, admin_context)) # TODO(dtantsur): allow periodics on hardware types themselves? if len(periodic_task_callables) > CONF.conductor.workers_pool_size: LOG.warning( 'This conductor has %(tasks)d periodic tasks ' 'enabled, but only %(workers)d task workers ' 'allowed by [conductor]workers_pool_size option', { 'tasks': len(periodic_task_callables), 'workers': CONF.conductor.workers_pool_size }) self._periodic_tasks = periodics.PeriodicWorker( periodic_task_callables, executor_factory=periodics.ExistingExecutor(self._executor)) # This is only used in tests currently. Delete it? self._periodic_task_callables = periodic_task_callables
def _collect_periodic_tasks(self, admin_context): """Collect driver-specific periodic tasks. Conductor periodic tasks accept context argument, driver periodic tasks accept this manager and context. We have to ensure that the same driver interface class is not traversed twice, otherwise we'll have several instances of the same task. :param admin_context: Administrator context to pass to tasks. """ LOG.debug('Collecting periodic tasks') # collected callables periodic_task_callables = [] # list of visited classes to avoid adding the same tasks twice periodic_task_classes = set() def _collect_from(obj, args): """Collect tasks from the given object. :param obj: the object to collect tasks from. :param args: a tuple of arguments to pass to tasks. """ if obj and obj.__class__ not in periodic_task_classes: for name, member in inspect.getmembers(obj): if periodics.is_periodic(member): LOG.debug('Found periodic task %(owner)s.%(member)s', {'owner': obj.__class__.__name__, 'member': name}) periodic_task_callables.append((member, args, {})) periodic_task_classes.add(obj.__class__) # First, collect tasks from the conductor itself _collect_from(self, (admin_context,)) # Second, collect tasks from hardware interfaces for ifaces in driver_factory.all_interfaces().values(): for iface in ifaces.values(): _collect_from(iface, args=(self, admin_context)) # TODO(dtantsur): allow periodics on hardware types themselves? if len(periodic_task_callables) > CONF.conductor.workers_pool_size: LOG.warning('This conductor has %(tasks)d periodic tasks ' 'enabled, but only %(workers)d task workers ' 'allowed by [conductor]workers_pool_size option', {'tasks': len(periodic_task_callables), 'workers': CONF.conductor.workers_pool_size}) self._periodic_tasks = periodics.PeriodicWorker( periodic_task_callables, executor_factory=periodics.ExistingExecutor(self._executor)) # This is only used in tests currently. Delete it? self._periodic_task_callables = periodic_task_callables