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

Generated by: LCOV version 1.14