LCOV - code coverage report
Current view: top level - vnsw/agent/uve - vm_stat_kvm.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 205 0.0 %
Date: 2026-11-09 02:10:49 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <sys/times.h>
       7             : #include <sys/types.h>
       8             : #include <sys/wait.h>
       9             : #include <unistd.h>
      10             : #include <uve/vm_stat_kvm.h>
      11             : #include <uve/vm_stat_data.h>
      12             : #include <db/db.h>
      13             : #include <db/db_entry.h>
      14             : #include <db/db_table.h>
      15             : #include <base/address.h>
      16             : #include <ifmap/ifmap_agent_parser.h>
      17             : #include <cmn/agent.h>
      18             : #include <uve/vrouter_uve_entry.h>
      19             : #include <sstream>
      20             : #include <fstream>
      21             : #include <uve/agent_uve.h>
      22             : #include <uve/vm_uve_table.h>
      23             : 
      24             : using namespace boost::uuids;
      25             : using namespace boost::asio;
      26             : 
      27           0 : VmStatKvm::VmStatKvm(Agent *agent, const uuid &vm_uuid)
      28           0 :     : VmStat(agent, vm_uuid) {
      29           0 : }
      30             : 
      31           0 : VmStatKvm::~VmStatKvm() {
      32           0 : }
      33             : 
      34           0 : void VmStatKvm::ReadCpuStat() {
      35           0 :     std::string tmp;
      36             :     //Typical output from command
      37             :     //Id:             1
      38             :     //Name:           instance-00000001
      39             :     //UUID:           90cb7351-d2dc-4d8d-a216-2f460be183b6
      40             :     //OS Type:        hvm
      41             :     //State:          running
      42             :     //CPU(s):         1
      43             :     //CPU time:       13.4s
      44             :     //Max memory:     2097152 KiB
      45             : 
      46             :     //Get 'CPU time' from the output
      47           0 :     double cpu_stat = 0;
      48           0 :     std::string cpu_stat_str, state_str, cpu_count_str;
      49             : 
      50           0 :     while (data_ >> tmp) {
      51           0 :         if (tmp == "State:") {
      52           0 :             data_ >> state_str;
      53             :         }
      54           0 :         if (tmp == "CPU(s):") {
      55           0 :             data_ >> cpu_count_str;
      56             :         }
      57           0 :         if (tmp == "time:") {
      58           0 :             data_ >> cpu_stat_str;
      59             :             /* We expect 'State' and 'CPU(s)' fields to be present before
      60             :              * 'CPU time' field. So break from the loop when we are done with
      61             :              * reading of 'CPU time' field. */
      62           0 :             break;
      63             :         }
      64             :     }
      65             : 
      66           0 :     vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_UNKNOWN;
      67           0 :     if (state_str.size()) {
      68           0 :         if (state_str == "running") {
      69           0 :             vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_ACTIVE;
      70           0 :         } else if (state_str == "paused") {
      71           0 :             vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_PAUSED;
      72           0 :         } else if (state_str == "shut") {
      73           0 :             vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_SHUTDOWN;
      74             :         }
      75             :     }
      76           0 :     vm_cpu_count_ = kInvalidCpuCount;
      77           0 :     if (cpu_count_str.size()) {
      78           0 :         stringToInteger(cpu_count_str, vm_cpu_count_);
      79             :     }
      80             :     //Remove the last character from 'cpu_stat_str'
      81           0 :     if (cpu_stat_str.size() >= 2) {
      82           0 :         cpu_stat_str.erase(cpu_stat_str.size() - 1);
      83             :         //Convert string to double
      84           0 :         std::stringstream ss(cpu_stat_str);
      85           0 :         ss >> cpu_stat;
      86           0 :     }
      87             : 
      88             :     time_t now;
      89           0 :     time(&now);
      90           0 :     if (prev_cpu_snapshot_time_) {
      91           0 :         cpu_usage_ = (cpu_stat - prev_cpu_stat_)/
      92           0 :                      difftime(now, prev_cpu_snapshot_time_);
      93           0 :         cpu_usage_ *= 100;
      94             :     }
      95             : 
      96           0 :     prev_cpu_stat_ = cpu_stat;
      97           0 :     prev_cpu_snapshot_time_ = now;
      98             : 
      99             :     //Clear buffer
     100           0 :     data_.str(" ");
     101           0 :     data_.clear();
     102             : 
     103             :     //Trigger a request to start vcpu stat collection
     104           0 :     GetVcpuStat();
     105           0 : }
     106             : 
     107           0 : void VmStatKvm::ReadVcpuStat() {
     108           0 :     std::string tmp;
     109           0 :     uint32_t index = 0;
     110           0 :     std::vector<double> vcpu_usage;
     111             :     //Read latest VCPU usage time
     112           0 :     while(data_ >> tmp) {
     113           0 :         if (tmp == "VCPU:") {
     114             :             //Current VCPU index
     115           0 :             data_ >> index;
     116             :         }
     117             : 
     118           0 :         if (tmp == "time:") {
     119           0 :             double usage = 0;
     120           0 :             data_ >> usage;
     121           0 :             vcpu_usage.push_back(usage);
     122             :         }
     123             :     }
     124             : 
     125           0 :     vcpu_usage_percent_.clear();
     126           0 :     if (prev_vcpu_usage_.size() != vcpu_usage.size()) {
     127             :         //In case a new VCPU get added
     128           0 :         prev_vcpu_usage_ = vcpu_usage;
     129             :     }
     130             : 
     131             :     time_t now;
     132           0 :     time(&now);
     133             :     //Calculate VCPU usage
     134           0 :     if (prev_vcpu_snapshot_time_) {
     135           0 :         for (uint32_t i = 0; i < vcpu_usage.size(); i++) {
     136           0 :             double cpu_usage = (vcpu_usage[i] - prev_vcpu_usage_[i])/
     137           0 :                                difftime(now, prev_vcpu_snapshot_time_);
     138           0 :             cpu_usage *= 100;
     139           0 :             vcpu_usage_percent_.push_back(cpu_usage);
     140             :         }
     141             :     }
     142             : 
     143           0 :     prev_vcpu_usage_ = vcpu_usage;
     144           0 :     prev_vcpu_snapshot_time_ = now;
     145             : 
     146           0 :     data_.str(" ");
     147           0 :     data_.clear();
     148             :     //Trigger a request to start mem stat
     149           0 :     GetMemStat();
     150           0 : }
     151             : 
     152           0 : void VmStatKvm::ReadMemStat() {
     153           0 :     if (pid_) {
     154           0 :         std::ostringstream proc_file;
     155           0 :         proc_file << "/proc/"<<pid_<<"/status";
     156           0 :         std::ifstream file(proc_file.str().c_str());
     157             : 
     158           0 :         bool vmsize = false;
     159           0 :         bool peak = false;
     160           0 :         bool rss = false;
     161           0 :         std::string line;
     162           0 :         while (std::getline(file, line)) {
     163           0 :             if (line.find("VmSize") != std::string::npos) {
     164           0 :                 std::stringstream vm(line);
     165           0 :                 std::string tmp; vm >> tmp; vm >> virt_memory_;
     166           0 :                 vmsize = true;
     167           0 :             }
     168           0 :             if (line.find("VmRSS") != std::string::npos) {
     169           0 :                 std::stringstream vm(line);
     170           0 :                 std::string tmp;
     171           0 :                 vm >> tmp;
     172           0 :                 vm >> mem_usage_;
     173           0 :                 rss = true;
     174           0 :             }
     175           0 :             if (line.find("VmPeak") != std::string::npos) {
     176           0 :                 std::stringstream vm(line);
     177           0 :                 std::string tmp; vm >> tmp; vm >> virt_memory_peak_;
     178           0 :                 peak = true;
     179           0 :             }
     180           0 :             if (rss && vmsize && peak)
     181           0 :                 break;
     182             :         }
     183           0 :     }
     184             : 
     185           0 :     data_.str(" ");
     186           0 :     data_.clear();
     187           0 :     GetDiskName();
     188           0 : }
     189             : 
     190           0 : void VmStatKvm::GetCpuStat() {
     191           0 :     std::ostringstream cmd;
     192           0 :     cmd << "virsh dominfo " << agent_->GetUuidStr(vm_uuid_);
     193           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatKvm::ReadCpuStat, this));
     194           0 : }
     195             : 
     196           0 : void VmStatKvm::GetVcpuStat() {
     197           0 :     std::ostringstream cmd;
     198           0 :     cmd << "virsh vcpuinfo " << agent_->GetUuidStr(vm_uuid_);
     199           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatKvm::ReadVcpuStat, this));
     200           0 : }
     201             : 
     202           0 : void VmStatKvm::GetMemStat() {
     203           0 :     ReadMemStat();
     204           0 : }
     205             : 
     206           0 : void VmStatKvm::GetDiskName() {
     207           0 :     std::ostringstream cmd;
     208           0 :     cmd << "virsh domblklist " << agent_->GetUuidStr(vm_uuid_) << " | grep "
     209           0 :         << agent_->GetUuidStr(vm_uuid_);
     210           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatKvm::ReadDiskName, this));
     211           0 : }
     212             : 
     213           0 : void VmStatKvm::ReadDiskName() {
     214           0 :     data_ >> disk_name_;
     215           0 :     if (!disk_name_.empty()) {
     216           0 :         GetDiskStat();
     217             :     } else {
     218           0 :         SendVmCpuStats();
     219           0 :         StartTimer();
     220             :     }
     221           0 : }
     222             : 
     223           0 : void VmStatKvm::GetDiskStat() {
     224           0 :     std::ostringstream cmd;
     225           0 :     cmd << "virsh domblkinfo " << agent_->GetUuidStr(vm_uuid_) << " "
     226           0 :         << disk_name_;
     227           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatKvm::ReadDiskStat, this));
     228           0 : }
     229             : 
     230           0 : void VmStatKvm::ReadDiskStat() {
     231           0 :     bool disk_size_found = false, virtual_size_found = false;
     232           0 :     std::string tmp;
     233           0 :     std::string virtual_size_str, disk_size_str;
     234           0 :     while (data_ >> tmp) {
     235           0 :         if (tmp == "Capacity:") {
     236           0 :             data_ >> virtual_size_str;
     237           0 :             virtual_size_found = true;
     238           0 :         } else if (tmp == "Allocation:") {
     239           0 :             data_ >> disk_size_str;
     240           0 :             disk_size_found = true;
     241             :         }
     242           0 :         if (virtual_size_found && disk_size_found) {
     243           0 :             break;
     244             :         }
     245             :     }
     246           0 :     if (virtual_size_str.size() >= 2) {
     247             :         //Convert string to uint32_t
     248           0 :         std::stringstream ss(virtual_size_str);
     249           0 :         ss >> virtual_size_;
     250           0 :     }
     251             : 
     252           0 :     if (disk_size_str.size() >= 2) {
     253             :         //Convert string to uint32_t
     254           0 :         std::stringstream ss(disk_size_str);
     255           0 :         ss >> disk_size_;
     256           0 :     }
     257             : 
     258           0 :     SendVmCpuStats();
     259           0 :     StartTimer();
     260           0 : }
     261             : 
     262           0 : void VmStatKvm::ReadMemoryQuota() {
     263           0 :     std::string tmp;
     264           0 :     while (data_ >> tmp) {
     265           0 :         if (tmp == "actual") {
     266           0 :             data_ >> vm_memory_quota_;
     267             :         }
     268             :     }
     269           0 :     GetCpuStat();
     270           0 : }
     271             : 
     272           0 : void VmStatKvm::GetMemoryQuota() {
     273           0 :     std::ostringstream cmd;
     274           0 :     cmd << "virsh dommemstat " << agent_->GetUuidStr(vm_uuid_);
     275           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatKvm::ReadMemoryQuota, this));
     276           0 : }
     277             : 
     278           0 : bool VmStatKvm::TimerExpiry() {
     279           0 :     if (pid_ == 0) {
     280           0 :         GetPid();
     281             :     } else {
     282             :         //Get CPU and memory stats
     283           0 :         GetCpuStat();
     284             :     }
     285           0 :     return false;
     286             : }
     287             : 
     288           0 : void VmStatKvm::ReadPid() {
     289           0 :     std::string tmp;
     290             :     uint32_t pid;
     291             : 
     292           0 :     while (data_) {
     293           0 :         data_ >> pid;
     294           0 :         data_ >> tmp;
     295           0 :         if (tmp.find("qemu") != std::string::npos ||
     296           0 :                tmp.find("kvm") != std::string::npos) {
     297             :             //Copy PID
     298           0 :             pid_ = pid;
     299           0 :             break;
     300             :         }
     301             :         //Flush out this line
     302           0 :         data_.ignore(512, '\n');
     303             :     }
     304             : 
     305           0 :     data_.str(" ");
     306           0 :     data_.clear();
     307           0 :     if (pid_) {
     308             :         //Successfully read pid of process, collect other data
     309           0 :         GetMemoryQuota();
     310             :     } else {
     311           0 :         retry_++;
     312             :         //Retry after timeout
     313           0 :         if (retry_ < kRetryCount) {
     314           0 :             StartTimer();
     315             :         }
     316             :     }
     317           0 : }
     318             : 
     319           0 : void VmStatKvm::GetPid() {
     320           0 :     std::ostringstream cmd;
     321           0 :     cmd << "ps -eo pid,cmd | grep " << agent_->GetUuidStr(vm_uuid_)
     322           0 :         << " | grep instance-";
     323           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatKvm::ReadPid, this));
     324           0 : }
     325             : 
     326           0 : void VmStatKvm::Start() {
     327           0 :     GetPid();
     328           0 : }

Generated by: LCOV version 1.14