卷基于快照进行恢复

2023-05-16

基于P版本,对卷基于快照进行恢复的源码分析

1、特性描述

在pike版本中,openstack官网增加了一个新特性,Cinder volume revert to snapshot,该特性支持将卷恢复到最近的快照。还原过程将覆盖卷的当前状态和数据。如果在快照之后对卷进行了扩展,那么请求将被拒绝。该特性的目的是让用户能够更方便地恢复实例和卷,并减少停机时间。

2、api接口参数样例

POST /v3/{project_id}/volumes/{volume_id}/action

恢复一个卷到它自己最新的快照,这个接口仅仅支持恢复卸载的卷,并且卷的状态是有效的

Request Example
{
    "revert": {
        "snapshot_id": "5aa119a8-d25b-45a7-8d1b-88e127885635"
    }
}

3、源码跟踪

cinder-api服务侧的处理

api接口,对http请求的处理 

cinder/api/v3/volumes.py
    @wsgi.response(http_client.ACCEPTED)
    @wsgi.Controller.api_version('3.40')
    @wsgi.action('revert')
    def revert(self, req, id, body):
        """revert a volume to a snapshot"""

        context = req.environ['cinder.context']
        self.assert_valid_body(body, 'revert')
        snapshot_id = body['revert'].get('snapshot_id')-----------获取用户传入的快照uuid
        volume = self.volume_api.get_volume(context, id)-----------通过卷的id,获取卷对象
        try:
            l_snap = volume.get_latest_snapshot()------读取数据库获取卷最新的快照UUID
        except exception.VolumeSnapshotNotFound:
            msg = _("Volume %s doesn't have any snapshots.")
            raise exc.HTTPBadRequest(explanation=msg % volume.id)
        # Ensure volume and snapshot match.
        if snapshot_id is None or snapshot_id != l_snap.id:-------判断用户是否输入快照及输入的快照是否为最新的快照
            msg = _("Specified snapshot %(s_id)s is None or not "
                    "the latest one of volume %(v_id)s.")
            raise exc.HTTPBadRequest(explanation=msg % {'s_id': snapshot_id,
                                                        'v_id': volume.id})
        try:
            msg = 'Reverting volume %(v_id)s to snapshot %(s_id)s.'
            LOG.info(msg, {'v_id': volume.id,
                           's_id': l_snap.id})
            self.volume_api.revert_to_snapshot(context, volume, l_snap)------s1 调用恢复卷快照的接口
        except (exception.InvalidVolume, exception.InvalidSnapshot) as e:
            raise exc.HTTPConflict(explanation=six.text_type(e))
        except exception.VolumeSizeExceedsAvailableQuota as e:
            raise exc.HTTPForbidden(explanation=six.text_type(e))  

cinder volume模块对请求的处理

cinder/volume/api.py
    @wrap_check_policy
    def revert_to_snapshot(self, context, volume, snapshot):
        """revert a volume to a snapshot"""

        v_res = volume.update_single_status_where(-----------------更新卷的状态由 available 变为 reverting,
            'reverting', 'available')
        if not v_res:
            msg = _("Can't revert volume %s to its latest snapshot. "
                    "Volume's status must be 'available'.") % volume.id
            raise exception.InvalidVolume(reason=msg)
        s_res = snapshot.update_single_status_where(------------更新快照的状态由available 变为 restoring 
            fields.SnapshotStatus.RESTORING,
            fields.SnapshotStatus.AVAILABLE)
        if not s_res:
            msg = _("Can't revert volume %s to its latest snapshot. "
                    "Snapshot's status must be 'available'.") % snapshot.id
            raise exception.InvalidSnapshot(reason=msg)

        self.volume_rpcapi.revert_to_snapshot(context, volume, snapshot)--------s2调用cinder volume的rpc接口 

 调用rpc接口

cinder/volume/rpcapi.py
    @rpc.assert_min_rpc_version('3.15')
    def revert_to_snapshot(self, ctxt, volume, snapshot):
        version = self._compat_ver('3.15')
        cctxt = self._get_cctxt(volume.host, version)
        cctxt.cast(ctxt, 'revert_to_snapshot', volume=volume,snapshot=snapshot)  

 cinder-voume侧接受到rpc请求,对rpc信息进行处理

