cinder创建卷源码分析

本文以kilo版本的cinder为例

代码整体流程如下:

如整体架构图所示,创建卷涉及的大体步骤主要有以下几步:
a. Client发送请求,通过RESTFUL接口访问cinder-api。
b. Api解析响应请求,api解析由Client发送来的请求,并通过rpc进一步调用cinder-scheduler。
c. Scheduler对资源进行调度,scheduler选择合适的节点进行。
d. Volume调用Driver创建卷,volume通过指定Driver进行卷的创建。

cinder api

cinder client
POST  /v2/{tenant_id}/volumes  
    ↓
cinder.api.v2.volumes.VolumeController.create:
    # 对volume_type、metadata、snapshot等信息进行检查
    new_volume = self.volume_api.create(context,
                                        size,
                                        volume.get('display_name'),
                                        volume.get('display_description'),
                                        **kwargs)
    ↓
cinder.volume.api.API.create:
    # 对source_volume、volume_type等参数进行进一步检查
    flow_engine = create_volume.get_flow()
    ↓
cinder.volume.flows.api.create_volume.get_flow:
    api_flow.add(ExtractVolumeRequestTask())
    api_flow.add(QuotaReserveTask(),
                 EntryCreateTask(db_api),
                 QuotaCommitTask())
    api_flow.add(VolumeCastTask())
    ↓
cinder.volume.api.API.create:
    flow_engine.run()
    ↓
cinder.volume.flows.api.create_volume.ExtractVolumeRequestTask.execute:
    # 获取 request 信息并返回
cinder.volume.flows.api.create_volume.QuotaReserveTask.execute:
    # 预留配额
cinder.volume.flows.api.create_volume.EntryCreateTask.execute:
    # 在数据库中创建 volume 条目,此时卷的状态为”creating”
cinder.volume.flows.api.create_volume.QuotaCommitTask.execute:
    # 确认配额
cinder.volume.flows.api.create_volume.VolumeCastTask.execute:
    self._cast_create_volume(context, request_spec, filter_properties)
    ↓
cinder.volume.flows.api.create_volume.VolumeCastTask._cast_create_volume:
    if not host: # 如果未传入host,则会经过调度进行创建卷
        self.scheduler_rpcapi.create_volume()
    else: # 如果传入host,直接交由Volume Manager去创建卷
        self.volume_rpcapi.create_volume()
    ↓
cinder.scheduler.rpcapi.SchedulerAPI.create_volume: # 以未传入host为例
    return cctxt.cast(ctxt, 'create_volume', ···)

cinder scheduler

cinder.scheduler.manager.SchedulerManager.create_volume:
    flow_engine = create_volume.get_flow(context,···)
    ↓
cinder.scheduler.flows.create_volume.get_flow:
    scheduler_flow.add(ExtractSchedulerSpecTask())
    scheduler_flow.add(ScheduleCreateVolumeTask())
    ↓
cinder.scheduler.manager.SchedulerManager.create_volume:
    flow_engine.run()
    ↓
cinder.scheduler.flows.create_volume.ExtractSchedulerSpecTask.execute:
    # 获取用于调度的信息
    ↓ 
cinder.scheduler.flows.create_volume.ScheduleCreateVolumeTask.execute:
    self.driver_api.schedule_create_volume()
    ↓
cinder.scheduler.filter_scheduler.FilterScheduler.schedule_create_volume:
    weighed_host = self._schedule()
    # 更新数据库
    updated_volume = driver.volume_update_db(context, volume_id, host)
    self.volume_rpcapi.create_volume()
    ↓
cinder.volume.rpcapi.VolumeAPI.create_volume:
    cctxt.cast(ctxt, 'create_volume',···)

cinder volume

cinder.volume.manager.VolumeManage.create_volume:
    flow_engine = create_volume.get_flow()
    ↓
cinder.volume.flows.manager.create_volume.get_flow:
    volume_flow.add(ExtractVolumeRefTask(db, host))
    if allow_reschedule and request_spec: # 如果允许重新调度
        volume_flow.add(OnFailureRescheduleTask())
    volume_flow.add(ExtractVolumeSpecTask(db),
                    NotifyVolumeActionTask(db, "create.start"),
                    CreateVolumeFromSpecTask(db, driver),
                    CreateVolumeOnFinishTask(db, "create.end"))
    ↓                 
cinder.volume.manager.VolumeManage.create_volume:
    flow_engine.run()
    ↓
cinder.volume.flows.manager.create_volume.ExtractVolumeRefTask.execute:
    #从数据库中获得volume信息
    volume_ref = self.db.volume_get(context, volume_id)
    return volume_ref
    ↓
cinder.volume.flows.manager.create_volume.OnFailureRescheduleTask.execute:
    # 当进行task恢复回滚操作的时候,触发一个发送进行重新调度的请求
    ↓ 
cinder.volume.flows.manager.create_volume.ExtractVolumeSpecTask.execute:
    # 返回要创建volume的通用结构规范
    return specs
    #
    ↓
cinder.volume.flows.manager.create_volume.NotifyVolumeActionTask.execute:
    # 执行关于给定卷的相关通知操作,获取指定卷的使用率信息,并进行通知操作
    ↓
cinder.volume.flows.manager.create_volume.CreateVolumeFromSpecTask.execute:
    # 根据创建的不同类别,去创建卷
    create_type = volume_spec.pop('type', None)
    if create_type == 'raw':
        model_update = self._create_raw_volume(context,···)
    elif create_type == 'snap':
        model_update = self._create_from_snapshot(context,···)
    elif create_type == 'source_vol':
        model_update = self._create_from_source_volume(···)
    elif create_type == 'source_replica':
        model_update = self._create_from_source_replica(···)
    elif create_type == 'image':
        model_update = self._create_from_image(context,···)
    ↓
cinder.volume.flows.manager.create_volume.CreateVolumeFromSpecTask._create_raw_volume:
    # 以原始创建方式为例
    return self.driver.create_volume(volume_ref)
    ↓
cinder.volume.flows.manager.create_volume.CreateVolumeOnFinishTask.execute: 
    # 当成功的建立卷之后,完成卷建立之后的通知操作,启动更新数据库,将卷更新为available状态。               

参考

yikun's blog

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • 第一章 OpenStack基础 OpenStack管理的资源及提供的服务OpenStack做为一个操作系统,...
    sgt_tiger阅读 12,711评论 4 72
  • 以下是本人通过阅读Grizzly版OpenStack源码,整理的简要的Nova模块源码结构,希望和大家相互交流。 ...
    Chenzongshu阅读 2,594评论 0 50
  • cinder RPC 分析 [TOC] 我们都知道在Cinder内部,各组件之间通讯是通过RPC api,比如c...
    笨手笨脚越阅读 1,686评论 0 3
  • 1. 创建卷可以通过命令发送请求,例如cinder create 1 2. 由cinder-api处理,代码在/c...
    chendihao阅读 1,776评论 0 1
  • rest_api os-initialize_connection 逻辑分析 收到nova请求,POST /vo...
    笨手笨脚越阅读 1,592评论 0 3