Skip to content

Commit

Permalink
[SMAGENT-1855] Docker engine support for cpuset usage (#1473)
Browse files Browse the repository at this point in the history
Parses the CpusetCpus value from the docker socket, parses it to count the number of cpus and stores the value with the other container data.
  • Loading branch information
bryanseay authored Aug 19, 2019
1 parent 3a39ac9 commit 017a25e
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 1 deletion.
136 changes: 136 additions & 0 deletions userspace/libsinsp/cgroup_list_counter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#pragma once

#include <stdexcept>
#include "logger.h"

namespace libsinsp
{

/**
* Simple helper to read a comma-separated list that includes ranges and
* determine the total count of the values within.
* Examples: 1,4-5 = 3; 0-15 = 16; 3,7,11 = 3
*
* See the "List Format" section of
* http://man7.org/linux/man-pages/man7/cpuset.7.html
*
* Returns -1 if string is invalid.
*/
class cgroup_list_counter
{
public:
const int INVALID_CPU_COUNT = -1;

/**
* Return the number of elements given by the buffer. If needed, log at the
* given log-level.
*/
int operator ()(const char *buffer, sinsp_logger::severity log_level)
{
reset();

int cpu_count = 0;

try
{
const char *position = buffer;
for(; '\0' != *position; ++position)
{
if ('-' == *position)
{
if (nullptr == m_section_start)
{
throw std::runtime_error("duplicate range indicator before start");
}
if (nullptr != m_range_indicator)
{
throw std::runtime_error("duplicate range indicators");
}

m_range_indicator = position;
}
else if (',' == *position)
{
cpu_count += process_section(m_section_start, position, m_range_indicator);
reset();
}
else if (nullptr == m_section_start)
{
m_section_start = position;
}

}

// There is never a trailing comma so always process the
// final section
cpu_count += process_section(m_section_start, position, m_range_indicator);

}
catch (const std::exception& ex)
{
g_logger.format(log_level,
"Invalid List Format: %s. Detail: %s",
buffer,
ex.what());
return INVALID_CPU_COUNT;
}

return cpu_count;
}

private:

static int process_number(const char *section_start, const char *section_end)
{
std::string section(section_start, section_end - section_start);
return std::stoi(section.c_str());

}

static int process_section(const char *section_start, const char *section_end, const char *range_indicator)
{
if (nullptr == section_start)
{
throw std::runtime_error("invalid end of section before start of section");
}

if (nullptr == section_end)
{
throw std::runtime_error("invalid end of section");
}

if (section_end <= section_start)
{
throw std::runtime_error("invalid section");
}

if (range_indicator)
{
// Split into two sections
int first = process_number(section_start, range_indicator);
int second = process_number(range_indicator + 1, section_end);

if (second <= first)
{
throw std::runtime_error("invalid range");
}

return second - first + 1;
}

// We don't care what the value is, we just want to know that it is a number
(void)process_number(section_start, section_end);
return 1;
}

void reset()
{
m_section_start = nullptr;
m_range_indicator = nullptr;
}

const char *m_section_start = nullptr;
const char *m_range_indicator = nullptr;
};

}
1 change: 1 addition & 0 deletions userspace/libsinsp/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ string sinsp_container_manager::container_to_json(const sinsp_container_info& co
container["cpu_shares"] = (Json::Value::Int64) container_info.m_cpu_shares;
container["cpu_quota"] = (Json::Value::Int64) container_info.m_cpu_quota;
container["cpu_period"] = (Json::Value::Int64) container_info.m_cpu_period;
container["cpuset_cpu_count"] = (Json::Value::Int) container_info.m_cpuset_cpu_count;

if(!container_info.m_mesos_task_id.empty())
{
Expand Down
9 changes: 8 additions & 1 deletion userspace/libsinsp/container_engine/docker_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
*/

#include "container_engine/docker.h"
#include "cgroup_list_counter.h"
#include "sinsp.h"
#include "sinsp_int.h"
#include "container.h"
Expand Down Expand Up @@ -739,7 +740,13 @@ bool docker_async_source::parse_docker(std::string &container_id, sinsp_containe
{
container->m_cpu_period = cpu_period;
}
const Json::Value &privileged = host_config_obj["Privileged"];
const auto cpuset_cpus = host_config_obj["CpusetCpus"].asString();
if (!cpuset_cpus.empty())
{
libsinsp::cgroup_list_counter counter;
container->m_cpuset_cpu_count = counter(cpuset_cpus.c_str(), sinsp_logger::SEV_DEBUG);
}
const Json::Value& privileged = host_config_obj["Privileged"];
if(!privileged.isNull() && privileged.isBool())
{
container->m_privileged = privileged.asBool();
Expand Down
2 changes: 2 additions & 0 deletions userspace/libsinsp/container_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ class sinsp_container_info
m_cpu_shares(1024),
m_cpu_quota(0),
m_cpu_period(100000),
m_cpuset_cpu_count(0),
m_is_pod_sandbox(false),
m_metadata_complete(true),
m_metadata_deadline(0)
Expand Down Expand Up @@ -223,6 +224,7 @@ class sinsp_container_info
int64_t m_cpu_shares;
int64_t m_cpu_quota;
int64_t m_cpu_period;
int32_t m_cpuset_cpu_count;
std::list<container_health_probe> m_health_probes;

bool m_is_pod_sandbox;
Expand Down
6 changes: 6 additions & 0 deletions userspace/libsinsp/parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4708,6 +4708,12 @@ void sinsp_parser::parse_container_json_evt(sinsp_evt *evt)
container_info.m_cpu_period = cpu_period.asInt64();
}

const Json::Value& cpuset_cpu_count = container["cpuset_cpu_count"];
if(check_json_val_is_convertible(cpuset_cpu_count, Json::intValue, "cpuset_cpu_count"))
{
container_info.m_cpuset_cpu_count = cpuset_cpu_count.asInt();
}

const Json::Value& mesos_task_id = container["mesos_task_id"];
if(check_json_val_is_convertible(mesos_task_id, Json::stringValue, "mesos_task_id"))
{
Expand Down

0 comments on commit 017a25e

Please sign in to comment.