LCOV - code coverage report
Current view: top level - vnsw/agent/uve - vm_stat.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 125 0.0 %
Date: 2026-11-09 02:10:49 Functions: 0 13 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.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 <init/agent_param.h>
      19             : #include <uve/vrouter_uve_entry.h>
      20             : #include <sstream>
      21             : #include <fstream>
      22             : #include <uve/agent_uve.h>
      23             : #include <uve/vm_uve_table.h>
      24             : 
      25             : using namespace boost::uuids;
      26             : using namespace boost::asio;
      27             : 
      28           0 : VmStat::VmStat(Agent *agent, const uuid &vm_uuid):
      29           0 :     agent_(agent), vm_uuid_(vm_uuid), mem_usage_(0),
      30           0 :     virt_memory_(0), virt_memory_peak_(0), vm_memory_quota_(0),
      31           0 :     prev_cpu_stat_(0), cpu_usage_(0),
      32           0 :     prev_cpu_snapshot_time_(0), prev_vcpu_snapshot_time_(0),
      33           0 :     input_(*(agent_->event_manager()->io_service())),
      34           0 :     timer_(TimerManager::CreateTimer(*(agent_->event_manager())->io_service(),
      35           0 :     "VmStatTimer")), marked_delete_(false), pid_(0), retry_(0), virtual_size_(0),
      36           0 :     disk_size_(0), disk_name_(),
      37           0 :     vm_state_(VrouterAgentVmState::VROUTER_AGENT_VM_UNKNOWN),
      38           0 :     prev_vm_state_(VrouterAgentVmState::VROUTER_AGENT_VM_UNKNOWN),
      39           0 :     vm_cpu_count_(kInvalidCpuCount), prev_vm_cpu_count_(kInvalidCpuCount) {
      40           0 : }
      41             : 
      42           0 : VmStat::~VmStat() {
      43           0 :     TimerManager::DeleteTimer(timer_);
      44           0 : }
      45             : 
      46           0 : void VmStat::ReadData(const boost::system::error_code &ec,
      47             :                       size_t read_bytes, DoneCb &cb) {
      48           0 :     if (read_bytes) {
      49           0 :         data_<< rx_buff_;
      50             :     }
      51             : 
      52           0 :     if (ec) {
      53           0 :         boost::system::error_code close_ec;
      54           0 :         input_.close(close_ec);
      55           0 :         call_back_ = cb;
      56             :         //Enqueue a request to process data
      57           0 :         VmStatData *vm_stat_data = new VmStatData(this);
      58             : 
      59             :         VmUveTable *vmt = static_cast<VmUveTable *>
      60           0 :             (agent_->uve()->vm_uve_table());
      61           0 :         vmt->EnqueueVmStatData(vm_stat_data);
      62             :     } else {
      63           0 :         bzero(rx_buff_, sizeof(rx_buff_));
      64           0 :         async_read(input_, boost::asio::buffer(rx_buff_, kBufLen),
      65           0 :                    boost::bind(&VmStat::ReadData, this, placeholders::error,
      66             :                    placeholders::bytes_transferred, cb));
      67             :     }
      68           0 : }
      69             : 
      70           0 : void VmStat::ProcessData() {
      71           0 :     if (!call_back_.empty())
      72           0 :         call_back_();
      73           0 : }
      74             : 
      75           0 : void VmStat::ExecCmd(std::string cmd, DoneCb cb) {
      76             :     char *argv[4];
      77           0 :     char shell[80] = "/bin/sh";
      78           0 :     char option[80] = "-c";
      79             :     char ccmd[256];
      80           0 :     memset(ccmd, 0, sizeof(ccmd));
      81           0 :     strncpy(ccmd, cmd.c_str(), sizeof(ccmd)-1);
      82             : 
      83           0 :     argv[0] = shell;
      84           0 :     argv[1] = option;
      85           0 :     argv[2] = ccmd;
      86           0 :     argv[3] = 0;
      87             : 
      88             :     int out[2];
      89           0 :     if (pipe(out) < 0) {
      90           0 :         return;
      91             :     }
      92             : 
      93           0 :     if (vfork() == 0) {
      94             :         //Close read end of pipe
      95           0 :         close(out[0]);
      96           0 :         dup2(out[1], STDOUT_FILENO);
      97             :         //Close out[1] as stdout is a exact replica of out[1]
      98           0 :         close(out[1]);
      99             : 
     100             :         /* Close all the open fds before execvp */
     101           0 :         CloseTaskFds();
     102           0 :         execvp(argv[0], argv);
     103           0 :         perror("execvp");
     104           0 :         exit(127);
     105             :     }
     106             : 
     107             :     //Close write end of pipe
     108           0 :     close(out[1]);
     109             : 
     110           0 :     boost::system::error_code ec;
     111           0 :     int fd = ::dup(out[0]);
     112           0 :     close(out[0]);
     113           0 :     if (fd == -1) {
     114           0 :         return;
     115             :     }
     116           0 :     input_.assign(fd, ec);
     117           0 :     if (ec) {
     118           0 :         close(fd);
     119           0 :         return;
     120             :     }
     121             : 
     122           0 :     bzero(rx_buff_, sizeof(rx_buff_));
     123           0 :     async_read(input_, boost::asio::buffer(rx_buff_, kBufLen),
     124           0 :                boost::bind(&VmStat::ReadData, this, placeholders::error,
     125             :                            placeholders::bytes_transferred, cb));
     126             : }
     127             : 
     128           0 : bool VmStat::BuildVmStatsMsg(VirtualMachineStats *uve) {
     129           0 :     uve->set_name(UuidToString(vm_uuid_));
     130             : 
     131           0 :     std::vector<VmCpuStats> cpu_stats_list;
     132           0 :     VmCpuStats stats;
     133           0 :     stats.set_cpu_one_min_avg(cpu_usage_);
     134           0 :     stats.set_vm_memory_quota(vm_memory_quota_);
     135           0 :     stats.set_rss(mem_usage_);
     136           0 :     stats.set_virt_memory(virt_memory_);
     137           0 :     stats.set_peak_virt_memory(virt_memory_peak_);
     138           0 :     stats.set_disk_allocated_bytes(virtual_size_);
     139           0 :     stats.set_disk_used_bytes(disk_size_);
     140             : 
     141             : 
     142           0 :     cpu_stats_list.push_back(stats);
     143           0 :     uve->set_cpu_stats(cpu_stats_list);
     144             : 
     145           0 :     return true;
     146           0 : }
     147             : 
     148           0 : bool VmStat::BuildVmMsg(UveVirtualMachineAgent *uve) {
     149           0 :     uve->set_name(UuidToString(vm_uuid_));
     150             : 
     151           0 :     VmCpuStats stats;
     152           0 :     stats.set_cpu_one_min_avg(cpu_usage_);
     153           0 :     stats.set_vm_memory_quota(vm_memory_quota_);
     154           0 :     stats.set_rss(mem_usage_);
     155           0 :     stats.set_virt_memory(virt_memory_);
     156           0 :     stats.set_peak_virt_memory(virt_memory_peak_);
     157           0 :     stats.set_disk_allocated_bytes(virtual_size_);
     158           0 :     stats.set_disk_used_bytes(disk_size_);
     159             : 
     160           0 :     uve->set_cpu_info(stats);
     161             : 
     162           0 :     vnsConstants vns;
     163           0 :     if (vm_state_ != VrouterAgentVmState::VROUTER_AGENT_VM_UNKNOWN) {
     164           0 :         if (vm_state_ != prev_vm_state_) {
     165           0 :             uve->set_vm_state(vns.VrouterAgentVmStateMap.at(vm_state_));
     166           0 :             prev_vm_state_ = vm_state_;
     167             :         }
     168             :     }
     169             : 
     170           0 :     if (vm_cpu_count_ != kInvalidCpuCount) {
     171           0 :         if (vm_cpu_count_ != prev_vm_cpu_count_) {
     172           0 :             uve->set_vm_cpu_count(vm_cpu_count_);
     173           0 :             prev_vm_cpu_count_ = vm_cpu_count_;
     174             :         }
     175             :     }
     176             : 
     177           0 :     return true;
     178           0 : }
     179             : 
     180           0 : void VmStat::SendVmCpuStats() {
     181             :     //We need to send same cpu info in two different UVEs
     182             :     //(VirtualMachineStats and UveVirtualMachineAgent). One of them uses
     183             :     //stats-oracle infra and other one does not use it. We need two because
     184             :     //stats-oracle infra returns only SUM of cpu-info over a period of time
     185             :     //and current value is returned using non-stats-oracle version. Using
     186             :     //stats oracle infra we can still query the current value but for simpler
     187             :     //interface we are sending current value in separate UVE.
     188             :     //Also the non-stats oracle version has additional fields of vm_state and
     189             :     //vm_cpu_count which are not sent in stats-oracle version.
     190           0 :     VirtualMachineStats vm_agent;
     191           0 :     if (BuildVmStatsMsg(&vm_agent)) {
     192             :         VmUveTable *vmt = static_cast<VmUveTable *>
     193           0 :             (agent_->uve()->vm_uve_table());
     194           0 :         vmt->DispatchVmStatsMsg(vm_agent);
     195             :     }
     196           0 :     UveVirtualMachineAgent vm_msg;
     197           0 :     if (BuildVmMsg(&vm_msg)) {
     198           0 :         agent_->uve()->vm_uve_table()->DispatchVmMsg(vm_msg);
     199             :     }
     200           0 : }
     201             : 
     202           0 : bool VmStat::TimerExpiry() {
     203           0 :     return false;
     204             : }
     205             : 
     206           0 : void VmStat::StartTimer() {
     207           0 :     timer_->Cancel();
     208           0 :     timer_->Start(agent_->params()->vmi_vm_vn_uve_interval_msecs(),
     209             :                   boost::bind(&VmStat::TimerExpiry, this));
     210           0 : }
     211             : 
     212           0 : void VmStat::Start() {
     213           0 : }
     214             : 
     215           0 : void VmStat::Stop() {
     216           0 :     marked_delete_ = true;
     217           0 :     if (timer_->running() || retry_ == kRetryCount) {
     218             :         //If timer is fired, then we are in middle of
     219             :         //vm stat collection, in such case dont delete the vm stat
     220             :         //entry as asio may be using it
     221           0 :         delete this;
     222             :     }
     223           0 : }

Generated by: LCOV version 1.14