东东东 陈煜东的博客

分类存档: 虚拟化 ( 1 / 2)

libvirt 问题解决记录集

本篇记录在使用libvirt的时候遇到的一些情况,即解决方法.

出现Permission denied

[root@localhost vm]# virsh start centos
error: Failed to start domain centos
error: internal error process exited while connecting to monitor: qemu-system-x86_64: -drive file=/home/d/shixun/vm/vdisk.img,if=none,id=drive-ide0-0-0,format=qcow2: could not open disk image /home/d/shixun/vm/vdisk.img: Permission denied

解决:/etc/libvirt/qemu.conf

# Some examples of valid values are:
#
# user = "qemu" # A user named "qemu"
# user = "+0" # Super user (uid=0)
# user = "100" # A user named "100" or a user with uid=100
#
user = "root"

# The group for QEMU processes run by the system instance. It can be
# specified in a similar way to user.
group = "root"

# Whether libvirt should dynamically change file ownership
# to match the configured user/group above. Defaults to 1.
# Set to 0 to disable file ownership changes.
dynamic_ownership = 0

我的这个没能解决问题

/etc/init.d/libvirtd restart 不管用

libvirt遇到死锁

在使用virsh对虚拟机进行动态迁移时,虚拟机没有开启.于是就去开启虚拟机,但是却发现无法运行.

Error starting domain: Timed out during operation: cannot acquire state change lock

libvirtError: Timed out during operation: cannot acquire state change lock

我进行了以下的步骤

virsh undefine centos

####Login as a root user and kill the libvirtd.

killall -9 libvirtd

rm /var/run/libvirtd.pid   ##### Remove the libvirtd pid file.

/etc/init.d/libvirtd  restart   #### Restart libvirtd.

在尝试上面的操作后,不起作用.

修改一下的domain的xml文件中的name标签,给虚拟机改个名字,期间我还删除了domain的xml文件里的qemu:commandline里面信息,重新define后就可以运行了.

迁移需要FQDN

在进行迁移的时候使用命令 virsh migrate –live ubuntu qemu+ssh://dest_ip/system

error: internal hostname on destination resolved to localhost, but migration requires an FQDN

解决:ssh进入到dest host机器,运行hostname domain 就好了.其中domian是一个域名.将接下来就可以进行迁移了.

启动nfs出现问题

启动NFS服务,出现问题

Failed to issue method call: Unit nfsserver.service failed to load: No such file or directory. See system logs and 'systemctl status nfsserver.service' for details.

解决:按照教程来就好了

# vim /etc/exports
/var/lib/libvirt/images *.example.com(rw,no_root_squash,sync)

# service nfs start

# mount -t nfs storage_host:/var/lib/libvirt/images /var/lib/libvirt/images

挂载nfs出现问题

当去mount远程的nfs服务器,出现问题了.

mount.nfs: access denied by server while mounting 211.87.***.53:/mnt/nfs

解决:原来发现,在/etc/exports中,没有将/mnt/nfs添加进去,只能将里面有的文件夹才能mount到本机来.

可以先umoutn /mnt/nfs ,然后在mount看看能否成功

virsh关闭虚拟机

virsh shutdown 关闭虚拟机没起作用

解决:需要在虚拟机里安装一些东西

yum install acpid
chkconfig acpid on
service acpid start

virsh无法使用ssh协议访问远程机器

当我去远程查询信息的时候,virsh -c qemu+ssh://211.87.***.88/system list 的时候出现了下面的问题.

error: failed to connect to the hypervisor
error: no valid connection
error: End of file while reading data: : Input/output error

查看日志 cat /var/log/secure | grep sshd 发现是我这里主动发出断开的.难道是检测到libvirtd有些问题导致的?

当时使用virt-manage可以查询到远程的信息.估计是sshd出现的问题把.

解决:我没有重新安装sshd,我是通过tcp协议进行迁移的,因为是做测试,所以没有考虑安全的问题.具体使用tcp进行迁移,查看virsh使用qemu+tcp访问远程libvirtd .

分类: 虚拟化

virsh对kvm虚拟机进行动态迁移

迁移的类型:静态迁移和动态迁移

迁移虚拟机的方式有两种:一种是动态迁移,一种是静态迁移。

静态迁移

静态迁移:也叫做常规迁移、离线迁移(Offline Migration)。就是在虚拟机关机暂停的情况下从一台物理机迁移到另一台物理机。因为虚拟机的文件系统建立在虚拟机镜像上面,所以在虚拟机关机的情况下,只需要简单的迁移虚拟机镜像和相应的配置文件到另外一台物理主机上;如果需要保存虚拟机迁移之前的状态,在迁移之前将虚拟机暂停,然后拷贝状态至目的主机,最后在目的主机重建虚拟机状态,恢复执行。这种方式的迁移过程需要显式的停止虚拟机的运行。从用户角度看,有明确的一段停机时间,虚拟机上的服务不可用。这种迁移方式简单易行,适用于对服务可用性要求不严格的场合。

