原始地址不知道,转载来自:http://www.verydemo.com/demo_c441_i65124.html

简单的讲,nova最核心的功能就是对一大堆的虚拟机进行管理,虚拟机可以是各种各样(kvm, qemu, xen, vmware...),而且管理的方法也可以是各种各样(libvirt, xenapi, vmwareapi...),因为我的电脑不支持CPU的VT,而且以前在visualbox中装openstack,也只能使用qemu,所以这次测试的主要是qemu的使用,另外nova中默认使用的管理虚拟机的API是libvirt,所以这里的测试使用libvirt。

首先来简单说一下我对libvirt和qemu这两个的理解:

1. libvirt

libvirt是一套用c语言写的API,旨在为各种虚拟机提供一套通用的编程接口,而且支持与java,python等语言的绑定。基于libvirt的虚拟机管理工具也有很多:virt-manager(GUI工具),virsh(命令行工具)。其架构示意图如下:


(左图是没有使用libvirt的情况)

这里涉及到几个概念:

(1)Domain:虚拟机的一个运行实例,简单的理解,就是一个虚拟机虚拟出来的操作系统。它的叫法可是多种多样:instance,guest OS,virsual machine,其实都指的同一个概念。

(2)Hypervisor:指的就是虚拟机本身,比如qemu, kvm, xen...

libvirt 由几个不同的部分组成,其中包括应用程序编程接口 (API) 库、一个守护进程 (libvirtd),以及一个默认命令行实用工具 (virsh),libvirtd守护进程负责对虚拟机的管理工作,在用各种工具对虚拟机进行管理的时候,这个守护进程一定要跑起来,而且这个进程可以分为两种,一种是root权限的libvirtd,一种是普通用户权限的libvirtd,前者权限大,可以虚拟计算机的各种设备。

开启root权限的libvirtd守护进程要以root身份去运行:sudo libvirtd  --daemon


2. qemu

qemu是一个仿真器,即可用于来宾操作系统的虚拟化,也可以作为完整的机器仿真器使用,运行使用主机 CPU 或其他 CPU 架构的操作系统。

qemu 支持两种操作模式:用户模式仿真和系统模式仿真。用户模式仿真 允许一个 CPU 构建的进程在另一个 CPU 上执行(执行主机 CPU 指令的动态翻译并相应地转换 Linux 系统调用)。系统模式仿真 允许对整个系统进行仿真,包括处理器和配套的外围设备,这时就应该使用root权限的libvirtd。

qemu相关的命令:

  1. $ qemu-img create -f qcow disk.img 128M  
创建一个名为disk.img的128M大小的qcow格式的磁盘映像文件,这个文件充当来宾操作系统的硬盘。

$ qemu -hda disk.img -cdrom /root/cflinux-1.0.iso -boot d
-hda指定磁盘映像文件,-cdrom指定光盘镜像文件,-boot指定从哪里引导系统,d是从CD-ROM引导,c表示从硬盘引导

$ qemu -hda disk.img
开始启动来宾操作系统


接下来,使用visual manager工具来模仿一下openstack中Flat模式的网络,因为我在安装openstack的时候,最后一步总是无法ping或ssh上实例,所以这里通过对实例的直接操作来进行演示,其网络拓扑图如下:


(网络是我的一大浩劫,一遇到和网络相关的东西,立马就纠结了,网桥,路由,网关,网段,交换机,nat,dhcp等等,这些东西不实践一下,完全弄不明白他们是干什么的,还好,通过这一段时间的学习,基本上知道了怎么回事,开学之后,一定要补一下网络知识。)

从开始安装,到今晚之前,在这个拓扑图里,一直有一个不懂的东西,就是那个br100!原来它就是传说中的网桥,网卡可以桥接到这个网桥上,来连接两个局域网。网桥工作在物理链路层,相当于一个“低层”的路由器,通过mac帧来识别主机,所以桥接到这个网桥上的网卡是不需要配ip的,这解开了我“多年”的疑惑:为什么那个eth1不需要配ip啊?那两个局域网是怎么连到一块的?原来如此!