cinder/volume/manager.py
    def revert_to_snapshot(self, context, volume, snapshot):
        """Revert a volume to a snapshot.

        The process of reverting to snapshot consists of several steps:
        1.   create a snapshot for backup (in case of data loss) 为了防止数据丢失创建一个快照的备份
        2.1. use driver's specific logic to revert volume 调用驱动的revert_to_snapshot接口来恢复卷
        2.2. try the generic way to revert volume if driver's method is missing 如果驱动的revert_to_snapshot 方法没有,那么就使用一般的方式去恢复卷
        3.   delete the backup snapshot 删除快照的备份
        """
        backup_snapshot = None
        try:
            LOG.info("Start to perform revert to snapshot process.")
            # Create a snapshot which can be used to restore the volume
            # data by hand if revert process failed.
            backup_snapshot = self._create_backup_snapshot(context, volume)---------创建卷的快照的备份
            self._revert_to_snapshot(context, volume, snapshot)--------------s1 执行快照的恢复
		except 
			...........
        v_res = volume.update_single_status_where('available', 'reverting')-----------把卷的状态由reverting更新为available
        if not v_res:
            msg_args = {"id": volume.id,
                        "status": 'available'}
            msg = _("Revert finished, but failed to reset "----------底层恢复完了,但是状态的状态没有设置成功,需要手动设置
                    "volume %(id)s status to %(status)s, "
                    "please manually reset it.") % msg_args
            raise exception.BadResetResourceStatus(message=msg)

        s_res = snapshot.update_single_status_where(---------------把快照的状态由reverting更新为available
            fields.SnapshotStatus.AVAILABLE,
            fields.SnapshotStatus.RESTORING)
        if not s_res:
            msg_args = {"id": snapshot.id,
                        "status":
                            fields.SnapshotStatus.AVAILABLE}
            msg = _("Revert finished, but failed to reset "-----------底层恢复完成,但是快照的状态没有设置成功,需要手动设置
                    "snapshot %(id)s status to %(status)s, "
                    "please manually reset it.") % msg_args
            raise exception.BadResetResourceStatus(message=msg)
        if backup_snapshot:
            self.delete_snapshot(context,----------------------删除备份的快照
                                 backup_snapshot, handle_quota=False)
        msg = ('Volume %(v_id)s reverted to snapshot %(snap_id)s '
               'successfully.')
        msg_args = {'v_id': volume.id, 'snap_id': snapshot.id}
        LOG.info(msg, msg_args)
		
cinder/volume/manager.py	
    def _revert_to_snapshot(self, context, volume, snapshot):
        """Use driver or generic method to rollback volume."""

        self._notify_about_volume_usage(context, volume, "revert.start")
        self._notify_about_snapshot_usage(context, snapshot, "revert.start")
        try:
            self.driver.revert_to_snapshot(context, volume, snapshot)------调用相关驱动去恢复快照
        except (NotImplementedError, AttributeError):
            LOG.info("Driver's 'revert_to_snapshot' is not found. "
                     "Try to use copy-snapshot-to-volume method.")
            self._revert_to_snapshot_generic(context, volume, snapshot)----------没有实现revert_to_snapshot功能,那么走一般路径ceph调用的就是这个
        self._notify_about_volume_usage(context, volume, "revert.end")
        self._notify_about_snapshot_usage(context, snapshot, "revert.end")  

基于lvm的驱动

cinder/volume/drivers/lvm.py
    def revert_to_snapshot(self, context, volume, snapshot):
        """Revert a volume to a snapshot"""
        # NOTE(tommylikehu): We still can revert the volume because Cinder
        # will try the alternative approach if 'NotImplementedError'
        # is raised here.
        if self.configuration.lvm_type == 'thin':--------如果lvm配置成thin,那么不支持快照恢复
            msg = _("Revert volume to snapshot not implemented for thin LVM.")
            raise NotImplementedError(msg)
        else:
            self.vg.revert(self._escape_snapshot(snapshot.name))-----执行的是lvconvert --merge命令,合并快照到原始卷中,此时这个快照会被销毁
            self.vg.deactivate_lv(volume.name)------执行的是lvchange -a n命令,表示更改lv卷的状态为无效,lvchange表示更改lv的活动状态,y表示lv活动或有效,n表示lv不活动或无效
            self.vg.activate_lv(volume.name)--------执行的是lvchange -a y --yes,表示更改lv卷的状态为有效状态,--yes表示不提示确认互动,直接认为是,
            # Recreate the snapshot that was destroyed by the revert
            self.create_snapshot(snapshot)-----------创建快照  

由于ceph目前没有实现revert_to_snapshot方法,因此调用_revert_to_snapshot_generic接口

cinder/volume/manager.py
    def _revert_to_snapshot_generic(self, ctxt, volume, snapshot):
        """Generic way to revert volume to a snapshot.
        the framework will use the generic way to implement the revert
        to snapshot feature:
        1. create a temporary volume from snapshot-----从快照创建一个临时的卷
        2. mount two volumes to host--------------挂载两个卷到主机上
        3. copy data from temporary volume to original volume--------从临时卷拷贝数据到原始卷中
        4. detach and destroy temporary volume----------卸载并销毁临时卷
        """
        temp_vol = None

        try:
            v_options = {'display_name': '[revert] temporary volume created '
                                         'from snapshot %s' % snapshot.id}
            ctxt = context.get_internal_tenant_context() or ctxt
            temp_vol = self.driver._create_temp_volume_from_snapshot(--------通过快照创建临时卷
                ctxt, volume, snapshot, volume_options=v_options)
            self._copy_volume_data(ctxt, temp_vol, volume)-------从临时卷拷贝数据到原始卷,这个过程会分三个小步骤:挂载原始卷和临时卷;从临时卷拷贝数据到原始卷;
卸载临时卷和原始卷 self.driver.delete_volume(temp_vol)-----删除临时卷 temp_vol.destroy() except Exception: with excutils.save_and_reraise_exception(): LOG.exception( "Failed to use snapshot %(snapshot)s to create " "a temporary volume and copy data to volume " " %(volume)s.", {'snapshot': snapshot.id, 'volume': volume.id}) if temp_vol and temp_vol.status == 'available': self.driver.delete_volume(temp_vol) temp_vol.destroy()

  

转载于:https://www.cnblogs.com/potato-chip/p/11535166.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

