<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel rdf:about="https://dwt.life/feed/rss/tag/snapshot/">
<title>dwt&#039;s life - snapshot</title>
<link>https://dwt.life/tag/snapshot/</link>
<description></description>
<items>
<rdf:Seq>
<rdf:li resource="https://dwt.life/archives/102/"/>
<rdf:li resource="https://dwt.life/archives/101/"/>
<rdf:li resource="https://dwt.life/archives/100/"/>
</rdf:Seq>
</items>
</channel>
<item rdf:about="https://dwt.life/archives/102/">
<title>KVM虚拟机克隆快照总结</title>
<link>https://dwt.life/archives/102/</link>
<dc:date>2021-08-07T15:34:00+08:00</dc:date>
<description>克隆方案# virsh-clone 
＃ virt-clone --connect qemu:///system --original test2 --name testclone --file /var/lib/libvirt/images/newdemo.img --file /var/lib/libvirt/images/newdata.img

virt-clone --connect qemu:///system -o test2 --n testclone -f /fine1fs/virtual/vm/node25/testclone

/fine1fs/virtual/vm/node25/34c0ac46-8052-11e9-a322-fcaa14a3eb62

## 连接克隆 
# os_disk img_type == file
qemu-img create -f qcow2 -b /fine1fs/virtual/vm/node25/34c0ac46-8052-11e9-a322-fcaa14a3eb62/34c0ac46-8052-11e9-a322-fcaa14a3eb62_os.qcow2 /fine1fs/virtual/vm/node25/teset12/test12.qcow2

virsh dumpxml test2 &gt; /fine1fs/virtual/vm/node25/teset12/test12.xml
vim /etc/libvirt/qemu/test12.xml #修改name、UUID
virsh define /etc/libvirt/qemu/test12.xml
# os_disk img_type == rbd
# rbd 使用快照
#创建一个快照
rbd snap create -p rbd_pool/foo@foo_snap

#查看快照
rbd snap list -p rbd_pool foo #注意是foo不是foo_snap

#在克隆之前，确保快照处于protected状态
rbd snap protect  rbd_pool/foo@foo_image

# 克隆 
rbd clone test_for_s3/node25_a55f772e-86a7-11e9-b731-fcaa14a3eb62_os@20190610152225.snap test_for_s3/node25_e3e0926c-8b52-11e9-abe3-fcaa14a3eb62_os

#创建一个新的pool1: 
ceph osd pool create pool1 8 8

#克隆到pool1：
rbd clone rbd_pool/foo@foo_snap pool1/newfoo

#查看快照的children: 
rbd children rbd_pool/foo@foo_snap
#pool1/newfoo

#扁平化可以断开父子间的依赖关系：
rbd flatten pool1/newfoo
虚拟机克隆
# 
rbd ls test_for_s3

# 创建快照
rbd snap create test_for_s3/node25_8c8c9228-8c0f-11e9-bc32-fcaa14a3eb62_os@20190610152226.snap



# 保护快照
rbd snap protect  test_for_s3/node25_a55f772e-86a7-11e9-b731-fcaa14a3eb62_os@20190610152226.snap

# 克隆 
rbd clonetest_for_s3/node25_8c8c9228-8c0f-11e9-bc32-fcaa14a3eb62_os@20190610152226.snap test_for_s3/node25_3be0e280-8c1d-11e9-8eaa-fcaa14a3eb62_os 2&gt;&amp;1 | tee e

rbd clone rbd clone %s/%s@%s %s/%s 2&gt;&amp;1 |tee %s %s

#查看快照的children: 
rbd children rbd_pool/foo@foo_snap
#pool1/newfoo

#扁平化可以断开父子间的依赖关系：
rbd flatten test_for_s3/node25_34c0ac46-8052-11e9-a322-fcaa14a3eb62_os

