一.KVM虚拟机创建的用户操作
对于用户或者管理员来说,虚拟机的创建有着很多的方法,例如:kvm自带命令行工
具、使用virsh命令来创建、使用具有图形界面的virt-manager等等。但是它们底层实现的原理都是一样的,而且它们基本上都是通过开源的虚拟化库Libvirt来开发的。下面就讲一讲三种用户可以创建虚拟机的方式。
1.1 利用kvm自带命令行工具进行创建
kvm常用命令如下:
参数 | 示例 | 说明 |
-hda | -hda /data/windows.img | 指定windows.img作为硬盘镜像 |
-cdrom | -cdrom /data/windows.iso | 指定windows.iso作为光盘镜像 |
-boot | -boot c | 从硬盘启动 |
| -boot d | 从光盘启动 |
-m | -m 512 | 分配512M内存给虚拟系统 |
-vnc | -vnc :0 | 作为vnc服务器 |
-cpu | -cpu ? | 列出支持的CPU |
| -cpu core2duo | 指定CPU为core2duo |
-smp | -smp 2 | 指定虚拟机有2个CPU |
-net | -net nic | 为虚拟机网卡(默认为tap0) |
| -net tap | 系统分配tap设备(默认为tap0)1 |
| -net nic -net tap | 将虚拟机的网卡eth0连接真机里的tap0 |
具体创建一个虚拟机的步骤如下:
(1)生成硬盘镜像文件
root@host:kvm-img create -f rawtest.img 10G
其中“-f raw”指定镜像文件的格式为“raw”,“10G”指定镜像文件大小。
(2)从光盘启动虚拟机来安装操作系统
root@host:kvm -boot d -hda test.img-cdrom test.iso -m 512
其中“-boot d”指定虚拟机从光盘启动,“-hda test.img”指定硬盘镜像的位置,“-cdrom test.iso”指定光盘镜像的位置,“-m 512”指定虚拟机的内存为512M。
(3)安装操作系统后便可直接从硬盘启动虚拟机
root@host:kvm -boot c -hda test.img-m 512
1.2 利用virsh命令行工具进行创建
1.2.1 virsh工具简介
Virsh是由一个名叫libvirt的软件提供的管理工具,提供管理虚拟机比较高级的能力。Virsh可以管理KVM以及xen等虚拟机。
下面是virsh的一些常见的命令行选项:
命令 | Description |
help | 打印基本帮助信息。 |
list | 列出所有客户端。 |
dumpxml | 输出客户端 XML 配置文件。 |
create | 从 XML 配置文件生成客户端并启动新客户端。 |
start | 启动未激活的客户端。 |
destroy | 强制客户端停止。 |
define | 为客户端输出 XML 配置文件。 |
domid | 显示客户端 ID。 |
domuuid | 显示客户端 UUID。 |
dominfo | 显示客户端信息。 |
domname | 显示客户端名称。 |
domstate | 显示客户端状态。 |
quit | 退出这个互动终端。 |
reboot | 重新启动客户端。 |
restore | 恢复以前保存在文件中的客户端。 |
resume | 恢复暂停的客户端。 |
save | 将客户端当前状态保存到某个文件中。 |
shutdown | 关闭某个域。 |
suspend | 暂停客户端。 |
undefine | 删除与客户端关联的所有文件。 |
migrate | 将客户端迁移到另一台主机中。 |
命令 | Description |
setmem | 为客户端设定分配的内存。 |
setmaxmem | 为管理程序设定内存上限。 |
setvcpus | 修改为客户端分配的虚拟 CPU 数目。 |
vcpuinfo | 显示客户端的虚拟 CPU 信息。 |
vcpupin | 控制客户端的虚拟 CPU 亲和性。 |
domblkstat | 显示正在运行的客户端的块设备统计。 |
domifstat | 显示正在运行的客户端的网络接口统计。 |
attach-device | 使用 XML 文件中的设备定义在客户端中添加设备。 |
attach-disk | 在客户端中附加新磁盘设备。 |
attach-interface | 在客户端中附加新网络接口。 |
detach-device | 从客户端中分离设备,使用同样的 XML 描述作为命令attach-device。 |
detach-disk | 从客户端中分离磁盘设备。 |
detach-interface | 从客户端中分离网络接口。 |
命令 | Description |
version | 显示 virsh 版本 |
nodeinfo | 有关管理程序的输出信息 |
1.2.2 virsh命令来创建虚拟机步骤
(1)生成硬盘镜像文件
root@host:kvm-img create -f rawtest.img 10G
(2)编写xml配置文件,这一步在1.2.3节具体介绍
(3)创建并运行虚拟机
root@host:virsh create test.xml
其中“test.xml”指定步骤(2)中创建的xml文件
这样一个虚拟机便创建起来了。
1.2.3 xml配置文件的编写
利用virsh工具创建虚拟机必须编写xml配置文件,该文件指定虚拟机的各项参数,比如虚拟机名称、磁盘镜像的位置、内存大小、显示配置等等。下面给出一个简单的配置文件的例子。
#test.xml
windowsXP
500000
500000
1
hvm
/usr/bin/qemu-system-x86_64
下面介绍其中几个比较重要的元素及属性。
(1)元素的type属性指定运行域的虚拟机管理器,针对kvm应当选择“qemu”。
(2)元素的内容指定域的名字。
(3)元素和元素的内容非别指定启动时为域分配的最大内存和实际分配的内存。
(4)元素之间的内容用来指定操作系统启动的一些信息。其中重复的元素形成了一个启动顺序表,比如例子中先从磁盘启动,磁盘无法启动再从光盘启动。
(5)元素的device属性指明不同的设备,标签的file属性指明这些设备的位置。
1.3 如何通过图形化界面virt-manager来创建虚拟机
Virt-manger既虚拟机管理器,是创建和管理虚拟客户端的图形工具。具体的操作步骤为:
① 从控制台窗口启动这个工具,从root身份输入virt-manager命令,点击file菜单
的”新建”选项。
② virt-manager显示两种虚拟化方法:Qemu/KVM或者Xen,这里选择Qemu/KVM作
为hypervisor。
③ 选择虚拟机名称和指定一种安装方法,通过网络安装服务器或者本地CD/DVD驱动包括本地ISO文件,在此我用本地ISO的安装方法。
④ 输入本地ISO文件路径和文件名(假设本地ISO的路径就在根目录下,名称为Mini-BT3.6.1.iso)
⑤ 设置虚拟机使用的内存容量和处理器数量。
⑥ 配置虚拟机的存储方法。对于存储后端有两种选择:物理存储设备或者使用之前建立的磁盘文件。如果处于简单测试,创建文件作为存储后端。当创建虚拟磁盘时,默认为10GB。
⑦ 网络配置,在这里选择NAT方式。
这样一个虚拟机就开始启动起来了,将会出现启动界面,最后出现虚拟机中操作系统的界面。
二.libvirt函数库如何实现虚拟机创建
2.1 virsh工具”create”命令源码
在libvirt软件包安装完成之后,就可以看到libvirt的源码,这个源码实现了很多的开发虚拟化软件的用户接口,也就是开发的API。里面也实现了工具virsh,这个工具也实现了很多的功能。在/tools下面有一个virsh.c,这个文件里面实现virsh的功能,这里就具体把创建这部分代码选取出来。
/*
* "create" command
*/
static const vshCmdInfo info_create[] ={
{"help", N_("create a domain from an XML file")},
{"desc", N_("Create a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_create[]= {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containingan XML domain description")},
#ifndef WIN32
{"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
#endif
{"paused", VSH_OT_BOOL, 0, N_("leave the guest pausedafter creation")},
{"autodestroy", VSH_OT_BOOL, 0, N_("automatically destroythe guest when virsh disconnects")},
{NULL, 0, 0, NULL}
};
static bool
cmdCreate(vshControl *ctl, const vshCmd*cmd)
{
virDomainPtr dom;
const char *from = NULL;
bool ret = true;
char *buffer;
#ifndef WIN32
int console = vshCommandOptBool(cmd, "console");
#endif
unsigned int flags = VIR_DOMAIN_NONE;
if (!vshConnectionUsability(ctl, ctl->conn))
return false;
if (vshCommandOptString(cmd, "file", &from) <= 0)
return false;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return false;
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_START_PAUSED;
if (vshCommandOptBool(cmd, "autodestroy"))
flags |= VIR_DOMAIN_START_AUTODESTROY;
dom = virDomainCreateXML(ctl->conn, buffer, flags);
VIR_FREE(buffer);
if (dom != NULL) {
vshPrint(ctl, _("Domain %s created from %s\n"),
virDomainGetName(dom), from);
#ifndef WIN32
if (console)
cmdRunConsole(ctl, dom,NULL);
#endif
virDomainFree(dom);
} else {
vshError(ctl, _("Failed to create domain from %s"), from);
ret = false;
}
return ret;
}
代码的讲解:
⑴ typedef struct{
const char *name;
const char *data;
}vshCmdInfo;
上面这个结构体是关于命令的键值对信息,命令一般包含两个名称:命令的名字和命令的描述信息。
⑵ typedef struct{
const char *name;
vshCmdOptType type;
unsigned int flags;
const char *help;
}vshCmdOptDef;
上面这个结构体是关于命令选项的定义,该结构体一般包括四个字段:选项的名称,选项类型,标志,帮助信息。其中选项类型包括:bool类型,字符串类型,整型,字符数据,剩余的参数。
⑶ 在cmdCreate主程序中有一个特别重要的函数:virDomainCreateXML(),这个函数的最初原型是: virDomainPtr virDomainCreateXML (virConnectPtr conn,const char*xmlDesc,unsigned int flags),这个函数是基于一个指定的XML文件来创建一个虚拟机,其中conn表示一个指向hypervisor的连接,xmlDesc表示一个XML文件,flags表示命令选项的标志。
2.2 通过libvirt创建虚拟机的关键API
通过分析2.1中的virsh源码我们可以看出,使用libvirt进行虚拟机创建要调用两个关键的API-- virFileReadAll和virDomainCreateXML,下面分别进行说明。
2.2.1 virFileReadAll
该函数原型为intvirFileReadAll(const char *path, int maxlen, char **buf),功能是将参数“path”指定路径的文件内容读到一个缓冲区中,并将缓冲区地址记录在参数“*buf”中,而参数“maxlen”指定文件的最大长度。利用该API,我们可以将xml配置文件都到一个缓冲区中,以方便接下来的使用。
2.2.2virDomainCreateXML
该函数原型为virDomainPtr virDomainCreateXML (virConnectPtrconn, const char * xmlDesc, unsigned int flags),功能是根据参数“xmlDesc”定义的配置方式创建一个域并返回该域的指针。参数“conn”是指向虚拟机管理器的指针,而通过设置不同的“flags”标志,可以使创建的域具有不同的属性。
三. 利用libvirt库编写自己的虚拟机创建程序
Virsh命令用来创建虚拟机的命令是:virsh create,这个命令主要是从给定的XML文件生成客户端并启动客户端。
下面用一个测试例子来说明如何通过virsh命令来创建虚拟机的。
具体的操作实践步骤是:
- 首先需要创建虚拟硬盘,为了放置操作系统的地方,命令是:kvm-img create
701.img10G,也就是创建一个大小为10G的虚拟硬盘。
2. 编写一个xml文件,这个文件里面包含启动操作系统的一些特征,比如:内存容量,操作系统位置,虚拟硬盘位置等等,其实有很多的字段,可以简写一个xml文件,如果有些字段没有定义,那么系统就会默认,下面给出一个xml文件,命名为701.xml,程序为:
linux10.0421
512000
512000
1
hvm
/usr/bin/qemu-system-x86_64
3. 接着编写一个c文件,名称为701.c这个文件主要实现的功能就是调用这个xml文件来创建并启动虚拟机。这个c程序代码为:
#include
#include
#include
#include
const char *from=NULL;
static virConnectPtr conn=NULL;
#define VIRSH_MAX_XML_FILE 10*1024*1024
void closeConn()
{
if(conn!=NULL)
virConnectClose(conn);
}
int cmdCreate()
{
virDom