nova volume-attach代码流程分析

来源:互联网 发布:seo效果检测步骤包括 编辑:程序博客网 时间:2024/06/01 15:55

最近遇到一个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)


这里写图片描述

1 0