# 取消保护
rbd snap unprotect  test_for_s3/node25_a55f772e-86a7-11e9-b731-fcaa14a3eb62_os@20190610152226.snap

# 删除快照
rbd snap rm test_for_s3/node25_a55f772e-86a7-11e9-b731-fcaa14a3eb62_os@20190610152226.snap
虚拟机快照创建虚拟机快照kvm 环境 qcow2 支持快照# 确认镜像格式
qemu-img info test.qcow2

# 创建虚拟机快照
qemu-img snapshot -c snapshot01 test.qcow2  

# 列出某个镜像的所有快照
qemu-img snapshot -l test.qcow2  

# 使用快照
qemu-img snapshot -a snapshot01 test.qcow2  

# 删除快照
qemu-img snapshot -d snapshot01 test.qcow2 创建外部快照# 取最后一个快照
last_snap_name = dom.snapshotListNames()

# 路径获取
import os
a = &quot;/fine1fs/virtual/vm/node25/c998baae-9199-11e9-891b-fcaa14a3eb62/c998baae-9199-11e9-891b-fcaa14a3eb62_os.snapshot2&quot;
print(os.path.splitext(a)[0])


if dom.isActive():
    dom.managedSave()
    
snap = dom.snapshotCreateXML(snapxml,flags=148)磁盘快照和内存+磁盘快照#!/bin/bash
DOMAIN=&quot;test&quot;
TIMESTAMP=`date +%s`
SNAPSHOT_NAME=$TIMESTAMP

VM_FOLDER=&quot;/path/to/vms&quot;
SNAPSHOT_FOLDER=&quot;`echo $VM_FOLDER`/`echo $DOMAIN`/snapshots/`echo $TIMESTAMP`&quot;
mkdir -p $SNAPSHOT_FOLDER

MEM_FILE=&quot;`echo $SNAPSHOT_FOLDER`/mem.qcow2&quot;
DISK_FILE=&quot;`echo $SNAPSHOT_FOLDER`/disk.qcow2&quot;

# Find out if running or not
STATE=`virsh dominfo $DOMAIN | grep &quot;State&quot; | cut -d &quot; &quot; -f 11`

if [ &quot;$STATE&quot; = &quot;running&quot; ]; then

  virsh snapshot-create-as \
    --domain $DOMAIN $SNAPSHOT_NAME \
    --diskspec vda,file=$DISK_FILE,snapshot=external \
    --memspec file=$MEM_FILE,snapshot=external \
    --atomic

else

  virsh snapshot-create-as \
    --domain $DOMAIN $SNAPSHOT_NAME \
    --diskspec vda,file=$DISK_FILE,snapshot=external \
    --disk-only \
    --atomic

fi

virsh snapshot-create-as  --domain snaptest snapshot1 --diskspec file=&quot;/fine1fs/virtual/vm/node25/14e9948e-9199-11e9-8eb8-fcaa14a3eb62/14e9948e-9199-11e9-8eb8-fcaa14a3eb62_os.snapshot1&quot;,snapshot=external --memspec file=&quot;/fine1fs/virtual/vm/node25/14e9948e-9199-11e9-8eb8-fcaa14a3eb62/14e9948e-9199-11e9-8eb8-fcaa14a3eb62_os.memory&quot;,snapshot=external --atomic虚拟机快照测试# 虚拟机 running 
if dom.isActive():
    ret = dom.save(path)
    
    
dom.restore(path)


#ret = dom.snapshotCreateXML(memansp,flags=384)修改要求1.虚拟机支持快照  (1)已创建快照虚拟机不允许导出、克隆、迁移操作  (2)磁盘快照使用外部快照，创建快照需要暂停虚拟机(是否需要手动暂停)或关闭虚拟机,支持raw和qcow2格式  (3)只有虚拟机运行的时候，才允许创建内存快照2.其他virsh start x                                 启动名字为x的非活动虚拟机

virsh create x.xml                      创建虚拟机（创建后，虚拟机立即执行，成为活动主机）