动态迁移

动态迁移(Live Migration):也叫在线迁移(Online Migration)。就是在保证虚拟机上服务正常运行的同时,将一个虚拟机系统从一个物理主机移动到另一个物理主机的过程。该过程不会对最终用户造成明显的影响,从而使得管理员能够在不影响用户正常使用的情况下,对物理服务器进行离线维修或者升级。与静态迁移不同的是,为了保证迁移过程中虚拟机服务的可用,迁移过程仅有非常短暂的停机时间。迁移的前面阶段,服务在源主机的虚拟机上运行,当迁移进行到一定阶段,目的主机已经具备了运行虚拟机系统的必须资源,经过一个非常短暂的切换,源主机将控制权转移到目的主机,虚拟机系统在目的主机上继续运行。对于虚拟机服务本身而言,由于切换的时间非常短暂,用户感觉不到服务的中断,因而迁移过程对用户是透明的。动态迁移适用于对虚拟机服务可用性要求很高的场合。

动态迁移需要将原有的虚拟机镜像放在采用 SAN(storage area network)或 NAS(network-attached storage)之类的集中式共享外存设备,这样迁移的时候,不是迁移整个硬盘镜象,而是迁移内存的信息.所以迁移起来,速度比较快,停顿时间少。

动态迁移实际上是把虚拟机的配置封装在一个文件中,然后通过高速网络,把虚拟机配置和内存运行状态从一台物理机迅速传送到另外一台物理机上,期间虚拟机一直保持运行状态。现有技术条件下,大多虚拟机软件如 VMware、Hyper-V、Xen 进行动态迁移都需要共享存储的支持。典型的共享存储包括 NFS 和 SMB/CIFS 协议的网络文件系统,或者通过 iSCSI 连接到 SAN 网络。选用哪一种网络文件系统,需要根据具体情况而定。本文的实验采用了 NFS 文件系统作为源主机和目的主机之间的共享存储。

使用nfs网络文件系统

source host和dest host都通过网卡和NFS server进行连接,所有的VM镜像都在NFS Server上,然后将VM1从source host迁移到dest host上,通过网络来进行迁移,所以网络的速度决定这迁移的快慢.

nfs配置

 修改文件vi /etc/exports
/home/images *(rw,sync,no_root_squash)
/home/images 为要共享的文件夹
 rw:可读写的权限;
 ro:只读的权限;
 no_root_squash:登入到 NFS 主机的用户如果是 ROOT 用户,他就拥有 ROOT 权限,此参数很不安全,建议不要使用。
 sync:资料同步写入存储器中。
 async:资料会先暂时存放在内存中,不会直接写入硬盘。

重新启动 nfsserver 服务
 # service nfsserver restart 或者 systemctl restart nfs-server.service

查看状态
systemctl status nfs-server.service   ####查看nfs-server状态
exportfs -av   #####如果显示出共享的文件夹的话,说明设置已经生效

挂载NFS-server共享网络存储到本机
mount -t  nfs  nfs-server-host:/home/images /mnt/nfs
将NFS-server上的存储器/home/images/ 挂载到本地的/mnt/nfs 文件夹下。

nfs可能遇到的问题

如果在挂载nfs的时候,按tab键无法补全路径.

那么是防火墙的原因,把它添加到允许的规则里。设置selinux

setsebool -P virt_use_nfs 1

权限拒绝

error: Failed to start domain vdisk
error: internal error Process exited while reading console log output: char device redirected to /dev/pts/1
qemu-system-x86_64: -drive file=/mnt/nfs/vdisk.img,if=none,id=drive-ide0-0-0,format=qcow2: could not open disk image /mnt/nfs/vdisk.img: Permission denied

设置/mnt/nfs/vdisk.img的权限

注意问题

一定要注意所要共享的目录的权限问题,包括它的父目录,这些目录的权限要一样,否则mount的时候会出错

另外这个镜像最好都方在一个位置下。比如将nfs挂载到source host在/mnt/nfs,那么最好也在dest host的/mnt/nfs,路径一样,这样将来迁移就比较方便了。增加迁移的成功率。而且使用virt-manage必须路径一直,virsh可以要求不一致。只好还是source host和dest host在相同的路径挂载NFS网络共享系统

进行迁移

启动虚拟机

在 source host主机启动虚拟机

virsh start vdisk    ####vdisk 为虚拟机的名字

查看虚拟机状态

# virsh list --all
 Id    名称                            状态
----------------------------------------------------
 1     centos                         running
 2     vdisk                          running

进行迁移

virsh migrate vdisk --live qemu+ssh://des_ip:/system --unsafe

