阿使得肌肤· 发表于 2015-10-10 09:44:34

使用libvirt管理kvm(API篇)

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://speakingbaicai.blog.iyunv.com/5667326/1162005

一、简介

libvirt是Linux上的虚拟化库,是长期稳定的C语言API,支持KVM/QEMU、Xen、LXC等主流虚拟化方案。链接:http://libvirt.org/

API开发手册:http://libvirt.org/html/libvirt-libvirt.html

virsh是libvirt对应的shell命令。

之前写了一篇使用virsh管理kvm虚拟机的博客《使用libvirt管理kvm(virsh篇)》(传送门:http://speakingbaicai.blog.iyunv.com/5667326/1161964),这里再从编程接口API的角度介绍如何使用libvirt管理kvm虚拟机。

二、环境介绍

OS:Ubuntu
12.04.1 LTS

内核:Linux 3.2.0-33-generic-pae #52-Ubuntu SMP Thu Oct 18 16:39:21 UTC 2012 i686 i686 i386 GNU/Linux

libvirt:0.9.8

三、准备工作

ubuntu安装,直接apt-get
install

1、安装kvm/qemu

sudo apt-get install kvm qemu

2、安装libvirt

sudo apt-get install libvirt-bin libvirt-dev

3、网桥管理工具

sudo apt-get install bridge-utils

4、统一建模语言

sudo apt-get install uml-utilities

5、vnc 虚拟机查看工具

sudo apt-get install vncviewer vnc4server

四、创建镜像

在指定目录下

执行 qemu-img create
-f raw template.img 3G

这样就创建了一个大小为3G的镜像(img)

有人可能问镜像是什么东西。简单的说,我们在镜像上启动一个虚拟机,这个3G的镜像就相当于这个虚拟机对应的磁盘空间。

也有人执行 qemu-img create
-f qcow2 template.img 3G,(备注:qcow2支持动态扩张)来获得一个动态扩张的镜像。我个人还需要对磁盘资源进行简单的统计、管理,因此没有用这个。不同情景下可能这种模式更好,有兴趣的朋友自己试一下。

五、libvirt xml配置文件

libvirt(包括virsh)使用xml文件对虚拟机进行配置,其中包括虚拟机名称、分配内存、vcpu等多种信息。定义、创建虚拟机等操作都需要xml配置文件的参与,因此这里先介绍xml配置文件。我编辑了一个名为template.xml的xml文件,其中定义了一个名为demo的kvm 虚拟机。


[*]<domain type = 'kvm'>          //虚拟机类型,kvm
[*]    <name>demo</name>          //虚拟机名称
[*]    <memory>1048576</memory>   //分配内存,单位kb
[*]    <vcpu>1</vcpu>             //分配vcpu,单位个数
[*]    <os>
[*]      <type arch = 'x86_64' machine = 'pc'>hvm</type>
[*]      <boot dev = 'cdrom'/>//cd 启动
[*]      <boot dev = 'hd'/>   //硬盘启动
[*]    </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/bin/kvm</emulator>
[*]      <disk type = 'file' device = 'disk'>//对应的镜像,就是之前使用qemu-img命令新建的img文件,注意路径要正确
[*]            <driver name = 'qemu' type = 'raw'/>
[*]            <source file = '/var/lib/lynn/img/template.img'/>
[*]            <target dev = 'hda' bus = 'ide'/>
[*]      </disk>
[*]      <disk type = 'file' device = 'cdrom'> //可选项,iso通常是操作系统的安装光盘
[*]            <source file = '/var/lib/lynn/img/template.iso'/>
[*]            <target dev = 'hdb' bus = 'ide'/>
[*]      </disk>
[*]      <interface type = 'bridge'>         //libvirt默认虚拟机的网络配置是NAT模式,就是虚拟机与宿主机的网络拓扑是NAT形式。实际中,许多开发者更希望使用网桥模式。
[*]            <source bridge = 'br0'/>
[*]      </interface>
[*]      <input type ='tablet' bus='usb'/>
[*]      <input type = 'mouse' bus = 'ps2'/>
[*]      <graphics type = 'vnc' port = '-1' listen = '0.0.0.0' autoport = 'yes' keymap = 'en-us'/>//vnc端口系统自动配置
[*]    </devices>
[*]</domain>


六、libvirt的使用——头文件与编译

#include &quot;libvirt/libvirt.h&quot; //libvirt主要API

#include <libvirt/virterror.h> //libvirt 错误提示

编译时加入连接库 -lvirt,例如我要编译名为createvm.cpp的源文件,可以运行如下命令g&#43;&#43;
createvm.cpp -o createvm -lvirt。

七、主要使用的API

这里只列举一些常用的API,具体可参见libvirt
API开发手册



主要功能


函数原型



创建连接

virConnectPtr virConnectOpen(const char * name)               


根据xml文档创建虚拟机


virDomainPtr virDomainCreateXML(virConnectPtr conn, const char * xmlDesc, unsigned int flags)



根据虚拟机名字获得虚拟域


virDomainPtr virDomainLookupByName(virConnectPtr conn, const char * name)



获取虚拟域相关信息


int virDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)



关闭虚拟域


int virDomainShutdown (virDomainPtr domain)



销毁虚拟域


int virDomainDestroy (virDomainPtr domain)



八、新建虚拟机

备注:这里只是写一个简单的例子,除print.cpp以外的代码没有写成带参数、可配置的,请见谅。


[*]/*createvm.cpp*/
[*]/* compile with: g&#43;&#43; createvm.cpp -o createvm -lvirt */
[*]
[*]/* Wang Min @ iie         */
[*]/* autumn_sky_is@163.com    */
[*]/* date: 2013-02-27         */
[*]
[*]#include <iostream>
[*]#include <cstdio>
[*]#include <string>
[*]#include <fstream>
[*]#include <sstream>// for stringstream
[*]#include &quot;libvirt/libvirt.h&quot;
[*]#include <libvirt/virterror.h>
[*]
[*]using namespace std;
[*]string vm_xml_location = &quot;../xml/template.xml&quot;;
[*]
[*]int main()
[*]{
[*]    ifstream file(vm_xml_location.c_str());
[*]    if(!file) {
[*]      cout<<&quot;Cannot open file &quot;<<vm_xml_location<<endl;
[*]      return -1;
[*]    }
[*]    // read xml file
[*]    stringstream buffer;
[*]    buffer << file.rdbuf();
[*]    string vm_xml_template = buffer.str();
[*]    file.close();
[*]   
[*]    virConnectPtr conn = virConnectOpen(&quot;qemu:///system&quot;);
[*]    if(NULL==conn) {
[*]      fprintf(stderr, &quot;Failed to build connection to qemu:///system.\n&quot;);
[*]      return -1;
[*]    }
[*]
[*]    virDomainPtr vm_ptr = virDomainCreateXML(conn, vm_xml_template.c_str(), 0);
[*]    if(!vm_ptr) {
[*]      virErrorPtr error = virGetLastError();
[*]      cout<<error->message<<endl;
[*]      return -1;
[*]    }
[*]    return 0;
[*]}


编译后,直接运行./createvm,就创建了一个名为demo的kvm 虚拟机。需要预先在相应目录下新建好一个名为“template.xml”的配置文件

九、读取虚拟机信息


[*]/* print.cpp*/
[*]/* compile with: g&#43;&#43; print.cpp -o print -lvirt */
[*]
[*]/* Wang Min @ iie         */
[*]/* autumn_sky_is@163.com    */
[*]/* date: 2013-02-27         */
[*]
[*]#include <iostream>
[*]#include <cstdio>
[*]#include <string>
[*]#include <fstream>
[*]#include <sstream>// for stringstream
[*]#include &quot;libvirt/libvirt.h&quot;
[*]#include <libvirt/virterror.h>
[*]
[*]using namespace std;
[*]//using namespace rapidxml;
[*]
[*]int main(int argc, char * argv[])
[*]{
[*]    if(2!=argc){
[*]    cout<<&quot;Error: print need 1 parametre&quot;<<endl;
[*]    cout<<&quot;usage: ./print vm_name&quot;<<endl;
[*]    return -1;   
[*]    }
[*]    virConnectPtr conn = virConnectOpen(&quot;lxc:///&quot;);
[*]    if(NULL==conn) {
[*]      fprintf(stderr, &quot;Failed to build connection to lxc:///.\n&quot;);
[*]      return -1;
[*]    }
[*]
[*]    virDomainPtr domain = virDomainLookupByName(conn, argv);
[*]    if(domain == NULL){
[*]      cout<<&quot;can not find &quot;<<argv<<&quot;, regard it as success.&quot;<<endl;
[*]      return -1;
[*]    }   
[*]   
[*]    // get lxc Info
[*]    virDomainInfo info;
[*]    if(-1==virDomainGetInfo(domain, &info)){
[*]       cout<<&quot;can not get domain info&quot;<<endl;
[*]       return -1;
[*]    }
[*]   
[*]    printf(&quot;state:%d|maxmem:%d|memused:%d|cpunum:%d|cputime:%ld\n&quot;,info.state,info.maxMem,info.memory,info.nrVirtCpu,info.cpuTime);
[*]    cout<<&quot;Helloworld&quot;<<endl;
[*]    return 0;
[*]}


编译后运行./print virt_name,例如./print demo

十、关闭虚拟机


[*]/* shutdownvm.cpp*/
[*]/* compile with: g&#43;&#43; shutdownvm.cpp -o shutdownvm -lvirt */
[*]
[*]/* Wang Min @ iie         */
[*]/* autumn_sky_is@163.com    */
[*]/* date: 2013-02-27         */
[*]
[*]#include <iostream>
[*]#include <cstdio>
[*]#include <string>
[*]#include <fstream>
[*]#include <sstream>// for stringstream
[*]#include &quot;libvirt/libvirt.h&quot;
[*]#include <libvirt/virterror.h>
[*]
[*]using namespace std;
[*]string domname = &quot;demo&quot;;
[*]int main()
[*]{
[*]    virConnectPtr conn = virConnectOpen(&quot;qemu:///system&quot;);
[*]    if(NULL==conn) {
[*]      fprintf(stderr, &quot;Failed to build connection to qemu:///system.\n&quot;);
[*]      return -1;
[*]    }
[*]
[*]    virDomainPtr domain = virDomainLookupByName(conn, domname.c_str());
[*]    if(domain == NULL){
[*]      cout<<&quot;can not find &quot;<<domname <<&quot;, regard it as success.&quot;<<endl;
[*]      return 0;
[*]    }
[*]    if(virDomainShutdown(domain)!=0){
[*]      virErrorPtr error = virGetLastError();
[*]      cout<<error->message<<endl;
[*]      return -1;
[*]    }
[*]    return 0;
[*]}


编译后运行./shutdownvm

十一、销毁虚拟机


[*]/* destroyvm.cpp*/
[*]/* compile with: g&#43;&#43; destroyvm.cpp -o destroyvm -lvirt */
[*]
[*]/* Wang Min @ iie         */
[*]/* autumn_sky_is@163.com    */
[*]/* date: 2013-02-27         */
[*]
[*]#include <iostream>
[*]#include <cstdio>
[*]#include <string>
[*]#include <fstream>
[*]#include <sstream>// for stringstream
[*]
[*]#include &quot;libvirt/libvirt.h&quot;
[*]#include <libvirt/virterror.h>
[*]
[*]using namespace std;
[*]string domname = &quot;demo&quot;;
[*]int main()
[*]{
[*]    virConnectPtr conn = virConnectOpen(&quot;qemu:///system&quot;);
[*]    if(NULL==conn) {
[*]      fprintf(stderr, &quot;Failed to build connection to qemu:///system.\n&quot;);
[*]      return -1;
[*]    }
[*]
[*]    virDomainPtr domain = virDomainLookupByName(conn, domname.c_str());
[*]    if(domain == NULL){
[*]      cout<<&quot;can not find &quot;<<domname <<&quot;, regard it as success.&quot;<<endl;
[*]      return 0;
[*]    }
[*]    if(virDomainDestroy(domain)!=0){
[*]      virErrorPtr error = virGetLastError();
[*]      cout<<error->message<<endl;
[*]      return -1;
[*]    }
[*]    return 0;
[*]}


编译后运行./destroyvm

本文出自 “说话的白菜” 博客,请务必保留此出处http://speakingbaicai.blog.iyunv.com/5667326/1162005
页: [1]
查看完整版本: 使用libvirt管理kvm(API篇)