virsh suspend x                             暂停虚拟机

virsh resume x                             启动暂停的虚拟机

virsh shutdown x                    正常关闭虚拟机

virsh destroy x                              强制关闭虚拟机

virsh dominfo x                              显示虚拟机的基本信息

virsh domname 2                                   显示id号为2的虚拟机名

virsh domid x                                显示虚拟机id号

virsh domuuid x                             显示虚拟机的uuid

virsh domstate x                          显示虚拟机的当前状态
virsh blockcommit --domain snap –path --base /fine1fs/virtual/vm/node14/bab1f794-93d3-11e9-8c04-0cc47a6b577c/bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot03 --top /fine1fs/virtual/vm/node14/bab1f794-93d3-11e9-8c04-0cc47a6b577c/bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot04

virsh blockcommit --domain snap hda --base /fine1fs/virtual/vm/node14/bab1f794-93d3-11e9-8c04-0cc47a6b577c/bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot01 --top /fine1fs/virtual/vm/node14/bab1f794-93d3-11e9-8c04-0cc47a6b577c/bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot04 --wait --verbose
qemu-img rebase -u -b bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot02 bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot04查看快照关系链qemu-img info --backing-chain bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot05合并快照qemu-img rebase -u -b bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot02 bab1f794-93d3-11e9-8c04-0cc47a6b577c_os.snapshot04</description>
</item>
<item rdf:about="https://dwt.life/archives/101/">
<title>KVM虚拟机快照研究（二）</title>
<link>https://dwt.life/archives/101/</link>
<dc:date>2021-08-07T15:28:03+08:00</dc:date>
<description>使用Python脚本操作快照上一篇中介绍了KVM虚拟机各种快照的原理和命令行操作方法，由于磁盘外部快照最实用，所以本篇主要讲怎么利用Libvirt api操作磁盘外部快照。其中会涉及一些Libvirt api的基本用法，也会一起介绍。操作环境环境同上篇。Python与libvirt服务交互用的是libvirt模块；操作虚拟机的XML描述文件用的是xml.dom模块。创建快照我们要完成的功能是，给出一个虚拟机的名称，创建这个虚拟机的磁盘快照。首先建立与libvirt服务的连接，然后根据虚拟机名称获取该domain对象：conn = libvirt.open(&quot;qemu:///system&quot;)

dom = conn.lookupByName(&#039;vm&#039;)domain对象的方法snapshotCreateXML()实现了通过一个XML描述文件创建快照的功能，该方法接收的参数是一个描述快照的XML字符串（不是文件）和标志位flags。快照的XML描述文件一般是下面这种格式：  &lt;domainsnapshot&gt;

    &lt;name&gt;snapshot01&lt;/name&gt;

    &lt;description&gt;test api&lt;/description&gt;

    &lt;disks&gt;

      &lt;disk name=&#039;/path/diskname&#039;&gt;

      &lt;/disk&gt;

      &lt;disk name=&#039;/path/diskname&#039;&gt;

      &lt;/disk&gt;

    &lt;/disks&gt;

  &lt;/domainsnapshot&gt;可以看出，构建快照的XML描述文件需要首先获取到虚拟机的磁盘文件名，获取方法是读取并解析虚拟机的xml文件：xml = dom.XMLDesc(0)

doc = minidom.parseString(xml)

disks = doc.getElementsByTagName(&#039;disk&#039;)

for disk in disks:

    if disk.getAttribute(&#039;device&#039;) == &#039;disk&#039;:

    diskfile = disk.getElementsByTagName(&#039;source&#039;)[0].getAttribute(&#039;file&#039;)

    print diskfile这段代码的输出结果是：[root@localhost snapshot]# python test.py

/data/vm.img

/data/data.img然后把磁盘文件的名字填到快照xml里，存放在文件snapshot01.xml中：    &lt;domainsnapshot&gt;

      &lt;name&gt;snapshot01&lt;/name&gt;

      &lt;description&gt;test api&lt;/description&gt;

      &lt;disks&gt;

        &lt;disk name=&#039;/data/vm.img&#039;&gt;

        &lt;/disk&gt;

        &lt;disk name=&#039;/data/data.img&#039;&gt;

        &lt;/disk&gt;

      &lt;/disks&gt;

    &lt;/domainsnapshot&gt;flags另一个参数是标志位flags，Libvirt定义了一系列标志位控制创建快照的行为，每一位的作用可以通过查看Libvirt官方文档得知。Libvirt官方文档只有C语言的api文档，Python api的用法基本跟C语言的一致，所以不影响我们参考。标志位的取值及含义如下：#Restore or alter metadata

VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE    =   1  

#With redefine, make snapshot current

VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT =   2  

#Make snapshot without remembering it

VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA =   4  

#Stop running guest after snapshot

VIR_DOMAIN_SNAPSHOT_CREATE_HALT =   8  

#disk snapshot, not system checkpoint

VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY   =   16 

#reuse any existing external files

VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT   =   32 

#use guest agent to quiesce all mounted file systems   within the domain

VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE =   64 

#atomically avoid partial changes

VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC  =   128

#create the snapshot while the guest is running

VIR_DOMAIN_SNAPSHOT_CREATE_LIVE =   256我们需要用到的标志有VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA，VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY和VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC，分别对应virsh snapshot-create-as命令的参数--disk-only，--no-metadata和--atmotic。多个标志位叠加是通过二进制按位或操作，换算成十进制下的操作就是相加，所以flags的值为4+16+128=148。snapshotXML = open(&#039;snapshot01.xml&#039;,&#039;rb&#039;).read()

dom.snapshotCreateXML(snapshotXML,flags=148)快照脚本内容汇总如下：#!/usr/bin/python

import libvirt

import sys

from xml.dom import minidom

 

def getDom(vm):

    try:

        conn = libvirt.open(&quot;qemu:///system&quot;)

        dom = conn.lookupByName(vm)

        return dom

    except Exception,e:

        print &quot;Get domain   object of vm %s failed: %s&quot; % (vm,str(e))

        sys.exit(1)

 

def getDiskfile(vm):

    dom = getDom(vm)

    xml = dom.XMLDesc(0)

    doc = minidom.parseString(xml)

    disks = doc.getElementsByTagName(&#039;disk&#039;)

    diskfiles = []

    for disk in disks:

        if disk.getAttribute(&#039;device&#039;) == &#039;disk&#039;:

              diskfile = disk.getElementsByTagName(&#039;source&#039;)[0].getAttribute(&#039;file&#039;)

              diskfiles.append(diskfile)

    return diskfiles

 

def createXML(vm):

    diskfiles = getDiskfile(vm)

    xml = &quot;&quot;&quot;&lt;domainsnapshot&gt;

      &lt;name&gt;snapshot01&lt;/name&gt;

      &lt;description&gt;test api&lt;/description&gt;

    &lt;disks&gt;

      &lt;disk   name=&#039;%s&#039;&gt;

        &lt;/disk&gt;

      &lt;disk   name=&#039;%s&#039;&gt;

        &lt;/disk&gt;

      &lt;/disks&gt;

    &lt;/domainsnapshot&gt;&quot;&quot;&quot; % (diskfiles[0],diskfiles[1])

    with open(&#039;snapshot01.xml&#039;,&#039;w&#039;) as f:

        f.write(xml)

 

def createSnapshot(vm):

    dom = getDom(vm)

    snapshotXML = open(&#039;snapshot01.xml&#039;,&#039;rb&#039;).read()

    dom.snapshotCreateXML(snapshotXML,flags=148)

 

if __name__ == &quot;__main__&quot;:

    createXML(&#039;vm&#039;)

    createSnapshot(&#039;vm&#039;)
合并快照文件首先为虚拟机创建4个快照，现在磁盘文件形成了如下back chain（原理见上篇文章）：base&lt;-snapshot01&lt;-snapshot02&lt;-snapshot03&lt;-snapshot04*我们要通过api把snapshot03合并到snapshot02，用到的方法是blockCommit()，该方法有3个必须提供的参数disk，base和top，分别对应virsh blockcommit命令的参数--path，--base和--top。把命令virsh blockcommit --domain vm –path vda --base /data/vm.snapshot02 --top /data/vm.snapshot03翻译成Python代码就是：dom.blockCommit(&#039;vda&#039;,&#039;/data/vm.snapshot02&#039;,&#039;/data/vm.snapshot03&#039;)合并快照文件可能需要很长时间，但是blockCommit是异步的，执行完立即返回，如果我们想查看后台的这个合并任务，需要用blockJobInfo()方法查看合并任务是否已完成。合并脚本内容汇总如下：#!/usr/bin/python

import libvirt

import sys

 

def getDom(vm):

    try:

        conn = libvirt.open(&quot;qemu:///system&quot;)

        dom = conn.lookupByName(vm)

        return dom

    except Exception,e:

        print &quot;Get domain   object of vm %s failed: %s&quot; % (vm,str(e))

        sys.exit(1)

 

 

if __name__ == &quot;__main__&quot;:

    dom = getDom(&#039;vm&#039;)

  dom.blockCommit(&#039;vda&#039;,&#039;/data/vm.snapshot02&#039;,&#039;/data/vm.snapshot03&#039;)

    dom.blockCommit(&#039;vdb&#039;,&#039;/data/data.snapshot02&#039;,&#039;/data/data.snapshot03&#039;)</description>
</item>
<item rdf:about="https://dwt.life/archives/100/">
<title>KVM虚拟机快照研究（一）</title>
<link>https://dwt.life/archives/100/</link>
<dc:date>2021-08-07T15:24:00+08:00</dc:date>
<description>KVM虚拟机的快照用来保存虚拟机在某个时间点的内存、磁盘或者设备状态，如果将来有需要可以把虚拟机的状态回滚到这个时间点。根据被做快照的对象不同，快照可以分为磁盘快照和内存快照，两者加起来构成了一个系统还原点，记录虚拟机在某个时间点的全部状态；根据做快照时虚拟机是否在运行，快照又可以分为在线快照和离线快照。磁盘快照根据存储方式的不同，又分为内部快照和外部快照：内部快照只支持qcow2格式的虚拟机镜像，把快照及后续变动都保存在原来的qcow2文件内；外部快照在创建时，快照被保存在单独一个文件中，创建快照时间点之后的数据被记录到一个新的qcow2文件中，原镜像文件成为新的qcow2文件的backing file（只读），在创建多个快照后，这些文件将形成一个链——backing chain。外部快照同时支持raw和qcow2格式的虚拟机镜像。下文将分别具体介绍不同类型的KVM虚拟机快照。操作环境：操作系统：[root@localhost ~]# cat   /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)Libvirt版本：[root@localhost ~]# libvirtd --version
libvirtd (libvirt) 3.2.0qemu版本：[root@localhost ~]# rpm -qa|grep qemu-kvm
qemu-kvm-common-ev-2.3.0-29.1.el7.x86_64
qemu-kvm-ev-2.3.0-29.1.el7.x86_64centos7.4的默认yum源中的qemu-kvm不支持在线创建外部快照，需要安装Redhat的qemu-kvm-ev，安装方法：配置yum源[root@localhost ~]# cat   /etc/yum.repos.d/qemu-kvm-rhev.repo
[qemu-kvm-rhev]
name=oVirt rebuilds of qemu-kvm-rhev
baseurl=http://resources.ovirt.org/pub/ovirt-3.5/rpm/el7Server/
mirrorlist=http://resources.ovirt.org/pub/yum-repo/mirrorlist-ovirt-3.5-el7Server
enabled=1
skip_if_unavailable=1
gpgcheck=0安装[root@localhost ~]# yum install qemu-kvm-rhev -y测试机上有一台虚拟机[root@localhost ~]# virsh list

 Id      Name                             State

----------------------------------------------------

10      vm                             running
虚拟机的磁盘文件为系统盘/data/vm.img，数据盘/data/data.img。内存快照创建快照命令：virsh save vm vm.snapshot1[root@localhost ~]# virsh save vm   vm.snapshot1

 

Domain vm saved to vm.snapshot1

 
创建完后虚拟机会关机：

[root@localhost ~]# virsh list --all

 Id      Name                             State

----------------------------------------------------

 -       vm                             shut off回滚快照命令：virsh restore vm.snapshot1[root@localhost ~]# virsh restore   vm.snapshot1

Domain restored from vm.snapshot1

 

[root@localhost ~]# virsh list

 Id      Name                             State

----------------------------------------------------

 11      vm                             running注：只能对关机状态的虚拟机进行回滚快照；内存快照做完后，如果虚拟机磁盘文件发生修改，可能会导致corruption。磁盘内部快照磁盘内部快照可以在虚拟机开机状态创建，但是创建过程中虚拟机处于paused状态，创建快照命令：virsh snapshot-create-as --domain vm --name vm1这条命令执行后，虚拟机会变成paused状态[root@localhost ~]# virsh list

 Id      Name                             State

----------------------------------------------------

 13      vm                             paused
等快照创建完成，会重新变回running。查看快照命令：virsh snapshot-list –domain vm[root@localhost ~]# virsh snapshot-list   --domain vm

 Name                 Creation Time             State

------------------------------------------------------------

 vm1                  2018-03-06 10:37:57 +0800   running
快照回滚：virsh snapshot-revert --domain vm --snapshotname vm1快照删除：virsh snapshot-delete --domain vm --snapshotname vm1磁盘内部快照有2个缺点：只支持qcow2格式的镜像文件；创建快照虚拟机会paused，有停机时间，对于不能停机的线上业务来说是无法接受的。磁盘外部快照原理假设虚拟机磁盘镜像文件为base，创建一个外部快照snapshot1，这时候的镜像之间的关系backing chain如下：base&lt;-snapshot1*“*”表示目前active状态的镜像，base变为只读，snapshot1以base为backing file，虚拟机所有写入都发生在snapshot1，如果再创建一个外部快照snapshot2，backing chain会变成：base&lt;-snapshot1&lt;-snapshot2*snapshot2又以snapshot1为backing file，现在base和snapshot1都变成了只读。继续创建快照会加长这个backing chain：base&lt;-snapshot1&lt;-snapshot2&lt;-snapshot3&lt;-snapshot4*如果要回滚某个快照，就要把虚拟机使用的镜像指向该快照文件的backing file。例如，回滚到snapshot2，就要把虚拟机的镜像改为snapshot1；回滚到snapshot1，则要把虚拟机的镜像改为base。回滚到snapshot1会导致snapshot1之后的所有快照失效，因为他们在backing chain上游的backing file发生了变化（backing file只能是只读，如果数据发生变化，下游镜像也会失效）。缩短链随着快照数量变多，backing chain也会越来越长，变得难以维护。如果有些快照已经没用了可以进行删除。缩短这条链通常有两种思路：blockcommit，从top文件合并数据到base（下游镜像向backing file合并，称为“commit”）；blockpull，从base文件合并数据到top（从backing file向下游镜像合并，称为“pull”）。截止目前只能将backing file合并至当前的active的镜像中，也就是说还不支持指定top的合并。删除快照在上面的backing chain中，如果我们要删除snapshot2，方法如下：blockcommit：把snapshot2的数据合并到snapshot1，合并完后backing chain变成了base&lt;-snapshot1&lt;-snapshot2（内容为snapshot2+snapshot3）&lt;-snapshot4*blockpull：把snapshot2的数据合并到snapshot3，合并完后backing chain变成了base&lt;-snapshot1&lt;-snapshot3（内容为snapshot2+snapshot3）&lt;-snapshot4*具体操作1. 创建外部快照命令：virsh snapshot-create-as --domain vm --name snapshot1 --disk-only --atomic --no-metadata--disk-only 有这个参数，snapshot-create-as命令就会创建磁盘外部快照；--atomic 如果虚拟机有多个磁盘，则把为虚拟机所有磁盘创建快照的操作当做一个原子操作，要么全部成功，要么全部失败；--no-metadata 不让libvirt记录快照的元数据。这个参数不是必须的，但是强烈建议使用，目前libvirt对外部快照支持不完整，只能创建，不能删除和回滚，如果要删除一个有外部快照的虚拟机，会出现以下报错：[root@localhost ~]# virsh undefine vm

error: Failed to undefine domain test

error: Requested operation is not valid:   cannot delete inactive domain with 1 snapshots加上这个参数后，libvirt不再管理外部快照，删除和回滚都不会受影响了。快照创建成功后，在虚拟机磁盘文件目录下会多出2个新文件vm.snapshot1和data.snapshot1，分别是系统盘和数据盘的快照文件，查看镜像信息可以看出，它们分别以原镜像为backing file，与之前原理中分析的一致：[root@localhost data]# qemu-img info   vm.snapshot1

image: vm.snapshot1

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 3.4M

cluster_size: 65536

backing file: /data/vm.img

backing file format: qcow2

Format specific information:

      compat: 1.1

      lazy refcounts: false

      refcount bits: 16

      corrupt: false

[root@localhost data]# qemu-img info   data.snapshot1

image: data.snapshot1

file format: qcow2

virtual size: 1.0G (1073741824 bytes)

disk size: 196K

cluster_size: 65536

backing file: /data/data.img

backing file format: qcow2

Format specific information:

      compat: 1.1

      lazy refcounts: false

      refcount bits: 16

corrupt: false创建完后，虚拟机xml文件中使用的磁盘文件会libvirt自动被改成这两个新文件，这两个新文件处于active状态，原镜像变为只读。&lt;disk type=&#039;file&#039; device=&#039;disk&#039;&gt;

        &lt;driver name=&#039;qemu&#039; type=&#039;qcow2&#039; cache=&#039;none&#039; io=&#039;native&#039;/&gt;

        &lt;source file=&#039;/data/vm.snapshot1&#039;/&gt;

        &lt;target dev=&#039;vda&#039; bus=&#039;virtio&#039;/&gt;

        &lt;address type=&#039;pci&#039; domain=&#039;0x0000&#039; bus=&#039;0x00&#039; slot=&#039;0x04&#039;   function=&#039;0x0&#039;/&gt;

      &lt;/disk&gt;

      &lt;disk type=&#039;file&#039; device=&#039;disk&#039;&gt;

        &lt;driver name=&#039;qemu&#039; type=&#039;qcow2&#039; cache=&#039;none&#039; io=&#039;native&#039;/&gt;

        &lt;source file=&#039;/data/data.snapshot1&#039;/&gt;

        &lt;target dev=&#039;vdb&#039; bus=&#039;virtio&#039;/&gt;

        &lt;address type=&#039;pci&#039; domain=&#039;0x0000&#039; bus=&#039;0x00&#039; slot=&#039;0x07&#039;   function=&#039;0x0&#039;/&gt;

      &lt;/disk&gt;2. 回滚快照Libvirt目前不支持回滚外部快照，只能纯手工操作。为了证明在回滚快照后虚拟机确实回到了快照记录的状态，我们在虚拟机中在/root下新建一个空文件test。然后关闭虚拟机并把虚拟机的磁盘改回vm.img和data.img，开机后会发现/root/test不见了，可以证明虚拟机文件系统回到了创建快照的时间点。由上面的操作我们可以得出结论：回滚到某个快照，就是把虚拟机当前磁盘文件改为这个快照文件的backing file；快照名和快照文件名并不对应，例如创建snapshot1后产生的文件vm.snapshot1中记录的并不是快照snapshot1的内容，它的backing file才是。在下面介绍删除快照时，牢记这点尤其重要。3.删除快照在原理中已经介绍过，删除快照有blockcommit和blockpull两种思路，由于blockpull不支持指定top的合并，下面将只介绍blockcommit方式。我们先为虚拟机vm多创建几个快照，现在快照链为（以下操作都以系统盘为例，数据盘同理）：`base&lt;-snapshot1&lt;-snapshot2&lt;-snapshot3&lt;-snapshot4*`qemu-img命令也可以查看链关系：[root@localhost   data]# qemu-img info --backing-chain vm.snapshot4

image:   vm.snapshot4

file format: qcow2

virtual size:   20G (21474836480 bytes)

disk size:   452K

cluster_size:   65536

backing file:   /data/vm.snapshot3

backing file   format: qcow2

Format   specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image:   /data/vm.snapshot3

file format:   qcow2

virtual size:   20G (21474836480 bytes)

disk size:   196K

cluster_size:   65536

backing file:   /data/vm.snapshot2

backing file   format: qcow2

Format   specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image:   /data/vm.snapshot2

file format:   qcow2

virtual size:   20G (21474836480 bytes)

disk size:   196K

cluster_size:   65536

backing file:   /data/vm.img

backing file   format: qcow2

Format   specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image:   /data/vm.img

file format:   qcow2

virtual size:   20G (21474836480 bytes)

disk size:   1.5G

cluster_size:   65536

Format   specific information:

    compat: 0.10

    refcount bits: 16现在我们要删除snapshot2，根据回滚快照时得出的结论，要回滚到snapshot2就是把虚拟机磁盘指向vm.snapshot1，所以删除snapshot2就要在不影响backing chain中其他文件的前提下，把vm.snapshot2的内容合并到vm.snapshot1，vm.snapshot1的内容发生了改变，也就不能回滚到snapshot2了，达到了删除快照的目的。操作命令如下：virsh blockcommit --domain vm vda --base /data/vm.snapshot1 --top /data/vm.snapshot2 --wait –verbose

virsh blockcommit --domain vm vdb --base /data/data.snapshot1 --top /data/data.snapshot2 --wait –verbose合并完后，使用qemu-img命令再次查看文件信息可以发现，vm.snapshot2已经不在backing chain中了：[root@localhost data]# qemu-img info --backing-chain vm.snapshot4

image: vm.snapshot4

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 1.1M

cluster_size: 65536

backing file: /data/vm.snapshot3

backing file format: qcow2

Format specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image: /data/vm.snapshot3

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 388K

cluster_size: 65536

backing file: /data/vm.snapshot1

backing file format: qcow2

Format specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image: /data/vm.snapshot1

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 1.5M

cluster_size: 65536

backing file: /data/vm.img

backing file format: qcow2

Format specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image: /data/vm.img

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 1.5G

cluster_size: 65536

Format specific information:

    compat: 0.10

    refcount bits: 16总结三种快照中，只有磁盘外部快照可以不停机创建，所以这种快照最符合我们平时的需求，后续研究也重点关注外部快照。不幸的是libvirt对外部快照的支持太弱，大部分操作需要我们人脑思考、手工操作。接下来研究的重点有以下几点：测试外部快照创建时是否真正零停机时间；虚拟机运行时进行快照文件合并对性能有何影响；利用Python脚本封装外部快照的操作。</description>
</item>
</rdf:RDF>