1.1.7 libvirt API 使用示例

经过前面几个小节对libvirt的配置、编译、API、建立连接等内容的介绍,相信大家对libvirt已经有了大致的了解。对API进行学习的最好方法就是使用代码来调用API实现几个小功能,所以本节主要通过两个示例来分别演示如何调用libvirt的C语言和Python语言绑定的API。

1. libvirt C API的使用

在使用libvirt API之前,必须要在远程或本地的节点上启动libvirtd守护进程。在使用libvirt的客户端,先安装libvirt-devel软件包或使用6.1.2节中介绍的方法来自行编译和安装libvirt。本次示例中安装的是RHEL 6.3自带的libvirt-devel软件包,如下:


[root@rhel6u3-ga ~]# rpm -q libvirt-devel
libvirt-devel-0.9.10-21.el6.x86_64


如下一个简单的C程序(文件名为dominfo.c)就是通过调用libvirt的API来查询一些关于某个域的信息。该示例程序比较简单易懂,它仅仅对使用libvirt API的一个演示程序,这里不做过多的介绍。不过,这里有三点需要注意:1. 需要在示例代码的开头引入<libvirt/libvirt.h>这个头文件; 2. 由于只是做查询信息的功能,所以可以使用virConnectOpenReadOnly来建立只读连接; 3. 这里使用了空值(NULL)作为URI,是让libvirt自动根据6.1.6小节中介绍的默认规则去建立到Hypervisor的连接。这里由于本地是启动libvirtd守护进程,启动了两个QEMU/KVM客户机,所以它默认会建立到QEMU/KVM的连接。

/**
* Get domain information via libvirt C API.
* Tested with libvirt-devel-0.9.10 on a RHEL 6.3 host system.
*/
 
#include <stdio.h>
#include <libvirt/libvirt.h>
 
int getDomainInfo(int id) {
virConnectPtr conn = NULL; /* the hypervisor connection */
virDomainPtr dom = NULL;   /* the domain being checked */
virDomainInfo info;        /* the information being fetched */
 
/* NULL means connect to local QEMU/KVM hypervisor */
conn = virConnectOpenReadOnly(NULL);
if (conn == NULL) {
fprintf(stderr, “Failed to connect to hypervisor\n”);
return 1;
}
 
/* Find the domain by its ID */
dom = virDomainLookupByID(conn, id);
if (dom == NULL) {
fprintf(stderr, “Failed to find Domain %d\n”, id);
virConnectClose(conn);
return 1;
}
 
/* Get virDomainInfo structure of the domain */
if (virDomainGetInfo(dom, &info) < 0) {
fprintf(stderr, “Failed to get information for Domain %d\n”, id);
virDomainFree(dom);
virConnectClose(conn);
return 1;
}
 
/* Print some info of the domain */
printf(“Domain ID: %d\n”, id);
printf(“    vCPUs: %d\n”, info.nrVirtCpu);
printf(“   maxMem: %d KB\n”, info.maxMem);
printf(“   memory: %d KB\n”, info.memory);
 
if (dom != NULL)
virDomainFree(dom);
if (conn != NULL)
virConnectClose(conn);
 
return 0;
}
 
int main(int argc, char **argv)
{
int dom_id = 3;
printf(“—–Get domain info by ID via libvirt C API —–\n”);
getDomainInfo(dom_id);
return 0;
}

在获得dominfo.c这个示例程序之后,用virsh命令查看当前节点中的情况,再编译和运行这个示例程序去查询一些域的信息,可以将二者得到的一些信息进行对比,可以发现二者得到的信息是匹配的,命令行操作如下:

[root@rhel6u3-ga kvm_demo]# virsh list
Id    Name                           State
—————————————————-
3     kvm-guest                      running
6     kvm-guest-2                    running
 
[root@rhel6u3-ga kvm_demo]# virsh dommemstat 3
actual 1048576
rss 680228
 
[root@rhel6u3-ga kvm_demo]# virsh vcpucount 3
maximum      live           4
current      live           4
 
[root@rhel6u3-ga kvm_demo]# gcc dominfo.c -o dominfo -lvirt
 
[root@rhel6u3-ga kvm_demo]# ./dominfo
—–Get domain info by ID via libvirt C API —–
Domain ID: 3
vCPUs: 4
maxMem: 1048576 KB
memory: 1048576 KB


这里需要注意的是,在使用GCC编译dominfo.c这个示例程序时,加上了“-lvirt”这个参数来指定程序链接时的依赖的库文件,如果不指定libvirt相关的共享库,则会发生链接时错误。在本次示例的RHEL 6.3系统中,需要依赖的libvirt共享库文件是/usr/lib64/libvirt.so,如下:


[root@rhel6u3-ga ~]# ls /usr/lib64/libvirt.so
/usr/lib64/libvirt.so
2. libvirt Python API的使用

1.1.1小节中已经介绍过,许多种编程语言都提供了libvirt的绑定。Python作为一种在Linux上比较流行的编程语言,它也提供了libvirt API的绑定。在使用Python调用libvirt之前,需要安装libvirt-python软件包,或者使用6.1.2节中介绍的方法来自行编译和安装libvirt及其Python API。

本次示例是基于RHEL 6.3系统自带libvirt和libvirt-python软件包来进行的,对libvirt-python以及Python中的libvirt API文件的查询,命令行如下:


[root@rhel6u3-ga ~]# rpm -q libvirt-python
libvirt-python-0.9.10-21.el6.x86_64
[root@rhel6u3-ga ~]# ls /usr/lib64/python2.6/site-packages/libvirt*
/usr/lib64/python2.6/site-packages/libvirtmod_qemu.so  /usr/lib64/python2.6/site-packages/libvirt.pyo
/usr/lib64/python2.6/site-packages/libvirtmod.so       /usr/lib64/python2.6/site-packages/libvirt_qemu.py
/usr/lib64/python2.6/site-packages/libvirt.py          /usr/lib64/python2.6/site-packages/libvirt_qemu.pyc
/usr/lib64/python2.6/site-packages/libvirt.pyc         /usr/lib64/python2.6/site-packages/libvirt_qemu.pyo

如下是本次示例使用的一个Python小程序(libvirt-test.py),用于通过调用libvirt Python API来查询域的一些信息。该示例Python程序的源代码如下:

#!/usr/bin/python
# Get domain info via libvirt python API.
# Tested with python2.6 and libvirt-python-0.9.10 on a KVM host.
 
import libvirt
import sys
 
def createConnection():
conn = libvirt.openReadOnly(None)
if conn == None:
print ‘Failed to open connection to QEMU/KVM’
sys.exit(1)
else:
print ‘—–Connection is created successfully—–’
return conn
 
def closeConnnection(conn):
print ”
try:
conn.close()
except:
print ‘Failed to close the connection’
return 1
 
print ‘Connection is closed’
 
def getDomInfoByName(conn, name):
print ”
print ‘———– get domain info by name ———-”‘
try:
myDom = conn.lookupByName(name)
except:
print ‘Failed to find the domain with name “%s”‘ % name
return 1
 
print “Dom id: %d   name: %s” % (myDom.ID(), myDom.name())
print “Dom state: %s” % myDom.state(0)
print “Dom info: %s” % myDom.info()
print “memory: %d MB” % (myDom.maxMemory()/1024)
print “memory status: %s” % myDom.memoryStats()
print “vCPUs: %d” % myDom.maxVcpus()
 
def getDomInfoByID(conn, id):
print ”
print ‘———– get domain info by ID ———-”‘
try:
myDom = conn.lookupByID(id)
except:
print ‘Failed to find the domain with ID “%d”‘ % id
return 1
 
print “Domain id is %d ; Name is %s” % (myDom.ID(), myDom.name())
 
if __name__ == ‘__main__’:
name1 = “kvm-guest”
name2 = “notExist”
id1 = 3
id2 = 9999
print “—Get domain info via libvirt python API—”
conn = createConnection()
getDomInfoByName(conn, name1)
getDomInfoByName(conn, name2)
getDomInfoByID(conn, id1)
getDomInfoByID(conn, id2)
closeConnnection(conn)



该示例程序比较简单,只是简单地调用libvirt Python API获取一些信息,这里唯一需要注意的是“import libvirt ”语句引入了libvirt.py这个API文件,然后才能够使用libvirt.openReadOnly 、conn.lookupByName 等libvirt中的方法。本次示例中,必须被引入的libvirt.py这个API文件的绝对路径在 /usr/lib64/python2.6/site-packages/libvirt.py ,它实际调用是/usr/lib64/python2.6/site-packages/ libvirtmod.so 这个共享库文件。

获得该示例Python程序后,运行该程序(libvirt-test.py),查看其运行结果,命令行操作如下:


[root@rhel6u3-ga kvm_demo]# python libvirt-test.py 2>/dev/null
—Get domain info via libvirt python API—
—–Connection is created successfully—–
 
———– get domain info by name ———-”
Dom id: 3   name: kvm-guest
Dom state: [1, 1]
Dom info: [1, 1048576L, 1048576L, 4, 257070000000L]
memory: 1024 MB
memory status: {‘actual’: 1048576L, ‘rss’: 680228L}
vCPUs: 4
 
———– get domain info by name ———-”
Failed to find the domain with name “notExist”
 
———– get domain info by ID ———-”
Domain id is 3 ; Name is kvm-guest
 
———– get domain info by ID ———-”
Failed to find the domain with ID “9999″
 
Connection is closed