稍微过一会儿,我们就可以在dest host目标主机上看到虚拟机正在运行了。

参考资料

分类: 虚拟化

使用virsh创建虚拟机

第一步,先新建一块虚拟硬盘,这个不多说了,看之前的资料有

第二步,新建一个xml文件,里面存放虚拟机的配置信息,有内存、cpu、硬盘位置、光驱、VNC等配置,我们先贴出一个demo,下载该文件

<domain type="kvm">
    <name>centos</name>  <!--虚拟机名称-->
    <memory unit="MiB">1024</memory>   <!--最大内存,单位k-->
    <currentMemory unit="MiB">1024</currentMemory>  <!--可用内存,单位k-->
    <vcpu>2</vcpu>   <!--//虚拟cpu个数-->
    <os>
        <type arch="x86_64" machine="pc">hvm</type>
        <boot dev="hd" /> <!-- 硬盘启动 -->
        <boot dev="cdrom" />     <!--//光盘启动-->
    </os>
    <features>
        <acpi />
        <apic />
        <pae />
    </features>
    <clock offset="localtime" />
    <on_poweroff>destroy</on_poweroff>
    <on_reboot>restart</on_reboot>
    <on_crash>destroy</on_crash>
    <devices>
        <emulator>/usr/libexec/qemu-kvm</emulator>
        <disk type="file" device="disk">
            <driver name="qemu" type="qcow2" />
            <source file="/var/lib/libvirt/images/test.qcow2" />        <!--目的镜像路径-->
            <target dev="hda" bus="ide" />
        </disk>
        <disk type="file" device="cdrom">
            <source file="/var/lib/libvirt/images/ubuntu.iso" />        <!--光盘镜像路径 -->
            <target dev="hdb" bus="ide" />
        </disk>
        <interface type="bridge">       <!--虚拟机网络连接方式-->
            <source bridge="br0" />      <!--当前主机网桥的名称-->
        </interface>
        <input type="mouse" bus="ps2" />
        <!--vnc方式登录,端口号自动分配,自动加1,可以通过virsh vncdisplay来查询-->
        <graphics type="vnc" port="-1" autoport="yes" listen="0.0.0.0" keymap="en-us" />
    </devices>
</domain>

创建虚拟机

virsh define centos.xml   ###将配置导入到虚拟机
virsh start centos    #### 启动虚拟机

分类: 虚拟化

qemu和libvirt在pci pass through下动态迁移失败

最近的项目是虚拟机在PCI pass-through下做动态迁移,目前还没有一个好的解决方案,需要我们小组去讨论并提出一个解决方案来.既然是要做PCI pass through下做动态迁移的解决方案,那就得要先在这样的情况下做个迁移,看看到底会出现什么样的问题.

方案一:使用virsh进行动态迁移

在前面的文章中,我们进行的虚拟机的pci pass through,如果对pci pass through有不会的地方,参考之前的文章来进行设置.

接下来,我们要进行虚拟机的动态迁移.使用virsh启动虚拟机,运行以下命令进行迁移

virsh migrate --live vdisk qemu+ssh://211.87.***.45/system --unsafe

运行完后会出现问题.报了一个这样的错误.

error: Requested operation is not valid: domain has assigned non-USB host devices

上面的错误说明,现在的请求操作的非法的,因为虚拟机使用了非USB设备.

可以看到libvirt的源码 src/qemu/qemu_migration.c

/* Validate whether the domain is safe to migrate.  If vm is NULL,
 * then this is being run in the v2 Prepare stage on the destination
 * (where we only have the target xml); if vm is provided, then this
 * is being run in either v2 Perform or v3 Begin (where we also have
 * access to all of the domain's metadata, such as whether it is
 * marked autodestroy or has snapshots).  While it would be nice to
 * assume that checking on source is sufficient to prevent ever
 * talking to the destination in the first place, we are stuck with
 * the fact that older servers did not do checks on the source. */
bool
qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm,
                       virDomainDefPtr def, bool remote, bool abort_on_error)
{
    int nsnapshots;
    int pauseReason;
    bool forbid;
    size_t i;

    if (vm) {
        if (qemuProcessAutoDestroyActive(driver, vm)) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is marked for auto destroy"));
            return false;
        }

        /* perform these checks only when migrating to remote hosts */
        if (remote) {
            nsnapshots = virDomainSnapshotObjListNum(vm->snapshots, NULL, 0);
            if (nsnapshots < 0)
                return false;

            if (nsnapshots > 0) {
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("cannot migrate domain with %d snapshots"),
                               nsnapshots);
                return false;
            }

            /* cancel migration if disk I/O error is emitted while migrating */
            if (abort_on_error &&
                virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
                pauseReason == VIR_DOMAIN_PAUSED_IOERROR) {
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("cannot migrate domain with I/O error"));
                return false;
            }

        }

        if (virDomainHasDiskMirror(vm)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("domain has an active block job"));
            return false;
        }

        def = vm->def;
    }

    /* Migration with USB host devices is allowed, all other devices are
     * forbidden.
     */
    forbid = false;
    for (i = 0; i < def->nhostdevs; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];
        if (hostdev>mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
            hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
            forbid = true;
            break;
        }
    }
    if (forbid) {
        virReportError(VIR_ERR_OPERATION_INVALID,"%s",
                       _("domain has assigned non-USB host devices"));
        return false;
    }

    return true;
}

