基於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,驗證實現的正確性:

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章