经过这几天来的折腾,总算是在ubuntu14.04用kvm装上了xp, 看不少的的贴,也绕了不少的圈,总的来说,非常感谢
CSDN上的"上善若水75",看着他写的一个分类"QEMU-KVM"
本文大部分参考自
http://blog.csdn.net/hbsong75/article/category/1469881/2
从他走过的路上一点点去实现在ubuntu14.04 desktop(32bit)实现kvm装个XP,
为什么要装这个?
因为工作上的各种原因吧
工作上: 如同事给M$的doc, xls等,还是用ms office 打开会好一点,虽然永中在这方面也已经做得很不错了.
生活上: 我也有时要用到网银,可是招行的专业版好像还不好用ubuntu去做吧所以……
OK,正如上善若水75所说的,他这个实验的最终结果为:
1. 在主机上创建、启动windows虚拟机;
2. 客户机可以通过spice-gtk或RDP连接到虚拟机;
3. USB外设可以通过重定向的方式进入虚拟机进行使用。
好像正如我这边的期望值差不多,因此就继续下去了,
用于实验的主机必须是支持虚拟化的,可以用下面的命令来检验:
cat /proc/cpuinfo | grep vmx 或 cat /proc/cpuinfo |grep svm
试了一下,我这边这台老的T60居然还支持,真是万幸。
再 在主机的BIOS需开启虚拟化支持,一般在“Advanced”菜单项下->”Virtualization”是否是Enabled
在查看了一系列的资料后发现,这个配置的T60CPU是不支持64位的,这时又感到有点失望.
总之一系列的包,我是通过系统自带的apt-get来获得的,虽然网上指导说用手编译,但是我有时有点懒....
现在列出一下有哪些包是可以直接apt-get出来的吧.(如遇到有点差别请自行用
Apt-cache search来进行调整.
autotools-dev doxygen pkg-config devscriptslibusb-dev
另外,spice必须要自行编译,,,好像如果用系统源那个也有qemu-system-spice,但很多参数不兼容,
而./configure 的时候,不需要过多理会usbredirect
我们可以在随后的配置中进行修改.
make
sudo make install
之后,进行会出现spice的gtk版本叫spicy
接着?接着要get一大堆的库,
sudo apt-get install device-tree-compiler texi2html texinfo libaio-dev libattr1-dev libbluetooth-dev libbrlapi-dev libcap-dev libcap-ng-dev libcurl4-gnutls-dev libfdt-dev libgnutls-dev libncurses5-dev libpulse-dev libsdl1.2-dev libseccomp-dev libxen-dev uuid-dev xfslibs-dev librados-dev librbd-dev
其实这么多东西,无非就是两个为主qemu-kvm这个用qemu作为一个接口,去直接控制kvm,,,,,当然qemu也是有很多分支的,如qemu-arm等.
再者是libvir,
这货是用来管理虚拟机,,通过平时我们去编辑相应的xml文件即可.
qemu出来后,我们就可以开始了.
先创建镜像.
dev@xxx:~/vm$ sudo qemu-img create –f qcow2 xp.img 20G
dev@xxx:~/vm$ sudo qemu-img create –f qcow2 data.img 50G
这样我们就创建了对应虚拟机的系统盘xp.img和对应数据盘的 data.img。
目前为止,这两个盘还只是空的盘,里面除了基本的磁盘信息之外空空如也,实际大小也只有197M,这也是qcow2格式的特点(有关qcow2的介绍请参考https://people.gnome.org/~markmc/qcow-image-format.html)。
这里我还必须补充说明一下,如果后期用到virtio时,好像要用到关于raw格式的,也就是把上面的qcow2换成raw
这样我们就创建了对应虚拟机的系统盘xp.img和对应数据盘的 data.img。
目前为止,这两个盘还只是空的盘,里面除了基本的磁盘信息之外空空如也,实际大小也只有197M,这也是qcow2格式的特点(有关qcow2的介绍请参考https://people.gnome.org/~markmc/qcow-image-format.html)。
二.创建虚拟机
创建虚拟机就是将我们所需要的操作系统(如xp)安装到步骤一创建的镜像文件里。我们用到的命令是qemu-system-x86_64,它当然是qemu最核心的一个系统命令。为方便起见,我们从一个ISO文件安装,因此先将操作系统的ISO文件上传至主机。然后执行下面的命令:
dev@xxx:~/vm$ sudo qemu-system-x86_64 –hda xp.img –hdb data.img –cdrom windows_xp_professional_sp3_x86.iso –boot d --enable-kvm
下面就是熟悉的XP安装界面了。
稍微解释一下 qemu-system-x86_64–hda xp.img –hdb data.img –cdrom windows_xp_professional_sp3_x86.iso –boot d --enable-kvm
–hda xp.img:代表第一个硬盘,我们用来装XP系统,在虚拟机里即为C盘;
-hdb data.img:代表第二个硬盘,我们用来放数据,在虚拟机里即为D盘;
–cdrom windows_xp_professional_sp3_x86.iso:光驱,我们放了XP安装ISO;
–boot d:表示用光驱启动,如果用硬盘启动就是–boot c
--enable-kvm:启用KVM硬件虚拟化,加快虚拟机运行速度。
上面只是qemu-system-x86_64很少的一部分参数,包括网络、显示和各类扩展参数都没有包括,可以用qemu-system-x86_64 –help查看所有的参数。
当然,上述手工使用的方式不方便,仅作为体验使用,下一步我们通过libvirt来管理它。
Libvirt 是用c写的一个管理虚拟机及其资源(如网络、存储和外设等)的工具库,它不仅支持KVM/QEMU,它还支持xen,Vmware,OpenVZ和VirtualBox等其他HyperVisor,关于它的详细信息参考http://www.libvirt.org/。
在安装libvirt之前,需要安装几个依赖包:
dev@xxx:~/workroom/ libvirt /libvirt_1.0.2$ sudo apt-get install bridge-utils cgroup-lite cgroup-bin
一般也是通过sudo apt-get install libvirt来获得 libvirt
安装完后检查是否成功可以用virsh命令,virsh 是libvirt带的一个命令行工具,命令如下:
dev@xxx:~/workroom/ libvirt $ sudo virsh list
Id Name State
-------------------------------------------------------------
出现上述的命令就表示安装成功了。
可以用 sudo virsh help 查看所有 virsh 能做的事情,非常丰富!
Libvirt 其实并没有太多“实质”的东西,它所做的大部分都是要通过Hypervisor(如KVM-Qemu,XEN等)来实现的,它本质上就是一个适配器和管理库。但是它又是非常有价值的,它一方面封装了不同Hypervisor的底层不同实现,提供了统一的使用接口给上层应用,另一方面它通过规范的XML定义、命令行工具和API使得我们对虚拟机的使用和管理变得更方便。Libvirt 其实并没有太多“实质”的东西,它所做的大部分都是要通过Hypervisor(如KVM-Qemu,XEN等)来实现的,它本质上就是一个适配器和管理库。但是它又是非常有价值的,它一方面封装了不同Hypervisor的底层不同实现,提供了统一的使用接口给上层应用,另一方面它通过规范的XML定义、命令行工具和API使得我们对虚拟机的使用和管理变得更方便。
今天我们用libvirt 来创建、启动和关闭虚拟机,看看这个过程一般是怎么样的。
一.创建虚拟机
1. 语法: virsh define <file>
<file> 是XML格式的文件,一般格式如下:
<domain type='kvm'>
<name>XP_VM</name>
<uuid>91f15b08-e115-4016-a522-b550ff593af9</uuid>
<memory>1024000</memory>
<currentMemory>1024000</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='cdrom'/>
<boot dev='hd'/>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets='1' cores='1' threads='1'/>
</cpu>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xp_c.img' lock='exclusive'/>
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xp_d.img' lock='exclusive'/>
<target dev='hdb' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/opt/vm/windows_xp_professional_sp3_x86.iso'/>
<target dev='hdc'/>
<readonly/>
</disk>
<interface type='bridge'>
<mac address='52:54:00:7b:a8:d8'/>
<source bridge='virbr0'/>
</interface>
<input type='tablet' bus='usb'/>
<graphics type='spice' port='4000' autoport='no' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
<agent_mouse mode='off'/>
</graphics>
<sound model='ac97'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='qxl' vram='65536' heads='1'/>
</video>
</devices>
<qemu:commandline>
<qemu:arg value="-cpu"/>
<qemu:arg value="kvm64"/>
</qemu:commandline>
</domain>
我们把上述XML定义为 xp.xml。对没接触过虚拟化的朋友来说内容有点多,感兴趣的话不妨参考http://www.libvirt.org/formatdomain.html的详细说明。
2. 创建磁盘(我们在/opt/vm下创建虚拟机镜像文件)
dev@xxx:~/opt/vm$ sudo qemu-img create –f qcow2 xp_c.img 10G
dev@xxx:~/opt/vm$ sudo qemu-img create –f qcow2 xp_d.img 100G
注:如果没有创建磁盘,那么在执行 virsh define xp.xml的时候虽然不会报错,但是在启动该虚拟机的时候就会报找不到镜像文件的错误。
另外注意把windows_xp_professional_sp3_x86.iso这个XP的安装文件也放到该目录下,否则也会启动不了。
3. 执行下面的命令定义虚拟机
dev@xxx:~/opt/vm$ sudo virsh define xp.xml
Domain XP_VM defined from xp.xml
XP_VM是我们在xp.xml为这个虚拟机起的名字。
4. 启动虚拟机
dev@xxx:~/opt/vm$ sudo virsh start XP_VM
Domain XP_VM started
检查一下:
dev@xxx:~/opt/vm$ sudo virsh list
5. 用spice连接
到目前为止,VM已经创建而且已经在运行,可是我们怎么没看到呢?
对了,要用一个客户端工具连上去,我们用spice。还记得在Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(五)中编译的spice吗,编译安装完以后spice客户端也相应生成了,它在目录/usr/bin/spicec下
我们用下面的命令来连接这个虚拟机:
dev@xxx:~/opt/vm$ sudo spicec –h 127.0.0.1 –p 4000
注:-p 4000,4000是端口号,参看XML<graphics>一节的定义。
接下来就把虚拟机操作系统安装完吧……
正常安装完系统以后,关机!
把XML中启动顺序换一下,否则每次都要从光盘启动了:
<boot dev='hd'/>
<boot dev='cdrom'/>
修改完XML需要 virsh undefine XP_VM, virsh define xp.xml使新的配置生效。
二.启动虚拟机
接下来要启动虚拟机,就:
dev@xxx:~/opt/vm$ sudo virsh start XP_VM
然后spice连上去用:
dev@xxx:~/opt/vm$ sudo spicec –h 127.0.0.1 –p 4000
三.关闭虚拟机
关闭虚拟机可以选择在操作系统里直接关机或:
dev@xxx:~/opt/vm$ sudo virsh shutdown XP_VM
如果正常关不掉就:
dev@xxx:~/opt/vm$ sudo virsh destroy XP_VM
到目前为止,我们还是使用了最基本的libvirt参数来创建和使用虚拟机,以后我们在尝试使用更高级的一些功能。
在Ubuntu12.10下搭建基于KVM-QEMU的虚拟机环境(九)中我们用libvirt定义创建、启动和使用了基本的虚拟机过程。今天开始我们通过对XML的更多tag的改变来尝试更多新的功能。
今天要实验的是virtio 的功能,有关virtio的介绍参阅:http://www.linux-kvm.org/page/Virtio 和http://www.ibm.com/developerworks/cn/linux/l-virtio/
采用virtio的目的是提高虚拟机的性能,KVM在I/O虚拟化方面,传统的方式是使用QEMU纯软件的方式来模拟I/O设备(模拟的网卡、磁盘、显卡等等),其效率并不非常高。在KVM中,可以在客户机中使用半虚拟化驱动(Paravirtualized Drivers,PV Drivers)来提高客户机的性能(特别是I/O性能)。目前,KVM中实现半虚拟化驱动的方式是采用了virtio这个Linux上的设备驱动标准框架。
在未采用virtio之前,我们的磁盘是模拟的”ide”格式,XML的定义是:
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xp_c.img' lock='exclusive'/>
<target dev='hda' bus='ide'/>
</disk>
在装完系统以后,如下图红色字体所示,是“QEMU HARDDISK”
现在我们对XML做如下修改,主要修改部分标记为红色:
<domain type='kvm'>
<name>XP_VM2</name>
<uuid>91f15b08-e115-4016-a522-b550ff593af8</uuid>
<memory>1024000</memory>
<currentMemory>1024000</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='cdrom'/>
<boot dev='hd'/>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets='1' cores='1' threads='1'/>
</cpu>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/opt/vm/xpvm_virtio/xp_c.img' lock='exclusive'/>
<target dev='hda' bus='virtio'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xpvm_virtio/xp_d.img' lock='exclusive'/>
<target dev='hdb' bus='virtio'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/opt/vm/windows_xp_professional_sp3_x86.iso'/>
<target dev='hdc'/>
<readonly/>
</disk>
<disk type='file' device='floppy'>
<source file='/opt/vm/virtio-WinXP-x86.vfd'/>
<target dev='fda' bus='fdc'/>
<readonly/>
</disk>
<interface type='bridge'>
<mac address='52:54:00:7b:a8:d8'/>
<source bridge='virbr0'/>
<target dev='vnet1'/>
</interface>
<input type='tablet' bus='usb'/>
<graphics type='spice' port='4000' autoport='no' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
<agent_mouse mode='off'/>
</graphics>
<sound model='ac97'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='qxl' vram='65536' heads='1'/>
</video>
</devices>
<qemu:commandline>
<qemu:arg value="-cpu"/>
<qemu:arg value="qemu64,model=3"/>
</qemu:commandline>
</domain>
也就是对磁盘、网络和内存等主要有关IO的设备采用virtio的方式。
在重新安装虚拟机系统之前,从https://www.linuxwind.org/virtio下载最新的virtio的软盘文件(virtio-WinXP-x86.vfd),在装系统的时候就会弹出提示需要安装上这些虚拟磁盘驱动,默认选上就可以了。
做好准备以后重新安装操作系统后,再查看
这时候发现磁盘驱动器已经变成了“Red Hat VirtIO SCSI Disk Device”,这意味着virtio磁盘驱动已经装上了!
下一篇将介绍如何安装虚拟网卡驱动和虚拟显卡驱动等内容。
上一个介绍主要讲了如何virtio驱动对于虚拟机性能改善的重要性以及如何安装针对磁盘的虚拟驱动,接下来我们继续安装其他几个虚拟驱动:QXL虚拟显卡、虚拟网卡、虚拟串口和改善显示和鼠标体验的vdagent程序。在继续之前我们先还是有针对性的修改定义虚拟机的XML定义文件,参阅红色字体部分:
<domain type='kvm'>
<name>XP_VM2</name>
<uuid>91f15b08-e115-4016-a522-b550ff593af8</uuid>
<memory>1024000</memory>
<currentMemory>1024000</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='cdrom'/>
<boot dev='hd'/>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets='1' cores='1' threads='1'/>
</cpu>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/opt/vm/xpvm_virtio/xp_c.img' lock='exclusive'/>
<target dev='hda' bus='virtio'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xpvm_virtio/xp_d.img' lock='exclusive'/>
<target dev='hdb' bus='virtio'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/opt/vm/windows_xp_professional_sp3_x86.iso'/>
<target dev='hdc'/>
<readonly/>
</disk>
<disk type='file' device='floppy'>
<source file='/opt/vm/virtio-WinXP-x86.vfd'/>
<target dev='fda' bus='fdc'/>
<readonly/>
</disk>
<interface type='bridge'>
<mac address='52:54:00:7b:a8:d8'/>
<source bridge='virbr0'/>
<target dev='vnet1'/>
<model type='virtio'/>
</interface>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<alias name='virserial-channel1'/>
</channel>
<input type='tablet' bus='usb'/>
<graphics type='spice' port='4000' autoport='no' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
<agent_mouse mode='off'/>
</graphics>
<sound model='ac97'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='qxl' vram='65536' heads='1'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
</memballoon>
</devices>
<qemu:commandline>
<qemu:arg value="-cpu"/>
<qemu:arg value="qemu64,model=3"/>
</qemu:commandline>
</domain>
挑出来就是下面一段:
<channeltype='spicevmc'>
<targettype='virtio' name='com.redhat.spice.0'/>
<aliasname='virserial-channel1'/>
</channel>
有关spicevmc的说明如下(http://www.libvirt.org/formatdomain.html):
Paravirtualized SPICE channel. The domainmust also have a SPICE server as a graphicsdevice, at which point the host piggy-backs messages across the main channel. The target element must be present, withattributetype='virtio'; an optional attribute namecontrols how the guest will have access to the channel, and defaults toname='com.redhat.spice.0'. The optional address element can tie thechannel to a particular type='virtio-serial'controller.
简单的说是一个虚拟串口通道,用于优化主机和虚拟机之间的一些通信。
在修改了XML后,需要通过重新执行下面的命令来让其生效:
sudo virsh undefine XP_VM2
sudo virsh define xp.xml
然后再启动虚拟机:sudo virsh start XP_VM2
启动完成后当然还是通过spice连接上去: spicec –h 127.0.0.1 –p 4000:
启动完后你会发现在虚拟机的设备管理器上会出现一些未知设备,那是因为在更新了XML定义后系统发现了一些硬件上的改动。为了让系统识别这些设备,我们需要为其装上驱动,下载这些驱动的路径是:http://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-0.74.exe
这个exe里面就包含了完整的虚拟显卡驱动、虚拟网卡驱动和虚拟串口驱动,而且针对windows各个版本的都有(也包括32位和64位)。
下载以后执行这个EXE程序:
中间会有些警告信息,那是因为没有数字证书,没关系,选择安装就是。
其中如果重启完虚拟机后,发现网卡不能正常地识别的话,那么请在硬件管理器中查找应用,再把驱动的位置定位到软盘A 中去.那么网卡一般都可找到,
安装完以后再看一下设备管理器,发现那些原来带黄色问号的设备纷纷被识别出来了,原来它们就是虚拟网卡、虚拟串口和虚拟显卡,参考下图:
同时在服务列表中可以看到增加了一个叫RHEV Spice Agent的服务:
这个服务就是所谓的vdagent,它主要起到下面几个作用:
1. 在虚拟机和本地系统间拷贝、粘贴文本;
2. 在全屏模式下让虚拟机自适应本地系统的分辨率;
3. 改善在虚拟机里面的鼠标使用体验等。
这个vdagent运行的LOG缺省在 C:\windows\temp 目录下,如果有什么问题可以去看看。
Libvirt除了在虚拟机的定义文件中可以初始挂载光驱之外,还有一种动态换盘挂载的方式,那就是采用 virsh命令中的attach-device命令,该命令的具体格式如下:
dev@devhost:/opt/vm/xpvm1$ sudo virsh attach-device <domain-name> filename
其中,filename是一个用XML格式定义的文件(我们把它命名为disk.xml):
<disk type=”file” device=”cdrom”>
<source file=”/opt/vm/drivers.iso”/>
<target dev=”hdc”/>
<readonly/>
</disk>
最初虚拟机挂的光盘是windows_xp_professional_sp3_x86.iso:
<domain type='kvm'>
<name>XP_VM</name>
<uuid>91f15b08-e115-4016-a522-b550ff593af9</uuid>
<memory>1024000</memory>
<currentMemory>1024000</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
<boot dev='cdrom'/>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets='1' cores='1' threads='1'/>
</cpu>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xpvm1/xp_c.img' lock='exclusive'/>
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xpvm1/xp_d.img' lock='exclusive'/>
<target dev='hdb' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/opt/vm/windows_xp_professional_sp3_x86.iso'/>
<target dev='hdc'/>
<readonly/>
</disk>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<alias name='virserial-channel1'/>
</channel>
<interface type='bridge'>
<mac address='52:54:00:7b:a8:d8'/>
<source bridge='virbr0'/>
<target dev='vnet1'/>
<model type='virtio'/>
</interface>
<input type='tablet' bus='usb'/>
<graphics type='spice' port='4000' autoport='no' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
<agent_mouse mode='off'/>
</graphics>
<memballoon model='virtio'>
<alias name='balloon0'/>
</memballoon>
<sound model='ac97'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='qxl' vram='65536' heads='1'/>
</video>
</devices>
<qemu:commandline>
<qemu:arg value="-cpu"/>
<qemu:arg value="kvm64"/>
</qemu:commandline>
</domain>
装完系统后,在虚拟机里看到的是:
我们可以不重新关闭、定义新的光盘文件,而直接采用 virsh attach-device命令来更改光盘:
dev@devhost:/opt/vm/xpvm1$ sudo virsh attach-device XP_VM disk.xml
这样做的好处是在某些情况下我们可以做到类似热插拔光盘的效果而不用重启虚拟机。
注:需要说明的是,经过试验,首先必须在定义的XML里有个初始的光盘设备,否则执行attach-device 另一个光盘文件会失败:报的错误是: internal error No device with bus 'ide' and target 'hdc'.
也就是说这其实是一种换盘,而不是动态挂载,光驱设备本身必须在启动虚拟机之前必须在XML中定义。
一、快照类型
1) 磁盘快照
内部的:快照驻留在原来的镜像文件内部
外部的:快照以一个新的外部独立文件的形式存在,在此之后,原镜像变成只读,所有改变记录到快照文件里
磁盘快照由virsh snapshot-create命令创建
2) 内存快照
可以将虚拟机的内存信息记录到一个文件
由 virsh save 命令创建
3) 系统检查点
1) 和2)的结合,类似休眠的功能。
二、快照命令
Libvirt提供的Snapshot相关的命令有以下一些:
Snapshot-create
Snapshot-create-as
Snapshot-current
Snapshot-delete
Snapshot-dumpxml
Snapshot-edit
Snapshot-info
Snapshot-list
Snapshot-parent
Snapshot-revert
1. Snapshot-create
Libvirt既支持在虚拟机关闭的情况下打快照,也支持在虚拟机运行的情况下打快照。今天重点实验在虚拟机运行的情况下打快照的情况。
启动虚拟机(虚拟机域名是XP_VM)后,在virsh命令行下打一个snapshot的命令如下:
Virsh # snapshot-create XP_VM
这个命令执行的是对XP_VM这个虚拟机执行磁盘和内存的snapshot,时间比较长,一般要花费5-10分钟,不是太实用。一般做快照的目的是防止镜像损毁,更关注的是只对磁盘打快照,而且希望把快照放在一个单独的镜像文件里。这时候我们就要用到一种外部快照的概念,方法如下:
先禁用apparmor(否则做外部快照的时候会报Permission Denied),请参考链接:http://blog.csdn.net/hbsong75/article/details/9285753
其次定义一个snapshot-create 的XML文件:
<domainsnapshot>
<name>snap1</name>
<disk name='hda' snapshot='external'>
<driver type='qcow2'/>
</disk>
<disk name='hdb' snapshot='no'/>
</domainsnapshot>
上述定义说明为虚拟机的C盘(hda)做一个名字为<imageName>.snap1的外部快照;而D盘不需要做快照。该XML保存为domainsnapshot.xml
第三,执行下面的命令:
Virsh# snapshot-create XP_VM /opt/vm/xpvm1/domainsnapshot.xml –disk-only
只对磁盘做外部快照执行就非常快,几秒钟就完成。
第四,用snapshot-list命令检查快照列表:
Virsh# snapshot-list XP_VM
操作结果参考下图:
另外,也可以到虚拟机镜像文件目录查看,可以发现xp_c.snap1, xp_c.snap2等也生成出来了,xp_c.snap2就是当前快照镜像,而原来的镜像xp_c.img成为了xp_c.snap1的母镜像,它成为只读了。而当前运行的C盘镜像已经是xp_c.snap2了(可以用 virsh dumpxml XP_VM 检查看看现在的虚拟机定义中的disk是怎么样的!)。
今天我们继续试验snapshot的功能。
1. 启动虚拟机,在空的D盘上新建一个文本文档test.txt;
2. 定义创建snapshot的XML:
<domainsnapshot>
<name>snap1</name>
<disk name='hda' snapshot='external'>
<driver type='qcow2'/>
</disk>
<disk name='hdb' snapshot='external'>
<driver type='qcow2'/>
</disk>
</domainsnapshot>
也即定义了创建这个虚拟机的外部快照。
3. 执行创建外部快照的命令:
命令执行显示“snap1”的快照创建成功。
4. 查看快照创建情况:
用virshsnapshot-list 查看“snap1”快照已经创建,是个磁盘快照。
同时到虚拟机定义目录下可以看到 xp_c.snap1和 xp_d.snap1已经新生成出来。
目前虚拟机D盘里有个叫test.txt的文本文件,也即做这个快照时的D盘状态。到目前为止xp_d.img已经变成只读,之后所有的改变都会写入到xp_d.snap1里面。
5. 在D盘再创建一个文本文件:test2.txt
目前虚拟机里D盘的状态是有2个文本文档:test.txt和 test2.txt
6. 修改创建snapshot的XML:
<domainsnapshot>
<name>snap2</name>
<disk name='hda' snapshot='external'>
<driver type='qcow2'/>
</disk>
<disk name='hdb' snapshot='external'>
<driver type='qcow2'/>
</disk>
</domainsnapshot>
重新执行上述步骤3-4,我们发现snap2快照也被创建出来了。到目前为止xp_d.snap1已经变成只读,之后所有的改变都会写入到xp_d.snap2里面。
7. 现在我们来看一下snap2、snap1和原始镜像的关系:qemu-imginfo xp_d.snap2
可以看到 xp_d.snap2的 backingfile 是 xp_d.snap1,而 xp_d.snap1的 backing file是 xp_d.img。也就是说,当打快照的时候,原来的镜像文件就成为快照镜像的parent,总的快照路径上是单向的继承的关系:
xp_d.img ——> xp_d.snap1 ——> xp_d.snap2 …….
这种快照关系如果能够很好的组织维护,那么就能起到一个很好的类似备份的效果,因为打快照的时候一般都是在系统完好的时候,如果在打完快照又做了一些系统改变(如装了一个新的软件)导致系统损坏,那么可以通过还原到之前的快照点来恢复系统。假设我们往D盘放了一个带病毒的test3.exe:
用了一会发现系统越来越慢,我们决定恢复到snap1的快照去,该怎么做呢?
8. 系统还原到快照1:virshsnapshot-revert XP_VM3 snap1
可惜目前版本的libvirt还不支持对外部快照的还原,对内部快照还原已经实现。
这种情况下,我们只好采用一种变通的方式:
将snap1合并到parent:
经过这个合并后,快照1的变动合并到了母镜像中(不包括快照2以后的任何改变)。
然后重新定义一个以xp_c.img和xp_d.img的虚拟机,重新启动后,我们看到系统D盘里只有打快照2之前的test.txt和test2.txt,而不包括打快照2之后的test3.exe及其他改变,也就恢复到了一个“中病毒”之前的状态:
相信过一段时间支持外部快照恢复的libvirt版本也会完成,到时候就没那么麻烦了。
接下来我们试验虚拟机的网络配置功能,KVM虚拟机网络配置主要有两种方式:NAT方式和Bridge方式。今天我们主要理解和实验NAT方式的网络配置。
NAT方式是kvm安装后的默认方式,它支持主机与虚拟机的互访,同时也支持虚拟机访问互联网,但不支持外界访问虚拟机,因为NAT的全称是Network Address Translation(网络地址转换),即虚拟机和主机在一个特定的内部子网内,虚拟机的网络数据在经过物理机网络的时候进行ip伪装,这样所有虚拟机出去的网络数据都相当于是物理机出去的数据,也就是说,我们可以分配给使用nat网络的虚拟机一个内网ip,而这个内网ip的虚拟机访问出去的时候外部网络看到的是物理机的外网ip,这样做的用处就是实现多个虚拟机共享物理主机的外网ip,节省外网ip地址。
NAT的逻辑原理图如下:
上图中的“virbr0”就充当了一个虚拟网络交换机的作用,所有虚拟机要跟外界通信都先通过这个virbr0。那么virbr0是如何在主机上创建出来的呢?virbr0又如何起作用的?虚拟机如何使用virbr0作为其网络交换机?
1. virbr0的创建
libvirt默认使用了一个名为default的nat网络,这个网络默认使用virbr0作为桥接接口,使用dnsmasq来为使用nat网络的虚拟机提供dns及dhcp服务,dnsmasq生效后的配置文件默认保存在以下路径:
/var/lib/libvirt/dnsmasq/default.hostsfile mac&&ip绑定的配置文件
/var/lib/libvirt/dnsmasq/default.leases dhcp分配到虚拟机的ip地址列表
/var/lib/libvirt/network/default.xml default网络的配置文件
打开default.xml可以看到:
<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
virsh net-edit default
or other application using the libvirt API.
-->
<networkstatus>
<class_id bitmap='0-2'/>
<floor sum='0'/>
<network>
<name>default</name>
<uuid>cfbccd14-664c-4d02-91ef-ef3b1e168f61</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0' />
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254' />
</dhcp>
</ip>
</network>
从上面的配置里可以清楚的看到网络名称是“default”, 网桥名称是”virbr0”,forward模式是“nat”,虚拟机可以dhcp的地址范围等。
ifconfig可以看到:
Virbr0已经被成功的虚拟出来了。
2. virbr0如何工作
本质上说libvirt所实现的这种nat网络是通过物理机的iptables规则来实现的,也即是在虚拟机数据经过nat表的postrouting链出去的时候对其进行了伪装。
如下图所示:
# iptables –t nat –L –nv
该主机上的设置表明对source是192.168.122.0网段的所有数据包,如果destination不是192.168.122.0网段(即不是同一子网的虚拟机或主机),那么都用主机的IP地址进行伪装。这样当虚拟机访问外网的时候,外网只看到了主机的IP地址,而看不到虚拟机的实际内网地址。
3. 虚拟机如何配置virbr0
虚拟机的定义XML中的interface定义如下:
<interface type='bridge'>
<mac address='52:54:00:7b:a8:d8'/>
<source bridge='virbr0'/>
<target dev='vnet0'/>
<model type='virtio'/>
</interface>
上面的source bridge就指向了“virbr0”,虚拟机从dnsmasq获取到192.168.122.0网段的一个IP地址
启动虚拟机后,运行“ifconfig”, 可以看到有个叫vnet0的网络接口被创建出来,这就是该虚拟机的虚拟网络接口。
再运行“brctlshow”看看:
很清楚,这个虚拟机的vnet0网络接口是加入在virbr0这个虚拟网桥的,所以这个虚拟机的网络数据都需要这个virbr0转发。
最后来看一下,虚拟机里面的IP情况:
可以看到这个虚拟机的IP地址是192.168.122.10,网关、DHCP服务器地址和DNS服务器地址都是192.168.122.1,192.168.122.1又是什么呢?就是主机上这个virbr0的IP地址。
Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(十六)
分类: 云计算 QEMU-KVM2013-07-13 11:13 1377人阅读 评论(1) 收藏 举报
qemu-kvmBridge 虚拟机
今天我们继续实验Bridge方式的网络配置。
Bridge的逻辑原理图如下:
上图中的“br0”就充当了一个桥的作用,主机上的物理网口eth0等根据需要加入到这个桥里面,所有虚拟机要跟外界通信都通过这个br0, br0再经过真实的物理接口eth0等与外界通信。与NAT不同,桥接方式虚拟机跟主机一样能获得主机所在网络的IP地址,不再由主机进行伪装。那么br0是如何在Ubuntu主机上创建出来的呢?虚拟机如何使用br0?
1. br0的创建
在Ubuntu下br0的创建如下:
打开/etc/network/interfaces,做如下修改:
保存后,重启网络服务或重启机器。(上述配置的每个选项的具体含义不再详述,请查阅相关文档)
然后再检查主机网路:
可以看到,有一个网络接口br0被创建出来,它的IP地址是192.168.1.103,而原先的eth0没有IP地址了。
2. 虚拟机如何配置br0
虚拟机的定义XML中的interface定义如下:
<interface type='bridge'>
<mac address='52:54:00:7b:a8:d8'/>
<source bridge=’br0’/>
<target dev='vnet0'/>
<model type='virtio'/>
</interface>
上面的source bridge就指向了“br0”.
启动虚拟机后,运行“ifconfig”, 可以看到有个叫vnet0的网络接口被创建出来,这就是该虚拟机的虚拟网络接口。
再运行“brctlshow”看看:
很清楚,这个虚拟机的vnet0网络接口是加入到br0这个网桥了(原先NAT模式是在virbr0里),所以这个虚拟机的网络数据都改成由这个br0转发。
最后来看一下,虚拟机里面的IP情况:
可以看到这个虚拟机的IP地址是192.168.1.105,网关、DHCP服务器地址和DNS服务器地址都是192.168.1.1,192.168.1.1又是什么呢?它是我环境下的一台路由器(兼DNS、DHCP服务器和网关)。这跟上一篇NAT模式下它获得的是主机上的虚拟网桥的IP地址等已经完全不同了。
今天我们实验一些libvirt虚拟机XML定义文件中的配置参数。
<domain type='kvm'>
<name>XP_VM4</name>
<uuid>92f1ab08-e115-4016-a522-b550ff593af8</uuid>
<memory>1024000</memory>
<currentMemory>1024000</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='cdrom'/>
<boot dev='hd'/>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets='1' cores='1' threads='1'/>
</cpu>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xp_c.img' lock='exclusive'/>
<target dev='hda' bus='virtio'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/opt/vm/xp_d.img' lock='exclusive'/>
<target dev='hdb' bus='virtio'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/opt/vm/windows_xp_professional_sp3_x86.iso'/>
<target dev='hdc'/>
<readonly/>
</disk>
<disk type='file' device='floppy'>
<source file='/opt/vm/virtio-WinXP-x86.vfd'/>
<target dev='fda' bus='fdc'/>
<readonly/>
</disk>
<interface type='bridge'>
<mac address='52:54:00:7b:a8:d8'/>
<!-- <source bridge='virbr0'/> -->
<source bridge='br0'/>
<target dev='vnet0'/>
<model type='virtio'/>
</interface>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<alias name='virserial-channel1'/>
</channel>
<input type='tablet' bus='usb'/>
<graphics type='spice' port='4000' autoport='no' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
<agent_mouse mode='off'/>
</graphics>
<sound model='ac97'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='qxl' vram='65536' heads='1'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
</memballoon>
</devices>
<qemu:commandline>
<qemu:arg value="-cpu"/>
<qemu:arg value="qemu64,model=3"/>
</qemu:commandline>
</domain>
1. 内存配置:
修改 <memory>1024000</memory>缺省单位是KB。
如果要将虚拟机的内存改为2G,就是<memory>2048000</memory>
2. CPU配置:
修改 <vcpu>1</vcpu>和 <cpu><topology sockets='1' cores='1' threads='1'/></cpu>
如果要改成4个VCPU,可以这样:<vcpu>4</vcpu>和 <cpu><topology sockets='1' cores='2' threads='2'/></cpu>
3. 时间同步配置:
修改 <clock offset='localtime'/>
Localtime:表示虚拟机从本地主机同步时间:
如果要从外部时间服务器同步UTC时间,则改为:
<clock offset=’utc’/>
4. 启动问题:
<boot dev='cdrom'/>
<boot dev='hd'/> ————光驱位第一启动项,硬盘其次
<bootmenu enable='yes'/> ————有启动菜单选项,F12可以选择启动顺序
5. 电源控制:
<acpi/> ————虚拟机接收电源控制信号,可以用libvirt的shutdown命令优雅的关闭虚拟机操作系统
6. 虚拟机行为控制:
<on_poweroff>destroy</on_poweroff> ——虚机操作系统关机后释放资源
<on_reboot>restart</on_reboot> ——虚机操作系统要求重启后libvirt重启虚拟机
<on_crash>restart</on_crash> ——虚机操作系统崩溃后重启虚拟机
7. 鼠标模式
<input type='tablet' bus='usb'/> ——光标的绝对移动
<input type=’mouse’ bus='ps2'/> ——光标的相对移动
实际使用效果 tablet较好
未完待续…
· 上一篇Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(十六)
· 下一篇Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(十八)
到目前为止,我们用spice 客户端连接虚拟机的命令如下:
dev@devhost:/opt/vm# sudo spicec –h 127.0.0.1 –p 4000 //127.0.0.1可以用实际的主机IP地址代替,这样在其他机器上也可以远程连接到这台虚拟机 。
这样连上去的效果,看到的虚拟机窗口缺省是一个640x480的窗口,那么有没有办法让虚拟机窗口全屏呢,答案是肯定的:将焦点集中到虚拟机窗口后(用鼠标在虚拟机窗口点以下)按 shift+F11,退出全屏也是同样按shift+F11。
全屏后,又有一个问题,那就是虽然窗口全屏了,但是虚拟机的分辨率还是640x480,需要手工更改显示属性,将其调到当前显示器的最佳分辨率,有点麻烦。
那有没有更好的办法让虚拟机连接的时候就全屏,并且分辨率直接变成最佳呢?
答案是在虚拟机里装上spice社区提供的spice-guest-tools程序(里面包含了一个叫vdagent的程序,该程序能够在虚拟机全屏模式下自动调整虚拟机的分辨率到本地终端的当前分辨率)。:http://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-0.59.exe
在安装完以后检查服务:
如果上述”RHEV Spice Agent”存在并且已经是运行状态,那么就已经安装成功。
另外,为了全屏且让虚拟机自动适应分辨率,需要在连接参数中指定全屏选项和自适应分辨率选项:–-full-screen=auto-conf:
dev@devhost:/opt/vm# sudo spicec –h 127.0.0.1 –p 4000 –-full-screen=auto-conf
这样连接上去的时候,虚拟机就全屏显示并且分辨率自动调整到了本地最佳分辨率的状态(本地Ubuntu系统设置的是最佳分辨率)。
Spice 客户端和spice 服务端通常运行在不同的机器上,运行spice服务端的主机通常有着多颗多核的CPU以及几十G以上的内存,通过底层支持虚拟化的KVM+qemu环境虚拟出几台到几十台虚拟机,供运行Spice客户端的终端连接使用,这些终端通常配置较低,仅仅充当虚拟桌面的显示之用,当然还有键盘、鼠标的输入和声音的输出等基本功能,这些在我们之前介绍的spice连接中都已经具备。
稍稍有些麻烦的是外设,如最常用的是USB类外设,如U盘。这些外设的物理接口在客户端机器上,但是它的数据又要像普通PC一样传递到虚拟机里去处理。在平常的PC机器上,USB总线像其他的PCI总线等都在同一块物理主板上,操作系统能够通过底层的设备驱动很容易的访问和检测。但是在虚拟机环境下,虚拟操作系统运行在服务器上,这些USB外设在另外一台物理终端上,工作机理已经大大的不同了。连接外设和操作系统的媒介只有网络,因此毫无疑问,使用这些外设除了通过网络传输之外别无它法。
好在spice 社区推出了USB外设重定向的架构,那就是使用在本系列文章(三)和(四)中提到的LisbUSB和USBRedir等技术,将USB数据做所谓的重定向,当然spice客户端和服务器端也做了一些改变,增加了专门用来传递USB数据的通道,大致架构如下:
注意到上图中 spice-gtk是spice社区一个新的采用glib库开发的spice 客户端,也只有在这个新的客户端里增加了关于USB重定向的channel,因此我们需要重新编译一个这样的客户端出来。
Spice-gtk的下载地址是:https://launchpad.net/ubuntu/+source/spice-gtk ,本着一切自己动手的原则,分别下载:spice-gtk_0.19-0nocelt3.debian.tar.gz,spice-gtk_0.19-0nocelt3.dsc和spice-gtk_0.19.orig.tar.bz2,然后按照以前文章的方法编译。
稍微需要指出的是需要先安装依赖包:
sudo apt-get install libgtk2.0-dev libgtk-3-dev libgudev-1.0-dev libcairo2-dev valac libvala-0.16-dev python-gtk2-dev gobject-introspection libgirepository1.0-dev gir1.2-gtk-2.0 libtext-csv-perl libacl1-dev libpolkit-agent-1-dev libpolkit-gobject-1-dev
而其中valac包ubuntu源上的版本不匹配,需要自己下载源码编译:https://launchpad.net/ubuntu/+source/vala-0.20
编译完后安装生成的的deb包即可编译spice-gtk,然后再安装spice-gtk相关的deb包。
安装完spice-gtk以后,改成用spice-gtk来连接虚拟机,spice-gtk的程序名叫spicy
dev@devhost:/opt/vm$spicy –h 127.0.0.1 –p 4000
同样,spicy连接成功后也会出来虚拟机的桌面,但是插入U盘后并没有在虚拟机里看到U盘出现。那是因为还需要做两件事情:
1. 修改libvirt XML定义,增加有关USB重定向的配置(在<devices>…</devices>里面):
<controller type='usb' index='0' model='ich9-ehci1'>
<alias name='usb0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x7'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci1'>
<alias name='usb0'/>
<master startport='0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0' multifunction='on'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
<alias name='usb0'/>
<master startport='2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<alias name='usb0'/>
<master startport='4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x2'/>
</controller>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir0'/>
<address type='usb' bus='0' port='4'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir1'/>
<address type='usb' bus='0' port='5'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir2'/>
<address type='usb' bus='0' port='6'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir3'/>
<address type='usb' bus='0' port='3'/>
</redirdev>
上述配置的具体介绍请参考libvirt文档:http://www.libvirt.org/formatdomain.html#elementsHostDevSubsys
注意,修改配置以后虚拟机需要undefine, define,然后重启。
2. 在spicy连接参数中加入USB重定向的参数
注:--spice-usbredir-auto-redirect-filter=”-1,-1,-1,-1,1”表示自动重定向目前插在客户端设备上的USB外设;--spice-usbredir-redirect-on-connect=”-1,-1,-1,-1,1”表示对动态插入的USB外设做自动重定向,具体filter的含义需要连接的话请看spice-gtk源码。
带了这些参数重新连接成功后,在连到虚拟机一看:
插在客户端机器上的U盘(上图中的Ubuntu12.1 E:)已经成功重定向到虚拟机里面了,当然如果你连的快的话,这个外设有一段时间才能出来,因为第一次需要自动安装一些USB驱动等。
在USB中保充一下,如发现设备没有自动识别可以看一下,spicy菜单上面的
Input子菜单.里面可以选译当前可识别到了哪些USB设备,再把其passthrough到虚拟机中去.
再次十分感谢CSDN中的上善若水75
http://blog.csdn.net/hbsong75
及
http://smilejay.com/kvm-principles-and-practices/