您的位置:首页 > 其它

管理下虚拟机如何? libvirt的一些基本用法

2013-01-24 23:23 120 查看
See the brief introduction in:http://en.wikipedia.org/wiki/Libvirt

源自我们已经用KVM创建了一个虚拟机,这时你想再创建一个,这当然没有问题,但问题是如果你创建很多个虚拟机,你想对其中的一个进行停止操作,你需要PS下kvm进程,然后再处理,这样我们就想到事情能不能简单一点,谁帮我管理一下这几个破虚拟机好不好。
先行者们也已经早就想到了,Libvirt就是开源的虚拟机管理程序,当然它支持qemu,xen....
1. 安装
ubuntu的世界,安装永远不是问题,apt-get install
2. 导入我们之前创建的虚拟机
virt-install --import --name demo3 --ram 512 --disk path=/media/kvm/winxp.img,format=qcow2
解释下:--import 是告诉这个工具,镜像我都做好系统了,用kvm启动他就行
--name xxx 告诉这个工具,以后这个镜像就叫这个名字了,你想对他做什么,告诉名字就可以
--raw 512 虚拟机内存啦
--disk path 镜像的地址
format 镜像的格式(libvirt默认是raw,如果不是raw必须要显示指出,否则会报boot失败)

3. 上面的操作就已经将这个虚拟机启动了,并且用virt-viewer打开了
4. 想管理他是吧,有两个工具
图形的virt-manager,这个不讲了,点点点
文本交互的virsh
virsh -c kemu:///system
virsh shutdown demo 关闭虚拟机
5. Libvirt提供了多种语言绑定开发,C/java/python
---------------------------------------------------------------------

一般而言,程序之中最最重要的是数据结构,故而我们从查找核心数据结构开始,但最初的表象切入点是libvirt的交互工具virsh。

1. 存储池的核心数据结构

[cpp:showcolumns] view
plaincopy

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

typedef struct _virStoragePoolObj virStoragePoolObj;

typedef virStoragePoolObj *virStoragePoolObjPtr;

struct _virStoragePoolObj {

virMutex lock; //线程异步锁

char *configFile; //XML文件路径

char *autostartLink; //软链接位置

int active; //是否激活

int autostart; //是否自动启用

unsigned int asyncjobs; //异步线程号

virStoragePoolDefPtr def; //当前存储池属性

virStoragePoolDefPtr newDef; //新存储池属性

virStorageVolDefList volumes; //当前存储池中卷列表

};

其中的virStoragePoolDefPtr类型是存储池属性数据结构

[c-sharp] view
plaincopy

typedef struct _virStoragePoolDef virStoragePoolDef;

typedef virStoragePoolDef *virStoragePoolDefPtr;

struct _virStoragePoolDef {

/* General metadata */

char *name; //存储池的名字

unsigned char uuid[VIR_UUID_BUFLEN]; //UUID

int type; /* virStoragePoolType */ //类型

unsigned long long allocation; //使用容量大小

unsigned long long capacity; //全部容量大小

unsigned long long available; //可用容量大小

virStoragePoolSource source; //原路径

virStoragePoolTarget target; //目的路径

};

找到以上两个核心数据结构,就基本上能够了解到如何描述每一个存储池,但是libvirt需要管理的是多个存储池
这时需要用到结构指针: 理解起来也简单,类似于一个数组, *p[1] 可以找到第二个结构变量
<细节>指针可以用malloc在堆上给他分配几个sizeof()的大小,存放几个结构变量,需要改数量时calloc堆上内存块的大小,根据调整变量的位置,通过memmove移动其他结构变量的位置。

实际使用中,又引入了这个结构体,便于获得到结构指针指向内存区域中结构变量的总个数

[c-sharp] view
plaincopy

typedef struct _virStoragePoolObjList virStoragePoolObjList;

typedef virStoragePoolObjList *virStoragePoolObjListPtr;

struct _virStoragePoolObjList {

unsigned int count;

virStoragePoolObjPtr *objs;

}

libvirt.c中conn->storageDriver->pools 就是这个类型的

2. 核心业务流程
表象 -> 细节
virsh的命令行 -> tools/virsh.c代码 -> src/libvirt.c -> src/storage/storage_dirver.c -> src/storage/storage_backend_XX.c

3. 新建存储池类操作
表象: 支持DIR,FS,NetFS,Logical,Disk,IScsi,Scsi,multipath (我们实际上只关=心DIR,FS,NetFs,Iscsi)
细节: DIR,FS,NetFS的卷的一些poolcreate,poolstart等需要实际跟操作系统打交道的功能是走的storage_backend_fs.c这个后端
同样的Logical,Disk,Iscsi,Scsi,mpath都有各自的后端

<一> pool-define virsh命令之一,用于按照提供的XML描述的内容,在存储池列表中新加入一个存储池,只加入不起用
XML描述格式,我们只关心DIR,Fs,NetFs,Iscsi几种
DIR:

[c-sharp] view
plaincopy

<pool type="dir">

<name>virtimages</name>

<target>

<path>/var/lib/virt/images</path>

</target>

</pool>

Fs:

[c-sharp] view
plaincopy

<pool type="fs">

<name>virtimages</name>

<source>

<device path="/dev/VolGroup00/VirtImages"/>

</source>

<target>

<path>/var/lib/virt/images</path>

</target>

</pool>

NetFs:

[c-sharp] view
plaincopy

<pool type="netfs">

<name>virtimages</name>

<source>

<host name="nfs.example.com"/>

<dir path="/var/lib/virt/images"/>

</source>

<target>

<path>/var/lib/virt/images</path>

</target>

</pool>

Iscsi: 这里path不指明一个固定的块设备,是因为物理机硬盘数的不确定性

[c-sharp] view
plaincopy

<pool type="iscsi">

<name>virtimages</name>

<source>

<host name="iscsi.example.com"/>

<device path="demo-target"/>

</source>

<target>

<path>/dev/disk/by-path</path>

</target>

</pool>

命令使用:
virsh> pool-define /tmp/default.xml

<细节> pool-define 只是把你要加入到存储池大家庭的这个存储池介绍给libvirt认识,他只看到的你的外表而已,不追究你的内在存不存在,但是你在libvirt那里已经挂上号了,pool-list --all 就能看到你,你是inactive的
代码:src/storage/storage_driver.c的storagePoolDefine函数中做以下几个事情:
* 读入xml信息
--virStoragePoolDefParseString
* 按读入的xml的name和uuid 信息判断是否在driver-pools重复存在
--virStoragePoolObjIsDuplicate
* 按读入的xml的type 判断类型写入dep->type
--virStorageBackendForType
* 扩展分配结构指针的的大小 calloc
+1 并且driver->pools->count +1

dirver->pools->obj[dirver->pools->count] = pool (这个是传入的xml构建的)
--virStoragePoolObjAssignDef
* 将存储池信息保存到指定配置文件位置,如果autostart==1,做软连接存储信息均为0
-virStoragePoolDefFormat 构建xml
--virStoragePoolObjSaveDef 保存xml
* 向hypervisor
connection注册存储池,加入到HashTable里 --virGetStoragePool

<二> pool-define-as virsh命令之一,pool-define的变种,不需要实现准备XML描述文件,把参数按照固定格式传入即可
他有个重要的选项 --print-xml 可以看到你输入的参数构成的XML,对照出那个参数传入的不对应。
命令使用: virsh> pool-define-as test, 0,0,0,0,/tmp/test

<三> pool-build virsh命令之一,针对dir,fs,netfs,logical,disk几种类型,如果pool-define时<path>参数指定的文件夹不存在的话,他会调用Linux基本文件操作函数创建这个目录,如果存在,他回修改文件夹的属性为可写
命令使用: virsh> pool-build test

<四> pool-start virsh命令之一,针对与处在inactive 状态的存储池有效,pool-list 可以看到状态为active,也可以在创建卷时使用这个存储池了。
命令使用:virsh> pool-start test

<细节> 一方面修改核心数据结构中变量的active参数,另一方面做一些二道贩子的事,如
dir/fs/netfs类型 脚本执行 mount/mount.nfs

iscsi 脚本执行iscsiadm XXXXX --login
执行上面命令后,回调用refresh_pool的函数,获取pool的容量信息,并存入核心数据结构变量中

<五> pool-create virsh命令之一,根据传入的XML描述文件,在存储池列表中新加入一个存储池,并且挂载启用它,代码是集pool-define和pool-start于一体,故而如果传入的XML描述文件的path指定文件夹不存在,则操作汇报错
命令使用:virsh>pool-create /tmp/example.xml

<六> pool-create-as virsh命令之一,pool-create的变种,不需要实现准备XML描述文件,把参数按照固定格式传入即可

他有个重要的选项 --print-xml 可以看到你输入的参数构成的XML,对照出那个参数传入的不对应。
命令使用:virsh>pool-create-as test, 0,0,0,0,/tmp/test

4. 删除/停止存储池类操作
<七> pool-destory virsh命令之一,停止正在工作的存储卷,pool-list 会看到变为inactive,但不改变其中内容
命令使用: virsh>pool-destory test
<细节> 改变核心数据结构变量的active的值为0
后端处理不同 fs,netfs 分别执行 umount / umount.nfs
iscsi来说就是iscsiadm
xxxxx --logout

<八> pool-delete
virsh命令之一,将非激活的存储卷中的内容清空,针对fs,netfs,dir,logical类型有效
命令使用:virsh>pool-delete test
<细节> 后端调用 rm -f 这个脚本命令

<九> pool-undefine virsh命令之一,将非激活的存储卷从存储卷列表中清除
命令使用; virsh>pool-undefine test
<细节> src/storage/storage_driver.c
storagePoolUndefine函数,做了这么几件事
* 判断pool是否存在于关键数据结构列表中
* 判断是否为inactive
* 判断是否没有异步线程
* unlink(ConfigureFile),删除xml文件
--virStoragePoolObjDeleteDef
* 不论是否为autostart,删除软连接
--unlink
* 释放结构指针多余内存,count
-1,调整结构指针大小 --virStoragePoolObjRemove

5. 修改存储池类操作
<十> pool-edit virsh命令之一,修改存储池属性,修改内容保存在结构体的newDef中,重启libvirt服务生效
命令使用: virsh>pool-edit test

6. 查询存储池类操作
<十一> virsh pool-dumpxml virsh命令之一,查看存储池的XML描述文件内容
命令使用: virsh>pool-dumpxml test
<细节> virStoragePoolDefFormat函数

<十二> pool-list virsh命令之一, --all/--inactive/--details 可以看到全部/非激活/细节
命令使用: virsh>pool-list --all
<细节> 先通过pools->count 得到总数量,根据条件遍历出active 数量
再遍历pools,得到name等的数组,按字母顺序排序

<十三> pool-info virsh命令之一,获得存储池的信息
激活的显示name,uuid,state,autostart,presistent和容量信息
非激活的显示 name,uuid,state,autostart,presistent信息
命令使用: virsh>pool-info test
<细节> virStoragePoolGetInfo函数得到信息

<十四> pool-refresh virsh命令之一,刷新存储池,是个异步任务,先清空当前volumes列表,后端执行refreshPool 更新volumes列表,更新pool的容量信息
命令使用: pool-refresh

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

Libvirt 编译与安装:http://www.docin.com/p-379569057.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: