nova event机制分析

本文主要分析Nova的一个event机制,目前主要用于VIF plugin是的notification,可以实现Nova 和 Neutron直接VIF 状态信息的交互。

1. nova部分

vif_plugging_timeout配置参数的解释,用于定义创建VM时等待VIF准备好的时间

    cfg.BoolOpt('vif_plugging_is_fatal',
                default=True,
                help="Fail instance boot if vif plugging fails"),
    cfg.IntOpt('vif_plugging_timeout',
               default=300,
               help='Number of seconds to wait for neutron vif plugging '
                    'events to arrive before continuing or failing (see '
                    'vif_plugging_is_fatal). If this is set to zero and '
                    'vif_plugging_is_fatal is False, events should not '
                    'be expected to arrive at all.'),

_create_domain_and_network():

        timeout = CONF.vif_plugging_timeout
        if (self._conn_supports_start_paused and #判断是不是支持开机是暂停,主要是virt_type是否是kvm or qemu, 此处进行判断的原因是vm需要暂停一下等待linux bridge创建好并把vm连接到br-int上去
            utils.is_neutron() and not
            vifs_already_plugged and power_on and timeout):
            events = self._get_neutron_events(network_info)#返回所有vif的active属性为False的项
        else:
            events = []

        launch_flags = events and libvirt.VIR_DOMAIN_START_PAUSED or 0
        domain = None
        try:
            with self.virtapi.wait_for_instance_event(#上下文管理
                    instance, events, deadline=timeout,
                    error_callback=self._neutron_failed_callback):
                self.plug_vifs(instance, network_info)
                self.firewall_driver.setup_basic_filtering(instance,
                                                           network_info)
                self.firewall_driver.prepare_instance_filter(instance,
                                                             network_info)
                with self._lxc_disk_handler(instance, image_meta,
                                            block_device_info, disk_info):
                    domain = self._create_domain(
                        xml, instance=instance,
                        launch_flags=launch_flags,
                        power_on=power_on)

                self.firewall_driver.apply_instance_filter(instance,
                                                           network_info)

contextlib.contextmanager和yield实现pyhton的上下文管理器,另一种实现方法可以参考with的实现原理,在我的另外一篇文章中有介绍。

任何在yield之前的内容都可以看做在代码块执行前的操作,而任何yield之后的操作都可以放在exit函数中。wait_for_instance_event ()就是

先准备计划等待一些event, 然后运行_create_domain_and_network()中提到的代码块,同时开始等待,等待超时后调用error_callback,

详细介绍在代码的注释中说的很清楚,在次不做翻译了。主要实现的功能就是等待vif准备好,等待时间超过300ms,就算本次vm创建失败。

@contextlib.contextmanager
    def wait_for_instance_event(self, instance, event_names, deadline=300,
                                error_callback=None):
        """Plan to wait for some events, run some code, then wait.

        This context manager will first create plans to wait for the
        provided event_names, yield, and then wait for all the scheduled
        events to complete.

        Note that this uses an eventlet.timeout.Timeout to bound the
        operation, so callers should be prepared to catch that
        failure and handle that situation appropriately.

        If the event is not received by the specified timeout deadline,
        eventlet.timeout.Timeout is raised.

        If the event is received but did not have a 'completed'
        status, a NovaException is raised.  If an error_callback is
        provided, instead of raising an exception as detailed above
        for the failure case, the callback will be called with the
        event_name and instance, and can return True to continue
        waiting for the rest of the events, False to stop processing,
        or raise an exception which will bubble up to the waiter.

        :param instance: The instance for which an event is expected
        :param event_names: A list of event names. Each element can be a
                            string event name or tuple of strings to
                            indicate (name, tag).
        :param deadline: Maximum number of seconds we should wait for all
                         of the specified events to arrive.
        :param error_callback: A function to be called if an event arrives

        """

        if error_callback is None:
            error_callback = self._default_error_callback
        events = {}
        for event_name in event_names:
            if isinstance(event_name, tuple):#event_name是一个元组,如('network-vif-plugged', vif['id'])
                name, tag = event_name
                event_name = objects.InstanceExternalEvent.make_key(  #nova/objects/external_event.py, 在该文件中定义event的几种类型
                    name, tag)
            events[event_name] = (
                self._compute.instance_events.prepare_for_instance_event(
                    instance, event_name))
        yield
        with eventlet.timeout.Timeout(deadline):
            for event_name, event in events.items():
                actual_event = event.wait()
                if actual_event.status == 'completed':
                    continue
                decision = error_callback(event_name, instance)
                if decision is False:
                    break

该函数返回一个event给上面的函数中的events中的event,再执行event.wait()

 def prepare_for_instance_event(self, instance, event_name):
        """Prepare to receive an event for an instance.

        This will register an event for the given instance that we will
        wait on later. This should be called before initiating whatever
        action will trigger the event. The resulting eventlet.event.Event
        object should be wait()'d on to ensure completion.

        :param instance: the instance for which the event will be generated
        :param event_name: the name of the event we're expecting
        :returns: an event object that should be wait()'d on
        """
        @utils.synchronized(self._lock_name(instance))
        def _create_or_get_event():
            if instance.uuid not in self._events:
                self._events.setdefault(instance.uuid, {})
            return self._events[instance.uuid].setdefault(
                event_name, eventlet.event.Event())
        LOG.debug('Preparing to wait for external event %(event)s',
                  {'event': event_name}, instance=instance)
        return _create_or_get_event()

2. neturon部分

OK,分析到这里不免产生疑惑,上文中判断event完成的语句是:

if actua_event.status == ‘completed‘

那么问题来了,是谁在改变event的status呢?plug vif 是由neutron完成的,故猜想应该是由neutron在修改这个status, 看nova api v2 和 v3

都有server_external_events.py 这个文件,显然,Nova为修改event的状态提供了Rest API, 在Neutron的代码下面,可以在notifiers目录下

的nova.py文件中找到调用rest API 的代码,故猜想成功了。

在neutron/db/db_base_plugin_v2.py文件中有:

        if cfg.CONF.notify_nova_on_port_status_changes:
            from neutron.notifiers import nova
            # NOTE(arosen) These event listeners are here to hook into when
            # port status changes and notify nova about their change.
            self.nova_notifier = nova.Notifier()
            event.listen(models_v2.Port, 'after_insert',
                         self.nova_notifier.send_port_status)
            event.listen(models_v2.Port, 'after_update',
                         self.nova_notifier.send_port_status)
            event.listen(models_v2.Port.status, 'set',
                         self.nova_notifier.record_port_status_changed)

当port的状态改变时,通知nova.

时间: 2024-10-12 08:16:57

nova event机制分析的相关文章

QT开发(六十三)——QT事件机制分析

QT开发(六十三)--QT事件机制分析 一.事件机制 事件是由系统或者QT平台本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事件则是由系统自动发出,如计时器事件. 事件的出现,使得程序代码不会按照原始的线性顺序执行.线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程中,用户点击"打开文件"将开始执行打开文件的操作,用户点击"保存文件"将开始执

Nginx处理stale事件机制分析

Nginx为提高效率采用描述符缓冲池(连接池)来处理tcp连接,一个连接对应一个读事件和一个写事件,nginx在启动的时候会创建好所用连接和事件,当事件来的时候不用再创建,然而连接池的使用却存在stale事件的问题,以下将详细分析Nginx是如何处理stale事件的,该问题涉及到epoll.Nginx连接与事件的相关知识. 1      Epoll的实现原理 epoll相关的系统调用有:epoll_create, epoll_ctl和epoll_wait.Linux-2.6.19又引入了可以屏蔽

Chromium的IPC消息发送、接收和分发机制分析

