• 使用libvirt技术监控虚拟机资源利用情况


    使用libvirt技术监控虚拟机资源利用情况

    (一)计算资源与内存资源的监控

    libvirt中提供virDomainGetInfo方法可以将一个domain的计算资源和内存资源的使用情况封装在一个结构体中,如下:

    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. }  
      

    获取内存资源和计算资源监控信息并打印的方法如下:

    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
    ");
            exit(1);
        }
        virDomainPtr vm_ptr = virDomainLookupByName(conn, "1");
        if(vm_ptr == NULL) {
            printf("error finding domain
    ");
            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
    ");
                virDomainFree(vm_ptr);
                virConnectClose(conn);
                exit(1);
            }
    
            if(gettimeofday(&real_time_s, NULL) == -1) {
                printf("error get time of day
    ");
                virDomainFree(vm_ptr);
                virConnectClose(conn);
                exit(1);
            }
    
            sleep(1);
            
            if(virDomainGetInfo(vm_ptr, &info_e) !=0) {
                printf("error get domain info
    ");
                virDomainFree(vm_ptr);
                virConnectClose(conn);
                exit(1);
            }
    
            if(gettimeofday(&real_time_e, NULL) == -1) {
                printf("error get time of day
    ");
                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 ", 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
    ");
            exit(1);
        }
        virDomainPtr vm_ptr = virDomainLookupByName(conn, "1");
        if(vm_ptr == NULL) {
            printf("error finding domain
    ");
            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
    ");
                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
    ");
                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
    ", 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>

    具体代码如下:

      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 ",(*interfacestats).tx_drop);
  • 相关阅读:
    利用pyinotify监控文件内容,像tailf命令但比它更强
    AWS SDK for C++调用第三方S3 API
    Windows 10恢复Shift+右键打开命令提示符窗口
    TP-LINK WR841N V8刷OpenWRT
    Build subversion 1.8 with SSL on OS X Yosemite
    OpenWrt自定义和官方一样的固件
    Windows 10下通过蓝牙连接iPhone个人热点进行共享上网
    Broadcom有线网卡在Windows 8/8.1/10下使用系统自带驱动会断网的解决办法
    BCM94352HMB蓝牙BCM20702A0在Ubuntu 14.04下的驱动方法
    Spring Boot 发送邮件
  • 原文地址:https://www.cnblogs.com/ruiy/p/6296874.html
Copyright © 2020-2023  润新知