<?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/category/virtual/">
<title>dwt&#039;s life - 虚拟化技术</title>
<link>https://dwt.life/category/virtual/</link>
<description></description>
<items>
<rdf:Seq>
<rdf:li resource="https://dwt.life/archives/254/"/>
<rdf:li resource="https://dwt.life/archives/132/"/>
<rdf:li resource="https://dwt.life/archives/125/"/>
<rdf:li resource="https://dwt.life/archives/121/"/>
<rdf:li resource="https://dwt.life/archives/103/"/>
<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:li resource="https://dwt.life/archives/99/"/>
<rdf:li resource="https://dwt.life/archives/97/"/>
</rdf:Seq>
</items>
</channel>
<item rdf:about="https://dwt.life/archives/254/">
<title>LXD 强行删除默认存储</title>
<link>https://dwt.life/archives/254/</link>
<dc:date>2022-07-07T21:56:07+08:00</dc:date>
<description>printf &#039;config: {}\ndevices: {}&#039; | lxc profile edit defaultlxc storage delete defaulthttps://stackoverflow.com/questions/42678979/how-to-remove-default-lxd-storage</description>
</item>
<item rdf:about="https://dwt.life/archives/132/">
<title> Compile qemu on Ubuntu 20.04</title>
<link>https://dwt.life/archives/132/</link>
<dc:date>2021-09-22T01:06:00+08:00</dc:date>
<description>下载源码git clone https://git.qemu.org/git/qemu.git
cd qemu
git submodule init
git submodule update --recursive编译安装./configure
make问题# ERROR: glib-2.48 gthread-2.0 is required to compile QEMU
$ sudo apt install -y libglib2.0-dev

# ERROR: pixman &gt;= 0.21.8 not present.
#        Please install the pixman devel package.
$ sudo apt install -y libpixman-1-dev另外几个编译的过程日志；https://www.jianshu.com/p/80c11180ef96https://blog.csdn.net/haifeng_gu/article/details/108055083参考：https://bevisy.github.io/p/compile-qemu-on-ubuntu-20.04/</description>
</item>
<item rdf:about="https://dwt.life/archives/125/">
<title>libvirt禁止每次增加新DHCP IP时写入iptables</title>
<link>https://dwt.life/archives/125/</link>
<dc:date>2021-08-19T02:00:00+08:00</dc:date>
<description>每次增加DHCP IP的时候就会增加一条iptables规则,影响其他IP的正常使用,使用hooks直接恢复mkdir /etc/libvirt/hooks
for f in daemon qemu lxc libxl network; do
  echo &#039;#!/bin/sh
iptables-restore &lt; /etc/sysconfig/iptables
iptables -I FORWARD -j ACCEPT&#039; &gt; &quot;/etc/libvirt/hooks/$f&quot;
  chmod +x &quot;/etc/libvirt/hooks/$f&quot;
done
service libvirtd restart</description>
</item>
<item rdf:about="https://dwt.life/archives/121/">
<title>Libvirt设置防火墙规则重置</title>
<link>https://dwt.life/archives/121/</link>
<dc:date>2021-08-14T03:52:04+08:00</dc:date>
<description>mkdir /etc/libvirt/hooks
for f in daemon qemu lxc libxl network; do
  echo &#039;#!/bin/sh
iptables-restore &lt; /etc/sysconfig/iptables&#039; &gt; &quot;/etc/libvirt/hooks/$f&quot;
  chmod +x &quot;/etc/libvirt/hooks/$f&quot;
done
service libvirtd restart</description>
</item>
<item rdf:about="https://dwt.life/archives/103/">
<title>wireshark抓包SNI</title>
<link>https://dwt.life/archives/103/</link>
<dc:date>2021-08-10T03:06:26+08:00</dc:date>
<description>http抓包相对而已比较简单了，tcpdump可以完成httpry（基于tcpdump）也可以介绍一下如何抓包https的域名tshark -p -Tfields -e ssl.handshake.extensions_server_name -Y 'ssl.handshake.extension.type == "server_name"'其中要安装tshark即yum install wiresharktshark -p -Tfields -e ssl.handshake.extensions_server_name -e http.host -Y 'ssl.handshake.extension.type == "server_name" or http.host' -i br0</description>
</item>
<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>
<item rdf:about="https://dwt.life/archives/99/">
<title>通过libvirt使用ceph块设备</title>
<link>https://dwt.life/archives/99/</link>
<dc:date>2021-08-07T14:51:00+08:00</dc:date>
<description>1. 创建存储池[root@ceph1 ~]# ceph osd pool create libvirt-pool 128 128查看刚刚创建的存储池：[root@ceph1 ~]# ceph osd lspools

0 rbd,1 .rgw.root,2 default.rgw.control,3 default.rgw.meta,4 default.rgw.log,5 default.rgw.buckets.index,6 default.rgw.buckets.data,7 default.rgw.buckets.non-ec,8 libvirt-pool,2. 创建ceph用户client.libvirt，权限限制到存储池libvirt-pool[root@ceph1 ~]# ceph auth get-or-create client.libvirt mon &#039;allow r&#039; osd &#039;allow class-read object_prefix rbd_children, allow rwx pool=libvirt-pool&#039;验证：[root@ceph1 ~]# ceph auth list

...

client.libvirt

key: AQBblU1b9FECCRAA4tW8qaBYtxTsDlaNJybZSQ==

caps: [mon] allow r

    caps: [osd] allow class-read object_prefix rbd_children, allow rwx pool=libvirt-pool

   ...3. 把虚拟机镜像文件centos6864.qcow2.img导入存储池libvirt-pool中[root@ceph1 ~]# qemu-img convert -f qcow2 -O raw centos6864.qcow2.img rbd:libvirt-pool/centos6864.qcow2.img验证：[root@ceph1 ~]# rbd -p libvirt-pool lscentos6864.qcow2.img4. 在libvirt中配置ceph认证需要的密钥定义密钥[root@localhost ~]# cat &gt; secret.xml &lt;&lt;EOF

&lt;secret ephemeral=&#039;no&#039; private=&#039;no&#039;&gt;

    &lt;usage type=&#039;ceph&#039;&gt;

        &lt;name&gt;client.libvirt secret&lt;/name&gt;

    &lt;/usage&gt;

&lt;/secret&gt;virsh secret-define --file secret.xml获取密钥uuid[root@localhost ~]# virsh secret-list

        UUID                                  Usage

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

 fdcb5967-d3e5-4618-98f5-5919a723e414  ceph client.libvirt secret设置密钥的值virsh secret-set-value --secret fdcb5967-d3e5-4618-98f5-5919a723e414 --base64 AQBblU1b9FECCRAA4tW8qaBYtxTsDlaNJybZSQ==其中“AQBblU1b9FECCRAA4tW8qaBYtxTsDlaNJybZSQ==”是从上面ceph auth list的client.libvirt的key字段中得到的5. 修改虚拟机xml文件的disk部分[root@localhost ~]# virsh edit test
&lt;disk type=&#039;network&#039; device=&#039;disk&#039;&gt;

      &lt;driver name=&#039;qemu&#039;/&gt;

      &lt;auth username=&#039;libvirt&#039;&gt;

        &lt;secret type=&#039;ceph&#039; uuid=&#039;fdcb5967-d3e5-4618-98f5-5919a723e414&#039;/&gt;

      &lt;/auth&gt;

      &lt;source protocol=&#039;rbd&#039; name=&#039;libvirt-pool/centos6864.qcow2.img&#039;&gt;

        &lt;host name=&#039;192.168.1.15&#039; port=&#039;6789&#039;/&gt;

        &lt;host name=&#039;192.168.1.16&#039; port=&#039;6789&#039;/&gt;

        &lt;host name=&#039;192.168.1.17&#039; port=&#039;6789&#039;/&gt;

      &lt;/source&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;0x06&#039; function=&#039;0x0&#039;/&gt;

&lt;/disk&gt;
     ...其中secret的uuid就是上面创建密钥的uuid；host配置的是ceph monitor的ip和端口，有几个monitor就写几个。6. 开启虚拟机[root@localhost ~]# virsh start test</description>
</item>
<item rdf:about="https://dwt.life/archives/97/">
<title>虚拟机镜像管理工具-- Libguestfs</title>
<link>https://dwt.life/archives/97/</link>
<dc:date>2021-08-05T22:42:00+08:00</dc:date>
<description>libguestfs是一个用来访问和修改虚拟机磁盘镜像的一个工具集libguestfs 是一组 Linux 下的 C 语言的 API ，用来访问虚拟机的磁盘映像文件。该工具包内包含的工具有virt-cat、virt-df、virt-ls、virt-copy-in、virt-copy-out、virt-edit、guestfs、guestmount、virt-list-filesystems、virt-list-partitions等工具，具体用法也可以参看官网。该工具可以在不启动KVM guest主机的情况下，直接查看guest主机内的文内容，也可以直接向img镜像中写入文件和复制文件到外面的物理机，当然其也可以像mount一样，支持挂载操作。安装Libguestfsyum install libguestfs-tools实例如何利用Libguestfs修复受损虚拟机？作为VMware虚拟化环境管理员，你肯定遇到过虚拟机无法启动的情况。实施排错时，你需要对虚拟机的内部进行检查。而Libguestfs Linux工具集可以在这种情况下为你提供帮助。Libguestfs允许在虚拟机上挂载任何类型的文件系统，以便修复启动故障。利用Libguestfs找出损坏的虚拟机文件使用Libguestfs，首先需要使用Libvirt。Libvirt是一个管理接口，可以和KVM、Xen和其他一些基于Liunx的虚拟机相互连接。Libguestfs的功能更加强大，可以打开Windows虚拟机上的文件。这意味着除了能够使用libguestfs，你还需要一些关于虚拟机操作系统内部架构的知识。但是首先你需要将虚拟机迁移到libguestfs可用的环境当中，也就是Linux环境。1. 使用guestfish操作虚拟机完成虚拟机磁盘镜像文件的复制之后，可以在libguestfs中使用guestfish这样的工具将其打开，这样就可以直接在vmdk文件上进行操作了。使用guestfish -rw -a /path/to/windows.vmdk命令来在虚拟机中创建一个连接到文件系统的交互式shell。在新出现的窗口中，你可以使用特定的命令来操作虚拟机文件。第一个任务就是找到可用的文件系统：\&gt;&lt;fs&gt; run 
\&gt;&lt;fs&gt; list-filesystems 
/dev/sda1: ntfs 
/dev/sda2: ntfs 当你使用guestfish shell找到可用文件系统类型之后，就可以进行挂载了。使用命令mount /dev/sda2 / 来挂载二个分区的内容——在Linux中是/dev/sda2——到guestfish根目录下。在guestfish中，你不能像在其他shell环境中一样操作目录。挂载的分区就是根目录，你不能使用cd命令来切换目录，这意味着所有的路径必须是完全限定路径，从根目录开始。在guestfish shell当中可以使用像vi、ls、cat、more、download这样的命令，来查看和下载文件以及目录，输入help可以看到完整的命令信息。在完整所有操作之后可以使用exit来关闭guestfish shell。2. virt-rescue提供了直接访问方式在libguestfs工具中，还有许多其他可用的工具。virt-rescue命令——是使用正常的Linux文件系统工具来实现ad-hoc变化的最佳命令——可以在安全shell中启动虚拟机。你可以在虚拟机中操作这些文件，就像对挂载的文件系统上进行操作一样，其提供了对虚拟机内容更加直接的访问方式。为了在虚拟机上使用virt-rescue命令进行操作，使用virt-rescure 虚拟机名来打开virt-rescue shell，之后就进入了&gt;&lt;rescue&gt;模式。如果需要在虚拟机中挂载系统文件，可以使用fdisk -l /dev/sda命令来查看虚拟机的分区情况，之后再使用命令mount /dev/sda1 /sysroot挂载你想要访问的分区。这样你就可以通过更改来修复虚拟机的内容了。虚拟机修复之后，关闭virt-rescue shell，将虚拟机重新移动到ESXi服务器的数据存储当中。虚拟机返回原位置之后，如果之前的操作一切顺利，你就应该可以访问它了。其他命令：virt-df查看磁盘占用率[root@localhost file]# virt-df centos.img
Filesystem                           1K-blocks       Used  Available  Use%
centos.img:/dev/sda1                    495844      31950     438294    7%
centos.img:/dev/VolGroup/lv_root      28423176     721504   26257832    3%virt-ls查看目录下文件[root@localhost file]# virt-ls centos.img /
.autofsck
bin
boot
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
sbin
selinux
srv
sys
tmp
usrvirt-copy-out将镜像里的文件拷贝出来virt-copy-out -d 虚拟机名 /etc/passwd /tmp/virt-filesystemsvirt-list-filesystemsvirt-list-partitions查看分区相关信息[root@localhost file]# virt-filesystems  -d 虚拟机名
/dev/sda1
/dev/VolGroup/lv_root

