Source code analysis openstack master cinder create volume

Cinder create volume 流程分析

整个流程可以通过 –debug 模式来梳理:

[stack@localhost devstack]$ cinder --debug create 1 --volume-type lvmdriver-1

流程如下:
1. 访问 keystone 组件获取当前用户的 token(包含该用户可访问资源的 endpoints)。
2. 使用 token 请求 cinder(发送 RESTFul 请求)创建卷,并返回 202。
3. Cinder 处理请求,创建卷,概括如下:

 - cinder-api 接受 http 请求,处理入参,创建 flow。核心 task 是发送 RPC 请求到 cinder-scheduler 做后续处理。
 - cinder-scheduler 从 AMQP 消息队列中抓取请求,根据请求条件选择合适的 host,发送 RPC 请求到 cinder-volume(主机选择:先过滤出所有满足条件的主机,再对这些主机进行称重,选择权重最高的主机)。
 - cinder-volume 从 AMQP 消息队列中抓取请求,调用 volume driver 最终创建卷。

Cinder create volume 源码分析(master 分支)

  1. cinder.api.openstack.wsgi 接收 RESTFul 请求,分析,转发请求到 cinder.api.v2.volumes.VolumeController.create。

  2. cinder.api.v2.volumes.VolumeController.create 处理入参,调用 cinder.volume.api.create。
    2.1 入参格式验证(必须是字典)
    2.2 name 和 description 长度校验(不能超过 255)
    2.3 volume type 存在性判断(入参可以是 name 或者是 uuid)
    2.4 snapshot 存在性判断(入参必须是 uuid)
    2.5 clone 源卷存在性判断
    2.6 replication 源卷存在性判断 + replication_status 判断(是否启用 replication)
    2.7 consistencygroup 存在性判断
    2.8 size 取值(优先级:入参 > snapshot volume size > clone volume size > replica volume size)
    2.9 image uuid 存在性判断
    2.10 直接调用 cinder.volume.api.create

  3. cinder.volume.api.create 继续处理入参,创建 flow,运行,返回。
    3.1 size 判断(大于 0 的正整数)
    3.2 consistencygroup 指定后判断 volume type(必须指定并且在 consistencygroup 包含的 volume type 中)
    3.3 group 指定后判断 volume type(必须指定并且在 group 包含的 volume type 中)
    3.4 clone 情况下判断 volume type(相同或者可以 retype)
    3.5 snapshot 情况下判断 volume type(相同或者可以 retype)
    3.6 获取 availability zones
    3.7 metadata 格式判断(如果指定,键和值都不能为空,并且长度不超过 255)
    3.8 调用 cinder.volume.flows.api.create_volume.get_flow() 创建flow(创建 volume 的核心处理过程)
    3.9 运行 flow,捕获 volume 状态,创建成功

  4. cinder.volume.flows.api.create_volume.get_flow() 新建 flow,包括下面的 task:
    4.1 ExtractVolumeRequestTask(对入参的进一步判断)

    检查 snapshot 为 available
    检查 clone 源卷为 available 或 in-use
    检查 replica 源卷为 available 或 in-use,并且 replica 状态为 active 或 active-stopped
    检查 size 不能比 snapshot 或 clone 源卷 size 小,同时是正整数
    检查 image 状态为 active,判断 size 必须比 image size 大,判断 size 必须比 image min_disk size 大
    检查 availability_zone
    根据 volume type 获取 qos 相关配置数据

    4.2 QuotaReserveTask(检查配额是否满足,并储存配额信息用来回滚)
    4.3 EntryCreateTask(在 cinder 数据库创建 volume)
    4.4 QuotaCommitTask(消费配额)
    4.5 VolumeCastTask(核心 task,RPC 到 cinder-scheduler)

    如果是 clone 卷(或是 snapshot 卷并配置 snapshot_same_host = True),直接转发请求到 volume manager 所在主机。
    其他任何情况,转发到 scheduler,由 scheduler 决定在哪个 host 上最终创建卷。
  5. cinder.scheduler.rpcapi.create_volume cast 请求。cinder.scheduler.manager.create_volume 接受请求,创建 flow,运行。
    cinder.scheduler.flows.api.create_volume.get_flow()

  6. cinder.scheduler.flows.api.create_volume.get_flow() 新建 flow,包括下面的 task:
    6.1 ExtractSchedulerSpecTask(构造 scheduler 筛选参数)
    6.2 ScheduleCreateVolumeTask(核心 task,调用配置的 scheduler_drivers 的 chedule_create_volume 筛选主机,默认的是 cinder.scheduler.filter_scheduler.FilterScheduler

  7. cinder.scheduler.filter_scheduler.FilterScheduler.schedule_create_volume
    下面过一下这个里面的核心流程:
    backend = self._schedule(获取创建卷的目标主机)

weighed_backends = self._get_weighted_candidates,获取称重后主机列表
    主要的三个操作流程:
        获取所有的主机 backend
            cinder.scheduler.host_manager.get_all_backend_states

        过滤出满足条件的主机 filtered backends
            默认的 filter 是:scheduler_default_filters: AvailabilityZoneFilter, CapacityFilter, CapabilitiesFilter。
            最终调用三个 filter 的 backend_passes 方法。
            AvailabilityZoneFilter:
                availability_zone 信息是否吻合。
            CapacityFilter:
                判断当前主机容量是否满足创建卷的需求。
                如果主机 free_space 是 infinite or unknown,返回 True,表示该主机可用。
                如果主机 total_space 是 infinite or unknown,并且保留容量为 0,返回 True,表示该主机可用。保留容量不为 0,返回 False,表示该主机不可用。
                如果主机支持自动精简(thin_provisioning_support = True),判断是否已经超过超分比(max_over_subscription_ratio),超过返回 False,否则返回 True。(这个算法是有 bug 的!!!)
                如果主机不支持自动精简,直接判断空余容量和创建卷大小,如果满足返回 True,否则返回 False。
            CapabilitiesFilter:
                判断 volume type 中的 extra_specs 是否和主机的信息吻合

        对满足条件的主机进行称重 weighed backends
            默认的 weighter 是:scheduler_default_weighers: CapacityWeigher。
            最终调用 weighter 的 _weigh_object 方法(返回当前主机可用容量)。
            _weigh_object:
                如果主机 free_space or total_space 是 infinite or unknown,返回最低权重:-1
                如果主机支持自动精简(thin_provisioning_support = True),返回的权重是:总容量 * 超分比(max_over_subscription_ratio) - 已经分配容量 - 保留容量
                如果不支持自动精简,返回的权重是:空余容量 - 保留容量
            最后返回给 cinder.scheduler.filter_scheduler.FilterScheduler 的主机信息会根据上面的容量权重由高到低进行排序

self._choose_top_backend,选择称重后的第一个主机(也就是权重最高的主机)

self.volume_rpcapi.create_volume(发送 RPC 请求到 cinder-volume)

  1. cinder.volume.rpcapi.create_volume cast 请求。cidner.volume.manager.VolumeManager.create_volume 接受请求,创建 flow,运行。
    cinder.volume.flows.manager.create_volume.get_flow()

  2. cinder.volume.flows.manager.create_volume.get_flow() 新建 flow,包括下面的 task:
    9.1 ExtractVolumeRefTask(重新从 db 获取 volume)
    9.2 OnFailureRescheduleTask(创建失败情况下 reschedule)
    9.3 ExtractVolumeSpecTask(构建创建卷请求的参数)
    9.4 NotifyVolumeActionTask(创建卷开始通知)
    9.5 CreateVolumeFromSpecTask(核心 task)

    根据 9.3 创建的请求结构判断具体调用 volume driver 的哪个接口:
    raw:创建裸设备
        self.driver.create_volume(volume)
    
    snap:从 snapshot 创建卷
        self.driver.create_volume_from_snapshot(volume, snapshot)
    
    source_vol:创建 clone 卷
        self.driver.create_cloned_volume(volume, srcvol_ref)
    
    image:从 image 创建一个可启动虚机的 boot volume
        检查 cinder-volume 节点缓存空间是否充足(image_conversion_dir)
        检查卷大小是否大于 image 大小
    
        下面是做成 boot volume 的三种方式:
            self.driver.clone_image(驱动默认不实现这个方法,volume driver 可以根据入参判断能否直接驱动层实现快速做成 boot volume)
    
            _clone_image_volume(self.driver.create_cloned_volume)(这种方式对应了一种特殊的业务场景:image 本身存储在一个普通的块存储设备中,直接通过存储端的克隆实现快速做成,参考:https://specs.openstack.org/openstack/cinder-specs/specs/liberty/clone-image-in-glance-cinder-backend.html)
    
            _create_from_image_cache_or_download(这个是目前默认的实现方式)
                _create_from_image_cache
                    根据 image 查找当前是否存在 image cache(cinder list --all 可以查看该 image volume,它属于 service project)
                    如果存在直接通过 image volume 进行克隆(self.driver.create_cloned_volume)
    
                _create_from_image_download
                    这是一个最通常的业务模式:新建卷,挂载,写数据,取消挂载
                        self.driver.create_volume
                        _copy_image_to_volume
                            self.driver.copy_image_to_volume
                                _copy_image_data_to_volume
                                    _attach_volume
                                        initialize_connection
                                    image_utils.fetch_to_raw
                                    _detach_volume
                                        terminate_connection
    
        self.driver.extend_volume
            上面的操作完成后,把卷大小修改为请求的大小
    
        通常的经过了上面的操作后会新建一个 image_cache,通过调用 _create_image_cache_volume_entry 来实现,本质实现就是通过 做成的 boot volume 做成一个 image volume(新建一个 create_volume 的 flow,最终通过 volume driver 的 clone 来实现)。
    
    source_replica:暂不分析。

    9.6 CreateVolumeOnFinishTask(创建卷成功通知并更新 cinder 数据库)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值