还有一个困惑就是多网卡的问题,一直不明白,为什么一台电脑要多个网卡,一个网卡不够用吗?原来真的不够用!一个网卡只能负责接入到一个网络,如果一个电脑要同时接入多个网络的话,那么就得用多个网卡了,也就是说一台电脑可以同时处于不同的局域网中。那这样的话,以前在我脑海中,一台电脑在网络中的身份是唯一的,这样的概念就不成立了啊,一台电脑也可以有多个身份,是由网卡决定的。


好了,吐槽完毕,下面是我模拟的简单的拓扑图:


我的目的就是让host能ping通任意一个虚拟机,虚拟机之间能够相互ping通,并且host能ssh上任意一个虚拟机。

1.  首先要做的就是建立br100网桥,在安装nova时,这个网桥是自动创建的,这里来手动创建,创建网桥使用到的工具是bridge-utils,即使用brctl相关的命令:

$ brctl addbr br100   #添加一个网桥
$ brctl addif br100 eth0   #把网卡桥接到网桥上
$ ifconfig eth0 0.0.0.0 
$ ifconfig br100 10.0.0.1   #给网桥配ip

eth0的ip可配可不配。这样创建的网桥不是永久的,系统重启的话,就会销毁了。


2.  建立虚拟机:

用visual manager建立3个虚拟机,我用的系统镜像是cflinux-1.0.iso,一个只有几兆的linux发行版,磁盘映像是用virtual manager创建的raw格式的image。

需要注意的是在第5步选择网络的时候,要选“specify shared device name”,然后在下面的输入框中输入刚刚创建好的网桥的名字:br100,如下图:



3.  改虚拟机的ip

不知道为什么visual manager创建的虚拟机初识状态的ip都是一样的,都是10.0.0.2,使用ifconfig命令把3个虚拟机的ip改为:

10.0.0.2       10.0.0.3        10.0.0.4

让他们在同一个网段。


这样,主机可以ping通实例,实例之间也可以相互ping通了,通过ssh root@10.0.0.2也能连上虚拟机了!


还未明白的问题:

每次虚拟机启动之后,用ifconfig在主机上查询网络信息,会看到vnet0, vnet1等这些信息,还有virbr0, virbr1等,后者我知道表示的是一个网段,但是前者是做什么用的呢?是虚拟机的虚拟出来的网卡吗?


上面介绍了qemu的基本使用,使用virsh或者virtual manager来管理虚拟机,但没有涉及到libvirt API,这里就使用libvirt的python API来演示一下虚拟机的创建。

看nova的源码,关于虚拟机管理的模块是virt,libvirt就是其中的一个包,这个包中包含了使用libvirt管理虚拟机的所有API,看一下下面的示意图:



libvirt.driver这个模块中有一个全局的变量libvirt,其指向的就是libvirt的库函数,连接的获得_conn、虚拟机的创建等都是通过这个变量来调用的libvirtAPI。

在对虚拟机进行管理之前,先要和虚拟机的管理程序,即Hypervisor建立连接,在这里创建连接有两种方式,一个是只读的,一个是可读写的,创建连接在_connect()方法中:

  1. @staticmethod  
  2. def _connect(uri, read_only):  
  3.     auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT],  
  4.             'root',  
  5.             None]  
  6.   
  7.     if read_only:  
  8.         return libvirt.openReadOnly(uri)  
  9.     else:  
  10.         return libvirt.openAuth(uri, auth, 0)  

创建虚拟机主要在_create_domain()方法中:

  1. def _create_domain(self, xml=None, domain=None, launch_flags=0):  
  2.     """Create a domain. 
  3.  
  4.     Either domain or xml must be passed in. If both are passed, then 
  5.     the domain definition is overwritten from the xml. 
  6.     """  
  7.     if xml:  
  8.         domain = self._conn.defineXML(xml)  
  9.     domain.createWithFlags(launch_flags)  
  10.     return domain  

