LCOV - code coverage report
Current view: top level - vnsw/agent/uve - vm_stat_docker.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 142 0.0 %
Date: 2026-08-03 02:19:58 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 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_docker.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 : VmStatDocker::VmStatDocker(Agent *agent, const uuid &vm_uuid)
      27           0 :     : VmStat(agent, vm_uuid), container_id_() {
      28           0 : }
      29             : 
      30           0 : VmStatDocker::~VmStatDocker() {
      31           0 : }
      32             : 
      33           0 : void VmStatDocker::Start() {
      34           0 :     if (vm_uuid_ == nil_uuid()) {
      35           0 :         return;
      36             :     }
      37           0 :     GetContainerId();
      38             : }
      39             : 
      40           0 : void VmStatDocker::ReadCpuStat() {
      41           0 :     double cpu_stat = 0;
      42           0 :     std::string cpu_stat_str;
      43           0 :     data_ >> cpu_stat_str;
      44             : 
      45           0 :     if (!cpu_stat_str.empty()) {
      46             :         //Convert string to double
      47           0 :         std::stringstream ss(cpu_stat_str);
      48           0 :         ss >> cpu_stat;
      49             :         //Convert from Nanoseconds to seconds
      50           0 :         cpu_stat = cpu_stat / kOneSecInNanoSecs;
      51           0 :     }
      52             : 
      53             :     time_t now;
      54           0 :     time(&now);
      55           0 :     if (prev_cpu_snapshot_time_) {
      56           0 :         cpu_usage_ = (cpu_stat - prev_cpu_stat_)/
      57           0 :                      difftime(now, prev_cpu_snapshot_time_);
      58           0 :         cpu_usage_ *= 100;
      59             :     }
      60             : 
      61           0 :     prev_cpu_stat_ = cpu_stat;
      62           0 :     prev_cpu_snapshot_time_ = now;
      63             : 
      64             :     //Clear buffer
      65           0 :     data_.str(" ");
      66           0 :     data_.clear();
      67             : 
      68             :     //Trigger a request to start Memory stat collection
      69           0 :     GetMemoryQuota();
      70           0 : }
      71             : 
      72           0 : void VmStatDocker::ReadMemStat() {
      73           0 :     if (pid_) {
      74           0 :         std::ostringstream proc_file;
      75           0 :         proc_file << "/proc/"<<pid_<<"/status";
      76           0 :         std::ifstream file(proc_file.str().c_str());
      77             : 
      78           0 :         bool vmsize = false;
      79           0 :         bool rss = false;
      80           0 :         bool peak = false;
      81           0 :         std::string line;
      82           0 :         while (std::getline(file, line)) {
      83           0 :             if (line.find("VmSize") != std::string::npos) {
      84           0 :                 std::stringstream vm(line);
      85           0 :                 std::string tmp; vm >> tmp; vm >> virt_memory_;
      86           0 :                 vmsize = true;
      87           0 :             }
      88           0 :             if (line.find("VmRSS") != std::string::npos) {
      89           0 :                 std::stringstream vm(line);
      90           0 :                 std::string tmp;
      91           0 :                 vm >> tmp;
      92           0 :                 vm >> mem_usage_;
      93           0 :                 rss = true;
      94           0 :             }
      95           0 :             if (line.find("VmPeak") != std::string::npos) {
      96           0 :                 std::stringstream vm(line);
      97           0 :                 std::string tmp; vm >> tmp; vm >> virt_memory_peak_;
      98           0 :                 peak = true;
      99           0 :             }
     100           0 :             if (rss && vmsize && peak)
     101           0 :                 break;
     102             :         }
     103           0 :     }
     104             : 
     105           0 :     data_.str(" ");
     106           0 :     data_.clear();
     107             : 
     108           0 :     SendVmCpuStats();
     109           0 :     StartTimer();
     110           0 : }
     111             : 
     112           0 : void VmStatDocker::GetCpuStat() {
     113           0 :     std::ostringstream cmd;
     114           0 :     cmd << "cat /sys/fs/cgroup/cpuacct/docker/" << container_id_
     115           0 :         << "/cpuacct.usage";
     116           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatDocker::ReadCpuStat, this));
     117           0 : }
     118             : 
     119           0 : void VmStatDocker::GetMemoryQuota() {
     120           0 :     std::ostringstream cmd;
     121           0 :     cmd << "cat /sys/fs/cgroup/memory/docker/" << container_id_
     122           0 :         << "/memory.stat";
     123           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatDocker::ReadMemoryQuota, this));
     124           0 : }
     125             : 
     126           0 : void VmStatDocker::GetMemStat() {
     127           0 :     ReadMemStat();
     128           0 : }
     129             : 
     130           0 : void VmStatDocker::GetPid() {
     131           0 :     std::ostringstream cmd;
     132           0 :     cmd << "docker inspect " << container_id_ << "| grep -A3 \\\"Paused\\\":";
     133           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatDocker::ReadPid, this));
     134           0 : }
     135             : 
     136           0 : void VmStatDocker::ReadPid() {
     137             :     /* Expecting data_ to have the following content
     138             :      *     "Paused": false,
     139             :      *     "Pid": 24430,
     140             :      *     "Restarting": false,
     141             :      *     "Running": true,
     142             :      */
     143           0 :     string tmp, paused_str, pid_str, running_str;
     144           0 :     while (data_ >> tmp) {
     145           0 :         if (tmp.find("Paused") != std::string::npos) {
     146           0 :             data_ >> paused_str;
     147             :         }
     148           0 :         if (tmp.find("Pid") != std::string::npos) {
     149           0 :             data_ >> pid_str;
     150             :         }
     151           0 :         if (tmp.find("Running") != std::string::npos) {
     152           0 :             data_ >> running_str;
     153           0 :             break;
     154             :         }
     155             :     }
     156             : 
     157             :     //Remove the last character from 'pid_str'
     158           0 :     if (pid_str.size() >= 2) {
     159           0 :         pid_str.erase(pid_str.size() - 1);
     160             :         //Convert string to uint32_t
     161           0 :         std::stringstream ss(pid_str);
     162           0 :         ss >> pid_;
     163           0 :     }
     164             : 
     165           0 :     vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_UNKNOWN;
     166           0 :     if (paused_str == "true,") {
     167           0 :         vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_PAUSED;
     168           0 :     } else if (running_str == "false,") {
     169           0 :         vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_SHUTDOWN;
     170           0 :     } else if (running_str == "true,") {
     171           0 :         vm_state_ = VrouterAgentVmState::VROUTER_AGENT_VM_ACTIVE;
     172             :     }
     173           0 :     data_.str(" ");
     174           0 :     data_.clear();
     175           0 :     GetMemStat();
     176           0 : }
     177             : 
     178           0 : void VmStatDocker::ReadMemoryQuota() {
     179           0 :     std::string tmp;
     180           0 :     while (data_ >> tmp) {
     181           0 :         if (tmp == "hierarchical_memory_limit") {
     182           0 :             data_ >> vm_memory_quota_;
     183             :             /* Convert the 'vm_memory_quota_' to KiB to make it consistent with
     184             :                Kvm's 'vm_memory_quota_' */
     185           0 :             vm_memory_quota_/= 1024;
     186           0 :             break;
     187             :         }
     188             :     }
     189             : 
     190           0 :     data_.str(" ");
     191           0 :     data_.clear();
     192           0 :     GetPid();
     193           0 : }
     194             : 
     195           0 : bool VmStatDocker::TimerExpiry() {
     196           0 :     if (container_id_.empty()) {
     197           0 :         GetContainerId();
     198             :     } else {
     199             :         //Get CPU and memory stats
     200           0 :         GetCpuStat();
     201             :     }
     202           0 :     return false;
     203             : }
     204             : 
     205           0 : void VmStatDocker::ReadContainerId() {
     206           0 :     data_ >> container_id_;
     207             :     //Clear buffer
     208           0 :     data_.str(" ");
     209           0 :     data_.clear();
     210             : 
     211           0 :     if (!container_id_.empty()) {
     212             :         //Successfully read container-id, collect other data
     213           0 :         GetCpuStat();
     214             :     } else {
     215           0 :         retry_++;
     216             :         //Retry after timeout
     217           0 :         if (retry_ < kRetryCount) {
     218           0 :             StartTimer();
     219             :         }
     220             :     }
     221           0 : }
     222             : 
     223           0 : void VmStatDocker::GetContainerId() {
     224           0 :     std::ostringstream cmd;
     225           0 :     cmd << "docker ps --no-trunc | grep " << agent_->GetUuidStr(vm_uuid_)
     226           0 :         << " | awk '{ print $1 }'";
     227           0 :     ExecCmd(cmd.str(), boost::bind(&VmStatDocker::ReadContainerId, this));
     228           0 : }

Generated by: LCOV version 1.14