可以看到源码上显示,只要检测到虚拟机上使用了非USB的PCI设备,直接将borbid设置为true,禁止虚拟机的迁移.

如果要添加可以迁移的PCI设备,那么需要在这里进行相应的修改.

方案二:使用qemu进行动态迁移

在source host运行以下命令以启动虚拟机

/usr/bin/qemu-kvm -name vdisk -enable-kvm -m 512 -smp 2 
-hda /mnt/nfs/vdisk.img 
-monitor stdio 
-vnc 0.0.0.0:0 
-device pci-assign,host=00:1b.0

在dest host上运行以下命令,等待虚拟机的迁移:

/usr/bin/qemu-kvm -name vdisk -enable-kvm -m 512 -smp 2 
-hda /mnt/nfs/vdisk.img 
-monitor stdio 
-vnc 0.0.0.0:0 
-incoming tcp:0.0.0.0:8888
  • 参数-incoming tcp:0.0.0.0:8888说明的是,虚拟机在监听tcp的8888端口,等待源虚拟机被迁移过来.

此时虚拟机的状态是inmigration状态,等待被迁移过来.

在source host上输入以下命令,进行虚拟机的迁移.

(qemu) migrate -d -b tcp:dest_ip:8888

 -d 可以在迁移的过程中查询迁移状态,否则只能在迁移结束后查询。
 -b 迁移虚拟机存储文件
 tcp:dest_ip:8888 数据迁移的协议、目的主机和端口。协议和端口必须和目的主机上虚拟机的 -incoming 参数一致。

运行这个命令后,出报这样的错误

(qemu) migrate -d tcp:dest_ip:8888
migrate: State blocked by non-migratable device '0000:00:04.0/pci-assign'

应该也是进行了检查,使用了一个不可迁移设备即pci pass through的设备.

通过libvirt和qemu的动态迁移出先的问题,基本可以定位到相应的代码,那么只要提供一种相应的解决方案,那么就可以迁移其他的设备了.

分类: 虚拟化

域(Domains) 客户机(Guests) 虚拟机(Virtual Machines)区别

术语域 (domain)客户机 (guest)虚拟机 (virtual machine)经常被交换使用的.但是他们还是有细微的区别的.

域 (domain) 是一组可配置的资源集合,包括内存,虚拟CPU,网络设备,存储设备,这些配置都是虚拟机 (virtual machine)运行的时候使用的.域 (Domain)被独立地赋予了虚拟资源(virtual resources),并且可以启动(start)、停止(stop)、重启(restart).

如果你使用过libvirt,那么你应该知道有个domain XML文件,回忆一下里面是记录着什么?是资源的信息吧.有CPU,内存,硬盘,光驱,网络,还有PCI上的设备.

客户机 (Guest)是一个运行在domain之内的虚拟化操作系统.也可以叫Guest OS,它可以是半虚拟化或者是硬件虚拟化.

虚拟机 (virtual machine)上可以运行它自己的操作系统(也叫做Guest OS) 。

参考资料

分类: 虚拟化

查看virsh管理qemu虚拟机日志信息和libvirtd日志信息

在软件的开发和运行过程中,程序的运行日志log是不能少的。我们可以从log中发现程序的运行状态,以及可能出先的一些error.通常运行日志log上有时间、信息级别(level)、消息输出(message)。通过分析日志,我们可以从中获得程序的运行信息,方便我们的调试、恢复等.

在libvirt程序管理VM虚拟机时,也会有日志的记录.既有libvirtd的后台程序的日志,也有vm日志.接下来,我们设置一些日志的信息.

libvirtd的运行日志

在运行libvirtd的时候,我们需要获得lbivirtd的运行信息.所以我们需要找到他的日志文件.一般情况下,它是在/var/log/libvirt/libvirtd.log路径下.

可能在这个目录下没有发现这个的日志文件.那么就要配置一些libvitd的参数了.

编辑文件/etc/libvirt/libvirtd.conf

#将日志级别设置为 1(调试)
log_level = 1
#指定日志输出文件名称
log_outputs="1:file:/var/log/libvirt/libvirtd.log"
注意 :libvirtd. 日志文件可能会飞速增长。 用户应配置logrotate ,否则您的 /var 文件系统最后会装满内容。