虚拟机相关的参数都在一个xml文件中配置,创建虚拟机时就使用这个xml文件中的内容作为参数,即上面的xml参数的类型是字符串。

defineXML()是用根据xml的内容定义了一个虚拟机,即创建了一个virDomain对象,但是并没有启动这个虚拟机。用这个方法定义的虚拟机是永久性的,会再生成一个和这个虚拟机相关的xml配置文件。还有一个方法是createXML(),它创建的虚拟机是临时性的。

createWithFlags()是启动之前定义的虚拟机,即让虚拟机的状态变为running。和它类似的方法还有一个create(),两者的区别暂时还不清楚。


根据上面的方法,就可以直接使用python来创建虚拟机了,简单的示例如下:

  1. import libvirt  
  2.   
  3. auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT],'root',None]  
  4.   
  5. conn=libvirt.openAuth("qemu:///system",auth,0#这里要用读写的方式打开连接  
  6.   
  7. with open('/suo/domain/demo.xml') as f:  
  8.     xml=f.read()  
  9.   
  10. domain=conn.defineXML(xml)  
  11. domain.createWithFlags(0)  
  12.   
  13. try:  
  14.     dom0 = conn.lookupByName("instance-00000001")  
  15. except:  
  16.     print 'Failed to find the main domain'  
  17.     sys.exit(1)  
  18.   
  19. print "Domain 0: id %d running %s" % (dom0.ID(), dom0.OSType())  
  20. print dom0.info()  

因为使用python创建虚拟机,需要读写很多root权限的文件,所以要用openAuth()方法来创建连接,并且qemu使用的是system模式的。

demo.xml文件如下:

  1. <domain type='qemu'>  
  2.   <name>instance-00000001</name>  
  3.   <uuid>c7a5fdbd-cdaf-9455-926a-d65c16db1809</uuid>  
  4.   <memory>219200</memory>  
  5.   <currentMemory>219200</currentMemory>  
  6.   <vcpu>1</vcpu>  
  7.   <os>  
  8.     <type arch='i686' machine='pc'>hvm</type>  
  9.     <boot dev='hd'/><!--优先从硬盘启动-->  
  10.     <boot dev='cdrom'/><!--硬盘不能启动的话,从光驱启动-->  
  11.   </os>  
  12.   <devices>  
  13.     <emulator>/usr/local/bin/qemu</emulator>  
  14.     <disk type='file' device='cdrom'>  
  15.       <source file='/suo/domain/cflinux-1.0.iso'/>  
  16.       <target dev='hdc'/>  
  17.       <readonly/>  
  18.     </disk>  
  19.     <disk type='file' device='disk'>  
  20.       <source file='/suo/domain/precise-server-cloudimg-i386-disk1.img'/>  
  21.       <target dev='hda'/>  
  22.     </disk>  
  23.     <interface type='bridge'>  
  24.       <source bridge='br100'/><!--这里配置的虚拟机让它桥接到br100网桥上-->  
  25.     </interface>  
  26.     <graphics type='vnc' port='-1'/>  
  27.   </devices>  
  28. </domain>  

官方文档上介绍这个xml的配置文件是还有很多复杂的内容,这里仅仅配置了最简单的情况,方便理解。另外网络的配置现在还不太明白怎么配置,只是简单的把这个虚拟机桥接到了br100这个网桥上。

运行上面的python文件,就可以创建虚拟机了(前提是创建好br100和root权限的libvirtd的守护进程正常运行),运行之后只是创建了虚拟机,但是对虚拟机的安装还是需要手动进行的,可以使用qemu的命令:qemu -hda instance-00000001.img来打开一个qemu的虚拟机窗口,也可以直接使用virtual manager来进行安装。


参考资料:

http://wiki.libvirt.org/page/Networking

http://www.ibm.com/developerworks/cn/linux/l-qemu/

http://wiki.dzsc.com/info/8659.html

http://blog.csdn.net/hilyoo/article/details/7721401

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