nova-compute启动分析-3

来源:互联网 发布:北京php工程师培训 编辑:程序博客网 时间:2024/06/05 03:28

在nova/service.py中Service类中start方法中

 if self.periodic_interval:            periodic = utils.LoopingCall(self.periodic_tasks) #循环调用 periodic_tasks 下面详细说明            periodic.start(interval=self.periodic_interval, now=False)            self.timers.append(periodic)

此出循环调用 self.periodic_tasks

def periodic_tasks(self, raise_on_error=False):        """Tasks to be run at a periodic interval."""        ctxt = context.get_admin_context()        self.manager.periodic_tasks(ctxt, raise_on_error=raise_on_error)

调用self.manager. periodic_tasks 函数。 

其中manager 就是nova/compute/manager.py 中 ComputeManager

ComputeManager的父类SchedulerDependentManager

SchedulerDependentManager父类Manager(nova/manager.py)(可以参考nova-compute启动分析-1中manager类图)


  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"), locals())                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"), locals())            try:                task(self, context)            except Exception as e:                if raise_on_error:                    raise                LOG.exception(_("Error during %(full_task_name)s: %(e)s"),                              locals())


这个方法其实就是隔_ticks_to_skip次运行保存在_periodic_tasks中的方法

其中属性  _periodic_tasks 来自  __metaclass__ = ManagerMeta

 

这个时候来看下 ManagerMeta 类(nova/manager.py)

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

  其实很简单,  if getattr(value, '_periodic_task', False):

  如果某个  cls.__dict__.values() 的属性存_periodic_task

  就加入到 cls._periodic_tasks 中 ,

 其中这个属性的设置 是通过装饰函数进行完成的 def periodic_task(nova/manager.py)

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])


 



原创粉丝点击