使用libvirt技術監控虛擬機資源利用情況


(一)計算資源與內存資源的監控

libvirt中提供virDomainGetInfo方法可以將一個domain的計算資源和內存資源的使用情況封裝在一個結構體中,如下:

C代碼    收藏代碼
  1. struct virDomainInfo{  
  2. unsigned char state : //the running state, one of virDomainState    
  3. unsigned long maxMem :// the maximum memory in KBytes allowed   
  4. unsigned long memory :// the memory in KBytes used by the domain   
  5. unsigned short nrVirtCpu :// the number of virtual CPUs for the domain   
  6. unsigned long long cpuTime : //the CPU time used in nanoseconds   
  7. }  
  

獲取內存資源和計算資源監控信息並打印的方法如下:

C代碼    收藏代碼
  1. virDomainInfoPtr domaininfo;     
  2. domaininfo = malloc(sizeof(virDomainInfo)* 1);  
  3. m = virDomainGetInfo(allDomains[numOfDom] , domaininfo);  
  4. printf("狀態:%d    ",(*domaininfo).state);  
  5. printf("最大內存:%ld    ",((*domaininfo).maxMem)/1024);  
  6. printf("內存:%ld   ",((*domaininfo).memory)/1024);  
  7. printf("虛擬cpu個數:%d   ",(*domaininfo).nrVirtCpu);  
  8. printf("cpu時間:%lld   ",(*domaininfo).cpuTime);  

  

libvirt中並不能直接獲取到虛擬機的CPU使用率,但是可以通過CPUTIME來計算出實際使用率。計算的公式為:

首先得到一個周期差:cpu_time_diff = cpuTimenow — cpuTimet seconds ago

然后根據這個差值計算實際使用率:%CPU = 100 × cpu_time_diff / (t × nr_cores × 109)

 

cpuTime可以通過virDomainGetInfo(C)和virDomain::info()(Python)獲得

#include <stdio.h>
#include <sys/time.h>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>

int main(int argc, char ** argv) {
    virConnectPtr conn = virConnectOpen("qemu:///system");
    if(conn == NULL) {
        printf("error connecting qemu driver\n");
        exit(1);
    }
    virDomainPtr vm_ptr = virDomainLookupByName(conn, "1");
    if(vm_ptr == NULL) {
        printf("error finding domain\n");
        virConnectClose(conn);
        exit(1);
    }
    virDomainInfo info_s,info_e;
    struct timeval real_time_s, real_time_e;
    int cpu_diff, real_diff;
    float usage;
    while(true){
        if(virDomainGetInfo(vm_ptr, &info_s) !=0) {
            printf("error get domain info\n");
            virDomainFree(vm_ptr);
            virConnectClose(conn);
            exit(1);
        }

        if(gettimeofday(&real_time_s, NULL) == -1) {
            printf("error get time of day\n");
            virDomainFree(vm_ptr);
            virConnectClose(conn);
            exit(1);
        }

        sleep(1);
        
        if(virDomainGetInfo(vm_ptr, &info_e) !=0) {
            printf("error get domain info\n");
            virDomainFree(vm_ptr);
            virConnectClose(conn);
            exit(1);
        }

        if(gettimeofday(&real_time_e, NULL) == -1) {
            printf("error get time of day\n");
            virDomainFree(vm_ptr);
            virConnectClose(conn);
            exit(1);
        }//轉換成微秒
        cpu_diff = (info_e.cpuTime - info_s.cpuTime) / 1000;
        //轉換成微秒
        real_diff = 1000000 * (real_time_e.tv_sec - real_time_s.tv_sec) +
                    (real_time_e.tv_usec - real_time_s.tv_usec);
//是否要考慮多核的情況?
usage = cpu_diff / (float) (real_diff); printf("cpu_diff:%d, real_diff:%d, cpu usage:%f\n", cpu_diff, real_diff, usage); } virDomainFree(vm_ptr); virConnectClose(conn); return 0;

 

 

#include <stdio.h>
#include <sys/time.h>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>

int main(int argc, char ** argv) {
    virConnectPtr conn = virConnectOpen("qemu:///system");
    if(conn == NULL) {
        printf("error connecting qemu driver\n");
        exit(1);
    }
    virDomainPtr vm_ptr = virDomainLookupByName(conn, "1");
    if(vm_ptr == NULL) {
        printf("error finding domain\n");
        virConnectClose(conn);
        exit(1);
    }

    virTypedParameter par_s, par_e;
    struct timeval real_time_s, real_time_e;

    int cpu_diff, real_diff;
    float usage;

    while(true){
        if(gettimeofday(&real_time_s, NULL) == -1) {
            printf("error get time of day\n");
            virDomainFree(vm_ptr);
            virConnectClose(conn);
            exit(1);
        }
        virDomainGetCPUStats(vm_ptr, &par_s, 1, -1, 1, 0);
        sleep(1);
        if(gettimeofday(&real_time_e, NULL) == -1) {
            printf("error get time of day\n");
            virDomainFree(vm_ptr);
            virConnectClose(conn);
            exit(1);
        virDomainGetCPUStats(vm_ptr, &par_e, 1, -1, 1, 0);
        cpu_diff = (par_e.value.ul - par_s.value.ul) / 1000;
        real_diff = 1000000 * (real_time_e.tv_sec - real_time_s.tv_sec) +
                    (real_time_e.tv_usec - real_time_s.tv_usec);
        usage = cpu_diff / (float)(real_diff);
        printf("cpu_diff:%d, real_diff:%d, cpu usage:%f\n", cpu_diff, real_diff, usage);

    }
    virDomainFree(vm_ptr);
    virConnectClose(conn);
    return 0;
}

這兩個接口的結果差不多,利用率與top命令輸出一致,但是與虛擬機內部使用率不一致。如將結果除以vcpu個數,則cpu利用率更接近虛擬機內部的虛擬機使用率。

 對於memory利用率,windows需要安裝 virtio memory balloon drivers for Windows guests,這樣 memory/MaxMemory就是正確的內存利用率。如果不安裝,那么這個比例始終為1。

(二)獲得網絡流量信息

    可以使用 virDomainInterfaceStats方法,將一個domain的網絡流量信息封裝在一個virDomainInterfaceStatsStruct結構體中,該方法需要傳遞一個虛擬網卡接口的參數,這個參數可以通過XML文件取得:

<interface type='bridge'>
      <mac address='00:16:3e:74:03:53'/>
      <source bridge='xenbr0'/>
      <script path='vif-bridge'/>
      <target dev='vif1.0 '/>          /*這個就是需要的參數*/
    </interface>

具體代碼如下:

C代碼    收藏代碼
    1. virDomainInterfaceStatsPtr interfacestats;  
    2.   
    3. interfacestats = malloc(sizeof(virDomainInterfaceStatsStruct)* 10);  
    4. m = virDomainInterfaceStats(allDomains[numOfDom], i_path, interfacestats, 10);  
    5.  printf("rx字節數:%ld    ",(*interfacestats).rx_bytes);  
    6.  printf("tx字節數:%ld    ",(*interfacestats).tx_bytes);  
    7.  printf("rx丟包:%ld    ",(*interfacestats).rx_drop);  
    8.  printf("tx丟包:%ld\n",(*interfacestats).tx_drop); 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM