[zz]基于libvirt API监测xen初探

通过使用Xen的API或封装了其API的函数库,如libvirt进行编程,实现以下功能:

1.以命令行形式显示宿主机(Host OS)上正在运行的客户机(Guest OS)名称; 
2.通过命令行形式显示指定客户机(Guest OS)的工作状态(显示其 CPU 利用率,和内存使用情况即可); 
这个作业工程类似于Fedora等Linux系统中内置的xm管理程序,在这里仅简单的实现xm top的功能。我选用了Fedora Core 8作为Host OS。在其上,通过Xen安装另一Fedora Core 8作为Guest OS。利用libvirt提供的API实现显示Guest OS名称、显示其 CPU 利用率,和内存使用情况的功能。并与xm、virt-manager的运行结果做对比,验证正确性。

安装所需的软件包:

•xen-3.1.2-2.fc8 
•libvirt-o.4.2-1.fc8 
•libvirt-devl-0.4.2-1.fc8 
其中,xen为虚拟机,libvirt为运行库,libvirt-devl为代码运行库,供开发编译使用。具体版本视安装源与系统其他组件的依赖关系。

在我使用Xen安装Guest OS的过程中出现的一点小问题:在Fedora Core 8中发现默认提供的SELinux服务会对xen产生影响,估计可能是阻碍了某些信号量的传递,通过修改/etc/sysconfig/selinux,设置其中SELINUX=disabled将SElinux禁用。

通过virt-manager或virt-install安装Guest OS。设置为256m内存,4G硬盘空间,半虚拟化方式。

有关libvirt API的使用:


virConnectPtr virConnectOpenReadOnly (const char * name)  
在使用时首先应调用这个函数,获得hypervisor的链接  
name URI of hypervisor,为NULL则代表本地链接 
Returns 返回hypervisor的指针

int virConnectListDomains (virConnectPtr conn, int * ids, int maxids)  
获得hypervisor下所有域的ID  
conn hypervisor链接指针 
ids 存储每个域ID的数组 
maxids 域数量的上限 
Returns 域的数量

virDomainPtr virDomainLookupByID (virConnectPtr conn, int id) 
由域的ID返回域的指针  
conn hypervisor链接指针 
id 域的ID 
Returns 返回域的指针

int virDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info) 
获得域的信息 
domain 域的指针 
info 指向存储域的信息的数据结构的指针 
Returns 成功获取返回0,否则返回-1

const char * virDomainGetName (virDomainPtr domain) 
得到域的名字 
domain 域的指针 
Returns 域的名字

int virConnectClose (virConnectPtr conn) 
释放hyperbisor的连接,如果程序出线异常或错误应调用本函数终止连接 
conn hypervisor的指针 
Returns 成功释放返回0,否则返回-1

int virDomainFree (virDomainPtr domain) 
释放域的指针,如果连接到域就要先调用这个函数释放域的链接,之后再释放hyperbisor的连接 
domain 域的指针 
Returns 成功释放返回0,否则返回-1


一个主要的数据结构:


struct virDomainInfo 
unsigned char state 当前域的运行状态 
unsigned long maxMem 支持的最大内存 
unsigned long memory 使用的内存 
unsigned short nrVirtCpu 虚拟CPU数量 
unsigned long long cpuTime 虚拟CPU运行时间


