nova volume-attach代码流程分析

    xiaoxiao2021-03-27  30

    最近遇到一个bug,是用户在nova端attach一个volume给instance后,再发起detach操作,导致该volume detach失败且一直处于detaching状态,借此走读nova volume-detach的代码流程,在此分享下心得笔记。

    nova client端发起nova volume-attach动作,首先在api侧获取到请求信息,并进行简单解析:

    nova/api/openstack/compute/volume.py

    def _attach_volume(self, context, instance, volume_id, device, disk_bus, device_type): """Attach an existing volume to an existing instance.This method is separated to make it possible for cells version to override it. """

    根据请求来的body,获取volume及instance信息,直接调用compute api:

    device = self.compute_api.attach_volume(context, instance,volume_id, device)

    compute api收到请求进行处理, nova/compute/api.py:

    def attach_volume(self, context, instance, volume_id, device=Nonedisk_bus=None, device_type=None):

    这里比较简单,直接返回另一方法:

    return self._attach_volume(context, instance, volume_id, device, disk_bus, device_type)

    再看_attach_volume方法:

    def _attach_volume(self, context, instance, volume_id, device, disk_bus, device_type):

    这部分主要创建bdm,rpc调用nova compute:

    self.compute_rpcapi.attach_volume(context, instance, volume_bdm)

    openstack下的rpc调用,最终都是由manager.py处理,所以直接看compute下的manager.py nova/compute/manager.py:

    def attach_volume(self, context, instance, bdm): return self._attach_volume(context, instance, driver_bdm) def _attach_volume(self, context, instance, bdm): bdm.attach(context, instance, self.volume_api, self.driver, do_driver_attach=True)

    直接看第二个方法,发起调用bdm.attach,在nova/virt/block_device.py中:

    def attach(self, context, instance, volume_api, virt_driver, do_driver_attach=False, **kwargs):

    在这里有以下几部分操作: 1)获取connect_info 2)调用driver将volume挂载给instance的动作(修改xml配置等);

    virt_driver.attach_volume

    3)检查connect_info信息 4)如果volume状态是detached:

    if volume['attach_status'] == "detached":

    则调用cinder中attach方法,会将volume设置为in-use状态:

    volume_api.attach(context, volume_id, instance.uuid, self['mount_device'], mode=mode)

    在调用cinder之前,有一个connect_info保存动作:

    self.save()

    正常在attach方法有装饰器修饰:

    @update_db

    在attach执行后更新数据库,保存connect_info信息。 在调用cinder之前加上保存的动作是为了防止在attach之后又 发生detach动作,此时cinder返回volume为in-use状态,但是connect_info尚未存储到数据库,在detach流程 中可能会因为获取不到有效的connect_info信息而导致detach失败:

    TRACE oslo.messaging.rpc.dispatcher TypeError: <type 'NoneType'> can't be decoded

    使得volume一直处于detaching状态。


    小笨驴在吃草的时候创建了微信公众号,为方便更多觅食的“小笨驴”,为大家准备了大量的免费基础教学资料以及技术解决方案,还会定时发布一些好的技术文章,当然也会扯扯蛋、谈谈人生、呵呵,希望我们这群乐于分享技术的“小笨驴”团队越来越大!(技术干货分享群qq:128015753)

    转载请注明原文地址: https://ju.6miu.com/read-664502.html

    最新回复(0)