openstack cinder 创建volume源码分析

本文深入分析了OpenStack Cinder创建volume的源码流程,从API入口、RPC调用到驱动执行。首先,介绍了volume API在cinder/api/v3/volumes.py中的定义,然后详细讲解了create_volume函数在cinder/volume/flows/api/create_volume.py中的实现,涉及scheduler_rpcapi、volume_rpcapi和db_api。接着,讨论了volume根据不同的创建来源如何调用驱动,以ceph为例,展示了如何使用rbd.py驱动创建。最后,补充了在host未知情况下,如何通过scheduler完成volume创建的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

cinder volume

备注:
为方便源码阅读, 列出的部分的源码将被省略, 如需要阅读完整代码, 建议在官网进行下载

cinder实现相对比较简单
基本结构:

  1. api --> volume API --> db
  2. api --> volume API --> rpc --> volume manager --> drivers

API 入口

目前cinder 已经更新到v3版本, 因此源码阅读的时候, api入口从v3开始
volume卷 api定义在 cinder/api/v3/volumes.py

class VolumeController(volumes_v2.VolumeController):
    """The Volumes API controller for the OpenStack API V3."""

v3继承v2的功能

目前v3已经更新了v2版本的create
源码如下

    @wsgi.response(202)
    def create(self, req, body):
        """Creates a new volume.

        :param req: the request
        :param body: the request body
        :returns: dict -- the new volume dictionary
        :raises: HTTPNotFound, HTTPBadRequest
        """
        self.assert_valid_body(body, 'volume')

        LOG.debug('Create volume request body: %s', body)
        context = req.environ['cinder.context']

# 获取并校验参数
        req_version = req.api_version_request
        # Remove group_id from body if max version is less than 3.13.
				....
				
        volume = body['volume']
        kwargs = {}
        self.validate_name_and_description(volume)

        # NOTE(thingee): v2 API allows name instead of display_name
        if 'name' in volume:
            volume['display_name'] = volume.pop('name')

        # NOTE(thingee): v2 API allows description instead of
        #                display_description
        if 'description' in volume:
            volume['display_description'] = volume.pop('description')

# image镜像进行创建
        if 'image_id' in volume:
            volume['imageRef'] = volume.pop('image_id')

# volume 类型
        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            # Not found exception will be handled at the wsgi level
            if not uuidutils.is_uuid_like(req_volume_type):
                kwargs['volume_type'] = (
                    volume_types.get_volume_type_by_name(
                        context, req_volume_type))
            else:
                kwargs['volume_type'] = volume_types.get_volume_type(
                    context, req_volume_type)

        kwargs['metadata'] = volume.get('metadata', None)


# 从快照创建
        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            # Not found exception will be handled at the wsgi level
            kwargs['snapshot'] = self.volume_api.get_snapshot(context,
                                                              snapshot_id)
        else:
            kwargs['snapshot'] = None

        source_volid = volume.get('source_volid')
        if source_volid is not None:
            # Not found exception will be handled at the wsgi level
            kwargs['source_volume'] = (
                self.volume_api.get_volume(context,
                                           source_volid))
        else:
            kwargs['source_volume'] = None

        source_replica = volume.get('source_replica')
        if source_replica is not None:
            # Not found exception will be handled at the wsgi level
            src_vol = self.volume_api.get_volume(context,
                                                 source_replica)
            if src_vol['replication_status'] == 'disabled':
                explanation = _('source volume id:%s is not'
                                ' replicated') % source_replica
                raise exc.HTTPBadRequest(explanation=explanation)
            kwargs['source_replica'] = src_vol
        else:
            kwargs['source_replica'] = None

        consistencygroup_id = volume.get('consistencygroup_id')
        if consistencygroup_id is not None:
            # Not found exception will be handled at the wsgi level
            kwargs['consistencygroup'] = (
                self.consistencygroup_api.get(context,
                                              consistencygroup_id))
        else:
            kwargs['consistencygroup'] = None

        # Get group_id if volume is in a group.
        group_id = volume.get('group_id')
        if group_id is not None:
            try:
                kwargs['group'] = self.group_api.get(context, group_id)
            except exception.GroupNotFound as error:
                raise exc.HTTPNotFound(explanation=error.msg)

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']
        elif size is None and kwargs['source_volume'] is not None:
            size = kwargs['source_volume']['size']
        elif size is None and kwargs['source_replica'] is not None:
            size = kwargs['source_replica']['size']

        LOG.info(_LI("Create volume of %s GB"), size)

        if self.ext_mgr.is_loaded('os-image-create'):
            image_ref = volume.get('imageRef')
            if image_ref is not None:
                image_uuid = self._image_uuid_from_ref(image_ref, context)
                kwargs['image_id'] = image_uuid


        kwargs['availability_zone'] = volume.get('availability_zone', None)
        
# 指定调度参数
        kwargs['scheduler_hints'] = volume.get('scheduler_hints', None)
        multiattach = volume.get('multiattach', False)
        kwargs['multiattach'] = multiattach

# API 创建volume卷
        new_volume = self.volume_api.create(context,
                                            size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        retval = self._view_builder.deta
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值