卷基于快照进行恢复 的相关文章

  • Hive 系列(四)—— Hive 常用 DDL 操作

    一 Database 1 1 查看数据列表 code show databases code 1 2 使用数据库 code USE database name code 1 3 新建数据库 语法 xff1a code CREATE DATA
  • SQL调用webApi

    有些时候对一些接口的调用放在数据库比放在程序里更好控制 xff0c 我这边用到的场景就是 xff0c 更具状态变化去调用 xff0c 我处理的方法就是放在 触发器里面 xff0c 只要状态数据变化就触发 xff0c 这样 xff0c 我就不
  • 第二种方式读取并显示HDFS中的内容

    1 讀取HDFS内容的java客戶端代碼 xff1a 1 package Hdfs 2 3 import java io InputStream 4 import java net URI 5 6 import org apache had
  • 更新镜像

    更新镜像这一概念 xff0c 会有两个完全不一样的概念 xff0c 需要先说清楚 1 更新FPGA的配置 这种方案对应Xilinx的bit文件下载和Intel Altera 的sof文件下载 xff0c 更新的是FPGA的配置 xff0c
  • Hadoop 单表关联

    前面的实例都是在数据上进行一些简单的处理 xff0c 为进一步的操作打基础 单表关联这个实例要求从给出的数据中寻找到所关心的数据 xff0c 它是对原始数据所包含信息的挖掘 下面进入这个实例 1 实例描述 实例中给出child parent
  • MFC获取字符串长度的5中方法

    char s1 61 34 中文ABC 34 wchar t s2 61 L 34 中文ABC 34 1 sizeof 获取字符数组的字节数 xff08 包括结束符0 xff09 sizeof s1 61 8 ANSI sizeof s2
  • python学习笔记(12)常用模块

    一 模块 包 什么是模块 xff1f 模块实质上就是一个python文件 它是用来组织代码的 xff0c 意思就是说把python代码写到里面 xff0c 文件名就是模块的名称 xff0c test py test就是模块名称 什么是包 x
  • python学习笔记(13)常用模块列表总结

    os模块 os remove 删除文件 os unlink 删除文件 os rename 重命名文件 os listdir 列出指定目录下所有文件 os chdir 改变当前工作目录 os getcwd 获取当前文件路径 os mkdir
  • python获取当前时间的用法

    python获取当前时间的用法 1 先导入库 xff1a import datetime 2 获取当前日期和时间 xff1a now time 61 datetime datetime now 3 格式化成我们想要的日期 xff1a str
  • nmap使用教程

    nmap简介 nmap是一个免费开放的网络扫描和嗅探的工具包 也叫网络映射器 nmap强大之处在于简单 易用 看一下nmap的基本功能 探测一组主机是否在线扫描主机端口 嗅探所提供的网络服务 推断出主机所用的操作系统丰富的脚本功能 wind
  • awk命令中BEGIN和END的作用

    BEGIN中的内容表示在awk起作用 xff08 扫描 xff09 前执行 xff0c 通常被用来初始化一些常量或者环境变量 END表示END之后的操作内容在awk全部扫描完之后执行
  • 国外最漂亮的50个网站欣赏

    http news cnblogs com n 44079 转载于 https www cnblogs com starcrm archive 2008 12 23 1360212 html
  • 串口的Hex/AscII发送与显示

    都要大四了还搞不清这个概念也真是丢脸 首先 xff0c 底层的数据传输都是字节流 xff0c 所以不管选择什么方式 xff0c 都会被分解为一个一个的字节 1选择Hex发送就代表你要发送的内容是纯数字 xff0c 由程序完成String到I
  • vue 数组对象取值

    转载于 https www cnblogs com classmethond p 10799334 html
  • vs调试工具栏不可用(变灰)解决办法

    菜单中页不能进行调试 使用vs的命令行工具 在命令行中运行 xff1a devenv ResetSkipPkgs 重新打开vs xff08 注 xff1a 第一次没有关闭vs xff0c 运行这条命令后 xff0c 会新打开vs没有变化 x
  • Nginx 反向代理Tomcat服务器获取真实IP问题

    1 nginx conf 配置 修改 Server location配置 增加 proxy set header X Real IP remote addr 保留代理之前的真实客户端ip proxy set header X Forward
  • Python实例浅谈之三Python与C/C++相互调用

    一 问题 Python模块和C C 43 43 的动态库间相互调用在实际的应用中会有所涉及 xff0c 在此作一总结 二 Python调用C C 43 43 1 Python调用C动态链接库 Python调用C库比较简单 xff0c 不经过
  • C语言允许以下划线开头的函数存在

    首先 xff0c C 43 43 里关于下划线的问题是源于C语言 xff0c 因为C 43 43 允许用extern C 来修饰代码以C语言语法方式编译 然后说C语言里的下划线 xff1a C语言确实允许以下划线开头的函数存在 xff0c
  • Linux top命令的用法详细详解

    查看多核CPU命令 mpstat P ALL 和 sar P ALL 说明 xff1a sar P ALL gt aaa txt 重定向输出内容到文件 aaa txt top命令经常用来监控Linux的系统状况 xff0c 比如cpu 内存
  • c# WInform 自定义导航布局

    问题形成原因 xff1a 软件一般都是左侧树导航或上部菜单导航 xff0c 做好一个软件后 xff0c 有的客户可能想用一个页面做导航图像 而各个客户用的功能可能不同 xff0c 所以导航布局需要自定义 思路 xff1a 1 把菜单列出来

随机推荐