[root@localhost file]# virt-list-filesystems  /file/centos.img
/dev/VolGroup/lv_root
/dev/sda1

[root@localhost file]# virt-list-partitions  /file/centos.img
/dev/sda1
/dev/sda2guestmount分区挂载[root@localhost ~]# guestmount -a /file/centos.qcow2  -m /dev/sda2  --rw /mnt
libguestfs: error: mount_options: /dev/sda2 on / (options: &#039;&#039;): mount: unknown filesystem type &#039;LVM2_member&#039;
guestmount: &#039;/dev/sda2&#039; could not be mounted.
guestmount: Did you mean to mount one of these filesystems?
guestmount:     /dev/sda1 (ext4)
guestmount:     /dev/VolGroup/lv_root (ext4)
guestmount:     /dev/VolGroup/lv_swap (swap)
[root@localhost ~]# guestmount -a /file/centos.qcow2  -m /dev/VolGroup/lv_root  --rw /mnt
fuse: mountpoint is not empty
fuse: if you are sure this is safe, use the &#039;nonempty&#039; mount option
libguestfs: error: fuse_mount: /mnt: Resource temporarily unavailable
[root@localhost ~]# ls /mnt/
bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  sbin  selinux  srv  sys  tmp  usr  var
[root@localhost ~]# umount /mnt/

[root@localhost ~]# guestmount -a /file/centos.qcow2  -m /dev/VolGroup/lv_root  --rw /mnt
[root@localhost ~]# ls /mnt/
bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  sbin  selinux  srv  sys  tmp  usr  var

[root@localhost ~]# umount /mnt/使用libguestfs访问windows系统[root@localhost opt]# virt-ls -a /file/win7.img c:
virt-ls: no operating system was found on this disk
If using guestfish &#039;-i&#039; option, remove this option and instead
use the commands &#039;run&#039; followed by &#039;list-filesystems&#039;.
You can then mount filesystems you want by hand using the
&#039;mount&#039; or &#039;mount-ro&#039; command.
If using guestmount &#039;-i&#039;, remove this option and choose the
filesystem(s) you want to see by manually adding &#039;-m&#039; option(s).
Use &#039;virt-filesystems&#039; to see what filesystems are available.
If using other virt tools, this disk image won&#039;t work
with these tools.  Use the guestfish equivalent commands
(see the virt tool manual page).
RHEL 6 notice
-------------
libguestfs will return this error for Microsoft Windows guests if the
separate &#039;libguestfs-winsupport&#039; package is not installed. If the
guest is running Microsoft Windows, please try again after installing
&#039;libguestfs-winsupport&#039;.需要注意的是，上面的用法中，有两个错误的地方，一处是linux查看C分区，后面不能直接跟C：，而应该换用/ ；第二个错误是由于没有安装libguestfs-winsupport 。该工具也可以看接通过yum安装 。安装完该包后，再进行查看：[root@localhost opt]# virt-ls -a /file/win7.img /
$Recycle.Bin
Documents and Settings
PerfLogs
Program Files
Program Files (x86)
ProgramData
Recovery
System Volume Information
Users
Windows
pagefile.sys利用guestmount进行挂载[root@localhost ~]# guestmount -a /file/win7.img  -m /dev/sda2  --rw /mnt
[root@localhost ~]# ls /mnt/
Documents and Settings  pagefile.sys  PerfLogs  ProgramData  Program Files</description>
</item>
</rdf:RDF>