由于Chromium采用多进程架构,因此会涉及到进程间通信问题.通过前面一文的学习,我们知道Browser进程在启动Render进程的过程中会建立一个以UNIX Socket为基础的IPC通道.有了IPC通道之后,接下来Browser进程与Render进程就以消息的形式进行通信.我们将这种消息称为IPC消息,以区别于线程消息循环中的消息.本文就分析Chromium的IPC消息发送.接收和分发机制. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! Chrom

Android7.0 Vold 进程工作机制分析之整体流程

Android7.0 Vold 进程工作机制分析之整体流程 一.Vold简介 Vold是Volume Daemon的缩写,负责管理和控制Android平台外部存储设备,包括SD插拨.挂载.卸载.格式化等.它是通过init进程解析init.rc脚本所启动的进程.它处于Native层. 二.基础架构 这里引用Gityuan博客的一张图. SystermServer进程和Vold进程是通过Socket进行通信的,Vold进程和Kernel是通过Netlink 进行通信的,Netlink 是一种特殊的S

事件拦截机制分析(Android群英传)

内容是博主照着书敲出来的,博主码字挺辛苦的,转载请注明出处,后序内容陆续会码出. 当Android系统捕获到用户的各种输入事件后,如何准确地传递给真正需要这个事件的控件呢?Android给我们提供了一整套完善的事件传递.处理机制,来帮助开发者完成准确的事件分配与处理. 要了解触摸事件的拦截机制,首先要了解什么是触摸事件?顾名思义,触摸事件就是捕获触摸屏幕后产生的事件.当点击一个按钮时,通常就会产生两个或者三个事件--按钮按下,这是事件一:如果不小心滑动一点,这就是事件二:当手抬起,这是事件三.A

MaxCompute(原ODPS) 事件(Event)机制

摘要: 免费开通大数据服务:https://www.aliyun.com/product/odps 转自habai 什么是 MaxCompute事件机制 MaxCompute event 用于监控表和实例等MaxCompute资源(目前只用于监控表). 免费开通大数据服务:https://www.aliyun.com/product/odps 什么是MaxCompute 大数据计算服务(MaxCompute,原名ODPS)是一种快速.完全托管的TB/PB级数据仓库解决方案.MaxCompute向

Linux通信之poll机制分析

poll机制分析 韦东山 2009.12.10 所有的系统调用,基于都可以在它的名字前加上"sys_"前缀,这就是它在内核中对应的函数.比如系统调用open.read.write.poll,与之对应的内核函数为:sys_open.sys_read.sys_write.sys_poll. 一.内核框架: 对于系统调用poll或select,它们对应的内核函数都是sys_poll.分析sys_poll,即可理解poll机制. sys_poll函数位于fs/select.c文件中,代码如下:

Linux x86_64 APIC中断路由机制分析

不同CPU体系间的中断控制器工作原理有较大差异,本文是<Linux mips64r2 PCI中断路由机制分析>的姊妹篇,主要分析Broadwell-DE X86_64 APIC中断路由原理.中断配置和处理过程,并尝试回答如下问题: 为什么x86中断路由使用IO-APIC/LAPIC框架,其有什么价值? pin/irq/vector的区别.作用,取值范围和分配机制? x86_64 APIC关键概念 Pin 此处的pin特指APIC的中断输入引脚,与内外部设备的中断输入信号相连.从上图中可以看出,

[转]易语言消息机制分析(消息拦截原理)

标 题: [原创]易语言消息机制分析(消息拦截原理)作 者: 红绡枫叶时 间: 2014-12-17,12:41:44链 接: http://bbs.pediy.com/showthread.php?t=195626 我自己做了个易语言的sig签名,方便分析的时候用.易语言例子是静态编译的.版本 5.11易语言其实是基于mfc的,它依然需要mfc的消息派发机制,只不过,自己当了系统与用户间的代理人.所有的消息都要经它转发而已.我在MFC的消息派发函数_AfxDispatchCmdMsg下断点,总