我的设计思路是,利用virConnectOpenReadOnly()获取链接,通过virConnectListDomains()得到当前活跃的域的ID。对于每一个ID利用virDomainLookupByID()得到指向其域的指针。调用virDomainGetInfo()获得当前域的内存、CPU运行时间等信息。当前域的名称由virDomainGetName()获得。
CPU占用率的计算方法为:在myxm中两次调用virDomainGetInfo()获取时间段开始前和结束后的虚拟CPU运行时间,二者差值可知虚拟CPU的运行时间。间隔时间段用sleep()实现。在sleep()前后用gettimeofday()取得真实的时间差。该时间段内CPU运行时间与真实时间的比值即为这段时间内的CPU占用率。
编译时gcc增加-lvirt参数,用于包含libvirt-devl库。

  1. view plaincopy to clipboardprint?  
  2. 01.<PRE class=csharp name="code">/**    
  3. 02. * Project: myxm    
  4. 03. * Version: 0.2    
  5. 04. * Abstract: A simple xen monitor    
  6. 05. * Author: Gu Xiangnan    
  7. 06. * Date: 2008-05-25    
  8. 07. */   
  9. 08.   
  10. 09.#include <STDLIB.H></STDLIB.H>    
  11. 10.#include <STDIO.H></STDIO.H>    
  12. 11.#include <LIBVIRT libvirt.h=""></LIBVIRT>    
  13. 12.   
  14. 13.#define MAXID 50     
  15. 14.    
  16. 15./* the data structure of time */    
  17. 16.typedef struct timeInfo     
  18. 17.{     
  19. 18.    long long cpu_time;     
  20. 19.    struct timeval real_time;     
  21. 20.} timeInfoNode;     
  22. 21.    
  23. 22./* the hypervisor connection */    
  24. 23.static virConnectPtr conn = NULL;     
  25. 24.    
  26. 25./* release the connect of hypervisor */    
  27. 26.void closeConn()     
  28. 27.{     
  29. 28.    if (conn != NULL)     
  30. 29.        virConnectClose(conn);     
  31. 30.}     
  32. 31.    
  33. 32./* release the domain pointer */    
  34. 33.void freeDom(virDomainPtr dom)     
  35. 34.{     
  36. 35.    if (dom != NULL)     
  37. 36.        virDomainFree(dom);     
  38. 37.}     
  39. 38.    
  40. 39./* get the start time of each domain */    
  41. 40.void getTimeInfo(int id, timeInfoNode * infos)     
  42. 41.{     
  43. 42.    virDomainPtr dom = NULL;     
  44. 43.    virDomainInfo info;     
  45. 44.    int ret;     
  46. 45.    
  47. 46.    /* Find the domain of the given id */    
  48. 47.    dom = virDomainLookupByID(conn, id);     
  49. 48.    if (dom == NULL)     
  50. 49.    {     
  51. 50.        fprintf(stderr, "Failed to find Domain %d\n", id);     
  52. 51.        freeDom(dom);     
  53. 52.        closeConn();     
  54. 53.    }     
  55. 54.    
  56. 55.    /* Get the information of the domain */    
  57. 56.    ret = virDomainGetInfo(dom, &info);     
  58. 57.    if (ret < 0)     
  59. 58.    {     
  60. 59.        fprintf(stderr, "Failed to get information for Domain %d\n", id);     
  61. 60.        freeDom(dom);     
  62. 61.        closeConn();     
  63. 62.    }     
  64. 63.    
  65. 64.    /* get the start of realTime*/    
  66. 65.    if (gettimeofday(&(infos->real_time), NULL) ==  - 1)     
  67. 66.    {     
  68. 67.        fprintf(stderr, "Failed to get start time\n");     
  69. 68.            return;     
  70. 69.    }     
  71. 70.    
  72. 71.    /* get the start of CPUTime*/    
  73. 72.    infos->cpu_time = info.cpuTime; /* nanosecond */    
  74. 73.    
  75. 74.    freeDom(dom);     
  76. 75.}     
  77. 76.    
  78. 77.void getDomainInfo(int id, timeInfoNode infos)     
  79. 78.{     
  80. 79.    virDomainPtr dom = NULL;     
  81. 80.    virDomainInfo info;     
  82. 81.    int ret;     
  83. 82.    struct timeval realTime;     
  84. 83.    int cpu_diff, real_diff;     
  85. 84.    float usage;     
  86. 85.    
  87. 86.    /* Find the domain of the given id */    
  88. 87.    dom = virDomainLookupByID(conn, id);     
  89. 88.    if (dom == NULL)     
  90. 89.    {     
  91. 90.        fprintf(stderr, "Failed to find Domain %d\n", id);     
  92. 91.        freeDom(dom);     
  93. 92.        closeConn();     
  94. 93.    }      
  95. 94.    
  96. 95.    /* Get the information of the domain */    
  97. 96.    ret = virDomainGetInfo(dom, &info);     
  98. 97.    if (ret < 0)     
  99. 98.    {     
  100. 99.        fprintf(stderr, "Failed to get information for Domain %d\n", id);     
  101. 100.        freeDom(dom);     
  102. 101.        closeConn();     
  103. 102.    }     
  104. 103.    
  105. 104.    /* get the end of realTime*/    
  106. 105.    if (gettimeofday(&realTime, NULL) ==  - 1)     
  107. 106.    {     
  108. 107.        fprintf(stderr, "Failed to get start time\n");     
  109. 108.        return;     
  110. 109.    }     
  111. 110.    
  112. 111.    /* calculate the usage of cpu */    
  113. 112.    cpu_diff = (info.cpuTime - infos.cpu_time) / 10000;     
  114. 113.    real_diff = 1000 *(realTime.tv_sec - infos.real_time.tv_sec) +      
  115. 114.        (realTime.tv_usec - infos.real_time.tv_usec);     
  116. 115.    usage = cpu_diff / (float)(real_diff);     
  117. 116.    
  118. 117.    /* print the results */    
  119. 118.    printf("%d\t%.3f%\t%lu\t%lu\t%hu\t%0X\t%s\n", id, usage, info.memory / 1024,     
  120. 119.        info.maxMem / 1024, info.nrVirtCpu, info.state, virDomainGetName(dom));     
  121. 120.    
  122. 121.    freeDom(dom);     
  123. 122.}     
  124. 123.    
  125. 124.int main()     
  126. 125.{     
  127. 126.    int idCount;     
  128. 127.    int i;     
  129. 128.    int id;     
  130. 129.    int ids[MAXID];     
  131. 130.    timeInfoNode timeInfos[MAXID];     
  132. 131.    
  133. 132.    printf("--------------------------------------------------------\n");     
  134. 133.    printf("             XEN Domain Monitor Version 0.2\n");     
  135. 134.    printf("             Build by Gu Xiangnan 35060514\n");     
  136. 135.    printf("--------------------------------------------------------\n");     
  137. 136.    
  138. 137.    /* NULL means connect to local Xen hypervisor */    
  139. 138.    conn = virConnectOpenReadOnly(NULL);     
  140. 139.    if (conn == NULL)     
  141. 140.    {     
  142. 141.        fprintf(stderr, "Failed to connect to hypervisor\n");     
  143. 142.        closeConn();     
  144. 143.        return 0;     
  145. 144.    }     
  146. 145.    
  147. 146.    /* get the count of IDs and save these ID into ids[] */    
  148. 147.    idCount = virConnectListDomains(conn, &ids[0], MAXID);     
  149. 148.    if (idCount < 0)     
  150. 149.    {     
  151. 150.        fprintf(stderr, "Failed to list the domains\n");     
  152. 151.        closeConn();     
  153. 152.        return 0;     
  154. 153.    }     
  155. 154.    
  156. 155.    printf("Domain Totals: %d\n", idCount);     
  157. 156.    printf("ID\tCPU\tMEM\tMaxMEM\tVCPUs\tState\tNAME\n");     
  158. 157.    
  159. 158.    /* loop get the CPUtime info by IDs */    
  160. 159.    for (i = 0; i < idCount; i++)     
  161. 160.    {     
  162. 161.        id = ids[i];     
  163. 162.        getTimeInfo(id, &(timeInfos[i]));     
  164. 163.    }     
  165. 164.    
  166. 165.    sleep(1);     
  167. 166.    
  168. 167.    /* loop print the domain info and calculate the usage of cpus*/    
  169. 168.    for (i = 0; i < idCount; i++)     
  170. 169.    {     
  171. 170.        id = ids[i];     
  172. 171.        getDomainInfo(id, timeInfos[i]);     
  173. 172.    }     
  174. 173.    
  175. 174.    printf("--------------------------------------------------------\n");     
  176. 175.    closeConn();     
  177. 176.    return 0;     
  178. 177.}     
  179. 178.</PRE>    
  180.  

运行结果:

 

可以对比一下vmm与xm top,验证实现的正确性:

 

原文地址:https://www.cnblogs.com/zhangzhang/p/2350257.html