以上的日志的输出级别为debug级别.这个级别的日志是最多的,一般只在开发以及测试的时候使用.而在生产运行环境中,日志的级别为info,warn,error,fatal. 以下前面的数字为他们的level.

  • 1 debug
  • 2 info
  • 3 warn
  • 4 error
  • 5 fatal

重启libvirtd 。虚拟机Guest操作系统正在运行时可重启 libvirtd。

# /etc/init.d/libvirtd restart

如果在目录下还是没发现日志文件,那么你可能需要使用一下命令来运行libvirtd.

libvirtd --daemon --listen --config /etc/libvirt/libvirtd.conf

查看virsh管理qemu虚拟机的信息

在使用virsh管理qemu的虚拟机时候,也是有日志的输出的.

具体的log在目录/var/log/livirt/qemu/ 下面,具体的log文件名与虚拟机名字关联.

分类: 虚拟化

virsh使用qemu+tcp访问远程libvirtd

因为ssh的不能访问 所以使用tcp进行对远程libvirtd进行连接访问,例如

virsh -c qemu+tcp://example.com/system

修改文件vim /etc/sysconfig/libvirtd,用来启用tcp的端口

LIBVIRTD_CONFIG=/etc/libvirt/libvirtd.conf

LIBVIRTD_ARGS="--listen"

修改文件vim /etc/libvirt/libvirtd.conf

listen_tls = 0

listen_tcp = 1

tcp_port = "16509"

listen_addr = "0.0.0.0"

auth_tcp = "none"

运行 libvirtd

service libvirtd restart

如果没起效果(我的就没有生效 :( ),那么使用命令行:

libvirtd --daemon --listen --config /etc/libvirt/libvirtd.conf

查看运行进程

[root@ddd run]# ps aux | grep libvirtd
root 16563 1.5 0.1 925880 7056 ? Sl 16:01 0:28 libvirtd -d -l --config /etc/libvirt/libvirtd.conf

查看端口

[root@ddd run]# netstat -apn | grep tcp
tcp        0      0 0.0.0.0:16509           0.0.0.0:*               LISTEN      13971/libvirtd      

在source host连接dest host远程libvirtd查看信息

virsh -c qemu+tcp://211.87.***.97/system

Welcome to virsh, the virtualization interactive terminal.

Type: 'help' for help with commands
'quit' to quit

成功使用tcp去访问libvirtd。

分类: 虚拟化

使用libvirt和qemu将pci pass through设备添加到虚拟机上

透传的优势

guest使用透传设备可以获得设备近乎原生的性能,

PCI pass-throught设备给动态迁移带来的问题, dest host可能没有同样的硬件.

就算可以模拟一个设备,但是原始设备的内部状态不能获得.

VT-d support

In order to assign devices in KVM, you’ll need a system which supports VT-d. This has nothing to do with the VT-x support of your CPU, VT-d needs to be supported by both your chipset on your motherboard and by your CPU.

If you are in doubt whether your motherboard or CPU supports VT-d or not, the Xen VT-d wikipage has some pointers of VT-d enabled chipsets, motherboards and CPUs: http://wiki.xensource.com/xenwiki/VTdHowTo

If your hardware doesn’t have an IOMMU (“Intel VT-d” support in case of Intel – “AMD I/O Virtualization Technology” support in case of AMD), you’ll not be able to assign devices in KVM. Some work towards allowing this were done, but the code never made it into KVM, due to various issues with the code. At the moment it doesn’t seem like device assignment without hardware support, will ever be integrated into KVM.

Assignment of graphics cards are not officially supported at the moment, but there has been some success passing through a secondary Radeon HD 5850 as a VM’s secondary display.

资料:http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM

在host选择PCI pass through设备

reboot and verify that your system has IOMMU support

AMD Machine

dmesg | grep AMD-Vi
 ...
 AMD-Vi: Enabling IOMMU at 0000:00:00.2 cap 0x40
 AMD-Vi: Lazy IO/TLB flushing enabled
 AMD-Vi: Initialized for Passthrough Mode
 ...

Intel Machine

dmesg | grep -e DMAR -e IOMMU
...
DMAR:DRHD base: 0x000000feb03000 flags: 0x0
IOMMU feb03000: ver 1:0 cap c9008020e30260 ecap 1000
...

If you get no output you’ll need to fix this before moving on. Check if your hardware supports VT-d and check that it has been enabled in BIOS.

NOTE: If you still get an error “No IOMMU found.” Check dmesg for errors suggesting your BIOS is broken. Another possible reason: CONFIG_DMAR_DEFAULT_ON is not set. In that case, pass “intel_iommu=on” as kernel parameter to enable it. AMD uses different kernel parameter than Intel, on AMD you need to pass “iommu=pt iommu=1”.

请看附录:No IOMMU found 解决

选择要使用的透传设备

# lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation 2nd Generation Core Processor Family DRAM Controller [8086:0100] (rev 09)
......
00:1b.0 Audio device [0403]: Intel Corporation 6 Series/C200 Series Chipset Family High Definition Audio Controller [8086:1c20] (rev 04)
.....
00:1f.3 SMBus [0c05]: Intel Corporation 6 Series/C200 Series Chipset Family SMBus Controller [8086:1c22] (rev 04)

友情提示:使用透传设备时,拿USB控制器作实验,可能鼠标键盘不能使用.请谨慎.

将设备从宿主机上解除绑定

使用echo命令,将设备从host机器上解除绑定,将来用于guest机器. For example:

echo "8086 1c20" > /sys/bus/pci/drivers/pci-stub/new_id
echo 0000:00:1b.0 > /sys/bus/pci/devices/0000:00:1b.0/driver/unbind
echo 0000:00:1b.0 > /sys/bus/pci/drivers/pci-stub/bind

关闭虚拟机

关闭虚拟机,修改配置文件.

使用libvirt进行pci pass through

修改虚拟机配置文件

<devices> …
    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
         <address domain='0x000' bus='0x00′ slot='0x1b' function='0x0' />
      </source>
   </hostdev>
</devices>

在修改完虚拟机配置文件后,运行虚拟机.

使用qemu进行pci pass through

使用qemu进行pci pass through也是一样的简单的.我们需要一个已经创建好操作系统的虚拟机.

在qemu命令行运行以下命令以启动虚拟机

/usr/bin/qemu-kvm -name vdisk -enable-kvm -m 512 -smp 2 \
-hda /mnt/nfs/vdisk.img \
-monitor stdio \
-vnc 0.0.0.0:0 \
-device pci-assign,host=00:1b.0

这样就将设备挂载到虚拟机上了.

  • 参数-device pci-assign,host=00:1b.0说的是使用一个pci设备,并提供一个设备的地址.
  • 参数-monitor stdio是使用一个标准的控制台输出.在命令行中进行输入命令,等等迁移的时候也在这里输入命令.

附录1:No IOMMU found 解决

启动虚拟机的时候出现了iommu的问题.以供大家参考

1.查看错误日志说明

在配置好XML文件后,启动虚拟机,遇到一个问题.

error: Failed to start domain vdisk
error: Unable to read from monitor: Connection reset by peer

查看虚拟机日志( cat /var/log/libvirt/qemu/vdisk.log )信息.

char device redirected to /dev/pts/3
No IOMMU found. Unable to assign device "hostdev0"
qemu-system-x86_64: -device pci-assign,configfd=20,host=00:1b.0,id=hostdev0,bus=pci.0,addr=0x4: Device 'pci-assign' could not be initialized
2013-07-08 06:41:23.256+0000: shutting down

上网查阅资料,说是要在BIOS上设置虚拟化,然后在引导程序里也要设置iommu.可以查看一下自己的电脑信息是否开启了.

2.查看信息gurb的引导信息

# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.9.6-200.fc18.x86_64 root=/dev/mapper/fedora-home ro rd.lvm.lv=fedora/swap rd.md=0 rd.dm=0 rd.lvm.lv=fedora/home rd.luks=0 vconsole.keymap=us rhgb quiet LANG=en_US.UTF-8

可以发现,我的还未开启intel_iommu=on选项.所以接下来我们来激活它.

3.激活intel_iommu=on

Activate Intel VT-d in the kernel

Activate Intel VT-d in the kernel by appending the intel_iommu=on parameter to the kernel line of the kernel line in the/boot/grub/grub.conf file. The example below is a modified grub.conf file with Intel VT-d activated.

对于intel的cpu和amd的cpu,在grub配置上是不同的,具体的配置请参考文章:http://pve.proxmox.com/wiki/Pci_passthrough

4.更新grub

在编辑完grub文件后,需要更新

grub2-mkconfig   # fedora arch centos
update-grub            # ubuntu debian

5.重启电脑,使其生效

# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.9.6-200.fc18.x86_64 root=/dev/mapper/fedora-home ro rd.lvm.lv=fedora/swap rd.md=0 rd.dm=0 rd.lvm.lv=fedora/home rd.luks=0 vconsole.keymap=us rhgb quiet intel_iommu=on LANG=en_US.UTF-8

发现开机已经启动了inte _iommu=on了.再次启动虚拟机已经就不会出现这个bug了.

附录2 PCI pass through 失败要关闭SELinux

我用的是Fedora 18 ,将SELinux给disalbed了,但是发现PCI pass through出先问题.上网看到文章PCI passthrough fails in qemu-kvm unless selinux is disabled 说,要将selinux设置成permissive模式,于是这个问题解决了.

参考资料

分类: 虚拟化

qemu安装kvm虚拟机

用qemu命令来创建虚拟机.

第一步,创建一个虚拟机的硬盘,将来来存放虚拟操作系统的.这个虚拟硬盘是利用文件系统来进行模拟的.

qemu-img create -f qcow2 vdisk.img 10G 

qcow2是一种硬盘的格式,比qcow更新,qcow2 is an updated version of the qcow format, intended to supersede it. The main difference with the original is that qcow2 supports multiple virtual machine snapshots through a new, flexible model for storing snapshots. qcow支持数据大小动态的增加.而不是一开始就固定大小了.直接分配那么大的位置占空间

第二步,安装iso,并运行

qemu-system-x86_64 -enable-kvm -m 512 -smp 1 -boot order=dc -hda /opt/vdisk.img -cdrom /home/d/Downloads/CentOS-6.4-x86_64-minimal.iso

其中,-enable-kvm 是使用kvm内核,不用qemu的内核,开启虚拟机加速, -m 2048 是给客户机分配512MB内存,-smp 1 是给客户机分配1个CPU,-boot order=dc 是指定系统的启动顺序为光驱(d: CD-ROM)、硬盘(c: hard Disk),-hda ** 是分配给客户机的IDE硬盘(即前面准备的镜像文件),-cdrom ** 是分配客户机的光驱。默认情况下,QEMU会启动一个VNC server端口(如上面的::1:5900),可以用vncviwer工具来连接到QEMU的VNC端口查看客户机。

出现

VNC server running on `127.0.0.1:5900'

这意味着,你的虚拟机已经开启了,并且,开通了一个端口给你,你可以利用5900端口去远程桌面连接.有个图片

接下来就是普通的安装操作系统了.在安装结束后,我们需要进行重启,可能就出现问题了.这是将原先的虚拟机ctrl+c强制结束了.然后再次运行虚拟机

第三步,运行刚刚安装的操作系统

# qemu-system-x86_64 vdisk.img -m 512 -enable-kvm

If you’re on Fedora/RHEL/CentOS (and installed a kvm package and not built kvm yourself from source) then substitute qemu-kvm for qemu-system-x86_64

查看进程的一些xinxi ps -eLo ruser,pid,ppid,lwp,psr,args | grep qemu

参考: qcow2、raw、vmdk等镜像格式 http://www.prajnagarden.com/?p=248

运行刚刚安装的操作系统 http://www.linux-kvm.org/page/HOWTO1#Running_the_newly-installed_guest

分类: 虚拟化

qemu命令行参数转libvirt的xml文件

运行虚拟机有多种方式,其中可以使用qemu-system-x86或者qemu-kvm来运行虚拟。另外还可以使用libvirt的virsh命令从xml文件定义来运行虚拟机。而网上许多的教程或者示例使用qemu命令参数来运行的,如果使用libvirt来运行可能会无从下手,不知道对应的参数。

libvirt从Domain的配置文件启动虚拟机

虚拟机(有时Domain,guest都表示虚拟机的含义。)可以通过Domain xml文件来进行配置虚拟机。以下是一个demo的配置文件。

<domain type='qemu'>
  <name>QEmu-fedora-i686</name>
  <uuid>c7a5fdbd-cdaf-9455-926a-d65c16db1809</uuid>
  <memory>219200</memory>
  <currentMemory>219200</currentMemory>
  <vcpu>2</vcpu>
  <os>
    <type arch='i686' machine='pc'>hvm</type>
    <boot dev='cdrom'/>
  </os>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='file' device='cdrom'>
      <source file='/home/user/boot.iso'/>
      <target dev='hdc'/>
      <readonly/>
    </disk>
    <disk type='file' device='disk'>
      <source file='/home/user/fedora.img'/>
      
<target dev='hda'/>
    </disk>
    <interface type='network'>
      <source network='default'/>
    </interface>
    <graphics type='vnc' port='-1'/>
  </devices>
</domain>

然后使用以下命令从xml文件导入到libvirt虚拟机管理软件中。

virsh define demo.xml

启动虚拟机。其中QEmu-fedora-i686为xml定义的虚拟机别名。

virsh start QEmu-fedora-i686

使用qemu命令行启动虚拟机

也可以使用qemu命令行启动虚拟机,但是每次都要输入那么长的参数会忘记,所以也可以写个shell脚本来保存参数。类似的,qemu启动虚拟机使用如下命令:

/usr/bin/qemu-system-x86_64 --enable-kvm \
  -m 1024 \
  -smp 1 \
  -name QEMUGuest1 \
  -nographic \
  -monitor pty -no-acpi -boot c \
  -drive  file=/dev/HostVG/QEMUGuest1,if=ide,index=0 \
  -net none \
  -serial none -parallel none -usb

看到这样长的参数,输入起来当然麻烦了。而且这样运行虚拟机libvirt还没办法直接查询虚拟机的状态。

在xml文件里使用任意qemu命令行参数

有些命令行的参数可以使用xml直接定义出来,但是有些并不能找到对应的xml的标签。但是libvrit为我们提供了一个qemu:commandline来配置xml文件。

例如:

<domain type='qemu' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  <name>QEmu-fedora-i686</name>
  <memory>219200</memory>
  <os>
    <type arch='i686' machine='pc'>hvm</type>
  </os>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
  </devices>
  <qemu:commandline>
    <qemu:arg value='-newarg'/>
    <qemu:env name='QEMU_ENV' value='VAL'/>
  </qemu:commandline>
</domain>

Libvirt提供一个XML命名空间和可选类库libvirt-qemu.so来解决qemu的一些特殊情况。当被正确使用时,这些扩展允许测试还没被libvirt的XML和API接口支持qemu的特性。然而,他们是不被支持的,因为该类库不能保证有一个稳定的API接口,滥用这些类库或者xml文件会导致不一致的状态使libvirtd奔溃,升级qemu-kvmlibvirtd会对那么依赖使用qemu特性的虚拟机有破坏性行为。如果你确信需要获得的qemu的特性,请发送RFE给libvirt的mailing list以得到纳入该功能的稳定的libvirt XML和API接口。

这些类库提供两个API:virDomainQemuMonitorCommand,用来发送任意监控命令(monitor command, 包括HMP和QMP格式)给qemu虚拟机 (Since 0.8.3);virDomainQemuAttach用来注册一个人工启动的qemu虚拟机,这样可以使用libvirtd来管理(Since 0.9.4)。

当启动虚拟机的时候,以下的XML扩展允许给qemu命令行参数。为了使用XML扩展,需要增加一个XML namespacehttp://libvirt.org/schemas/domain/qemu/1.0。一般给这namespace取名为qemu,需要增加一个元素<qemu:commandline>,还有两个子元素:

qemu:arg 当启动虚拟机的时候,向qemu进行提供一个命令行参数,将参数放在XML的value属性里。

qemu:env当启动虚拟机的时候,向qemu进行提供一个环境变量, 将 name-value对 放在name属性和可选的vlaue属性里。

将QEMU参数转domain XML配置

命令virsh domxml-from-native提供一个方法将已存在的一组QEMU参数转成可以被libvirt使用Domain XML文件。这个命令的目的用于将先前已经能够从命令行运行的虚拟机转化为用libvirt去管理的XML配置文件。请不要用它来创建一个新虚拟机。新的虚拟机应该由调用libvirt API的程序去创建,或者手工编写XML文件让virsh运行。

需要特别注意的是,在demo.args文件中,不能有换行出现,整个命令要在同一行里。

$ cat > demo.args <<EOF
LC_ALL=C PATH=/bin HOME=/home/test USER=test \
LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 \
-nographic -monitor pty -no-acpi -boot c -hda \
/dev/HostVG/QEMUGuest1 -net none -serial none \
-parallel none -usb
EOF

$ virsh domxml-from-native qemu-argv demo.args
<domain type='qemu'>
  <uuid>00000000-0000-0000-0000-000000000000</uuid>
  <memory>219136</memory>
  <currentMemory>219136</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch='i686' machine='pc'>hvm</type>
    <boot dev='hd'/>
  </os>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <devices>
    <emulator>/usr/bin/qemu</emulator>
    <disk type='block' device='disk'>
      <source dev='/dev/HostVG/QEMUGuest1'/>
      <target dev='hda' bus='ide'/>
    </disk>
  </devices>
</domain>

转化domain XML为QEMU参数

命令virsh domain-to-natice可以将libvirt的Domian XML文件转化成一组QEMU参数。

$ cat > demo.xml <<EOF
<domain type='qemu'>
  <name>QEMUGuest1</name>
  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
  <memory>219200</memory>
  <currentMemory>219200</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch='i686' machine='pc'>hvm</type>
    <boot dev='hd'/>
  </os>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <devices>
    <emulator>/usr/bin/qemu</emulator>
    <disk type='block' device='disk'>
      <source dev='/dev/HostVG/QEMUGuest1'/>
      <target dev='hda' bus='ide'/>
    </disk>
  </devices>
</domain>
EOF

$ virsh domxml-to-native qemu-argv demo.xml
  LC_ALL=C PATH=/usr/bin:/bin HOME=/home/test \
  USER=test LOGNAME=test /usr/bin/qemu -S -M pc \
  -no-kqemu -m 214 -smp 1 -name QEMUGuest1 -nographic \
  -monitor pty -no-acpi -boot c -drive \
  file=/dev/HostVG/QEMUGuest1,if=ide,index=0 -net none \
  -serial none -parallel none -usb

参考资料

分类: 虚拟化

较早的文章

Copyright © 2017 东东东 陈煜东的博客 粤ICP备13059639号-1

SITEMAP回到顶部 ↑