1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-08 21:17:43 +03:00

B #6027: Parse host NUMA monitoring (#2440)

Co-authored-by: Ruben S. Montero <rsmontero@opennebula.org>
This commit is contained in:
Pavel Czerný 2023-01-09 18:29:09 +01:00 committed by GitHub
parent bc0caa82f3
commit 0696693531
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 297 additions and 48 deletions

View File

@ -18,6 +18,8 @@
#include "Template.h"
class ObjectXML;
/**
* CapacityMonitoring stores host monitoring values like
* - FREE_CPU
@ -56,6 +58,44 @@ public:
int from_template(const Template &tmpl);
};
class NUMAMonitoringNode : public Template
{
public:
NUMAMonitoringNode()
: Template(false, '=', "NUMA_NODE")
{}
};
/**
* NUMA stores hugepages and memory monitoring
* <NUMA_NODE>
* <ID>
* <HUGEPAGE>
* <SIZE>
* <FREE>
* <MEMORY>
* <FREE>
* <USED>
*/
class NUMAMonitoring
{
public:
NUMAMonitoring() = default;
std::string to_xml() const;
int from_xml(ObjectXML& xml, const std::string& xpath_prefix);
int from_template(const Template &tmpl);
private:
void set_huge_page(unsigned int node_id, unsigned long size, unsigned long fr);
void set_memory(unsigned int node_id, unsigned long used, unsigned long fr);
std::map<unsigned int, NUMAMonitoringNode> nodes;
};
/**
* HostMonitoringTemplate stores all host monitoring info, divided to 3 main sections:
* - capacity
@ -89,6 +129,7 @@ private:
CapacityMonitoring capacity;
SystemMonitoring system;
NUMAMonitoring numa;
};
#endif // HOST_MONITORING_TEMPLATE_H_

View File

@ -31,18 +31,21 @@
/**
* This class represents the NUMA nodes in a hypervisor for the following attr:
* NODE_ID = 0
* HUGEPAGE = [ SIZE = "2048", PAGES = "0", FREE = "0"]
* HUGEPAGE = [ SIZE = "1048576", PAGES = "0", FREE = "0"]
* CORE = [ ID = "3", CPUS = "3:-1,7:-1", FREE = 2]
* CORE = [ ID = "1", CPUS = "1:23,5:-1", FREE = 0 ]
* CORE = [ ID = "2", CPUS = "2:47,6:-1", FREE = 1]
* CORE = [ ID = "0", CPUS = "0:23,4:-1", FREE = 0]
* MEMORY = [ TOTAL = "66806708", FREE = "390568", USED = "66416140",
* DISTANCE = "0 1", USAGE = "8388608" ]
* HUGEPAGE = [ SIZE = "2048", PAGES = "0", USAGE = "0" ]
* HUGEPAGE = [ SIZE = "1048576", PAGES = "0", USAGE = "0" ]
* CORE = [ ID = "3", CPUS = "3:-1,7:-1", FREE = 2, DEDICATED="NO"]
* CORE = [ ID = "1", CPUS = "1:23,5:-1", FREE = 0, DEDICATED="YES" ]
* CORE = [ ID = "2", CPUS = "2:47,6:-1", FREE = 1, DEDICATED="NO"]
* CORE = [ ID = "0", CPUS = "0:23,4:-1", FREE = 0, DEDICATED="NO"]
* MEMORY = [ TOTAL = "66806708", DISTANCE = "0 1", USAGE = "8388608" ]
*
* - NODE_ID
* - HUGEPAGE is the total PAGES and FREE hugepages of a given SIZE in the node
* - HUGEPAGE is the total PAGES and USAGE hugepages of a given SIZE in the node
* - CORE is a CPU core with its ID and sibling CPUs for HT architectures
* - USAGE - hugepages or memory allocated by oned
*
* The free hugaepages and memory capacity is stored in the monitoring node,
* see HostMonitoringTemplate.h
*/
class HostShareNode : public Template
{
@ -195,17 +198,15 @@ private:
unsigned long size_kb;
unsigned int nr;
unsigned int free;
unsigned long usage;
unsigned long allocated;
/**
* @return a VectorAttribute representing this core in the form:
* HUGEPAGE = [ SIZE = "1048576", PAGES = "200", FREE = "100",
* USAGE = "100"]
* HUGEPAGE = [ SIZE = "1048576", PAGES = "200", USAGE = "100"]
*/
VectorAttribute * to_attribute();
VectorAttribute * to_attribute() const;
};
/**
@ -225,13 +226,11 @@ private:
/**
* Memory information for this node:
* - total, free and used memory as reported by IM (meminfo file)
* - mem_used memory allocated to VMs by oned in this node
* - total_mem total memory available
* - mem_usage memory allocated to VMs by oned in this node
* - distance sorted list of nodes, first is the closest (this one)
*/
long long total_mem = 0;
long long free_mem = 0;
long long used_mem = 0;
long long mem_usage = 0;
@ -272,10 +271,9 @@ private:
* hugepage of the same size already exists this function does nothing
* @param size in kb of the page
* @param nr number of pages
* @param free pages
* @param update if true also adds the page to the object Template
*/
void set_hugepage(unsigned long size, unsigned int nr, unsigned int fr,
void set_hugepage(unsigned long size, unsigned int nr,
unsigned long usage, bool update);
void update_hugepage(unsigned long size);

View File

@ -98,7 +98,6 @@
<xs:element name="HUGEPAGE" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="FREE" type="xs:integer"/>
<xs:element name="PAGES" type="xs:integer"/>
<xs:element name="SIZE" type="xs:integer"/>
<xs:element name="USAGE" type="xs:integer"/>
@ -109,10 +108,8 @@
<xs:complexType>
<xs:all>
<xs:element name="DISTANCE" type="xs:string"/>
<xs:element name="FREE" type="xs:integer"/>
<xs:element name="TOTAL" type="xs:integer"/>
<xs:element name="USAGE" type="xs:integer"/>
<xs:element name="USED" type="xs:integer"/>
</xs:all>
</xs:complexType>
</xs:element>
@ -177,6 +174,25 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="NUMA_NODE" minOccurs="0" maxOccurs="unbounded">
<xs:element name="HUGEPAGE" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="FREE" type="xs:integer"/>
<xs:element name="SIZE" type="xs:integer"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="MEMORY">
<xs:complexType>
<xs:all>
<xs:element name="FREE" type="xs:string"/>
<xs:element name="USED" type="xs:integer"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="NODE_ID" type="xs:integer"/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@ -684,7 +684,14 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
end
if numa_nodes && !numa_nodes.empty?
print_numa_nodes(numa_nodes)
begin
monitoring_numa =
host.to_hash['HOST']['MONITORING']['NUMA_NODE']
rescue StandardError
monitoring_numa = nil
end
print_numa_nodes(numa_nodes, monitoring_numa)
end
puts
@ -769,14 +776,34 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
table.show(pcis)
end
def print_numa_nodes(numa_nodes)
def print_numa_nodes(numa_nodes, monitoring)
numa_nodes = get_numa_data(numa_nodes)
merge_numa_monitoring(numa_nodes, monitoring)
print_numa_cores(numa_nodes)
print_numa_memory(numa_nodes)
print_numa_hugepages(numa_nodes)
end
def merge_numa_monitoring(numa_nodes, monitoring)
return if monitoring.nil?
monitoring = [monitoring] if monitoring.class == Hash
numa_nodes.each do |node|
mon_node = monitoring.find {|x| x['NODE_ID'] == node['NODE_ID'] }
node['MEMORY']['FREE'] = mon_node['MEMORY']['FREE']
node['MEMORY']['USED'] = mon_node['MEMORY']['USED']
node['HUGEPAGE'].each do |hp|
mon_hp = mon_node['HUGEPAGE'].find {|x| x['SIZE'] == hp['SIZE'] }
hp['FREE'] = mon_hp['FREE']
end
end
end
def get_numa_data(numa_nodes)
numa_nodes = [numa_nodes] if numa_nodes.class == Hash
@ -886,7 +913,11 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
end
column :USED_REAL, 'Used memory', :size => 20, :left => true do |d|
OpenNebulaHelper.unit_to_str(d['MEMORY']['USED'].to_i, {})
if d['MEMORY']['USED'].nil?
'-'
else
OpenNebulaHelper.unit_to_str(d['MEMORY']['USED'].to_i, {})
end
end
column :USED_ALLOCATED, 'U memory',
@ -895,7 +926,11 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
end
column :FREE, 'Free memory', :size => 8, :left => true do |d|
OpenNebulaHelper.unit_to_str(d['MEMORY']['FREE'].to_i, {})
if d['MEMORY']['FREE'].nil?
'-'
else
OpenNebulaHelper.unit_to_str(d['MEMORY']['FREE'].to_i, {})
end
end
default :NODE_ID, :TOTAL, :USED_REAL, :USED_ALLOCATED, :FREE
@ -933,7 +968,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
end
column :FREE, 'Free pages', :size => 8, :left => true do |d|
d['HUGEPAGE']['FREE']
d['HUGEPAGE']['FREE'] || '-'
end
column :USED, 'allocated pages', :size => 8, :left => true do |d|

View File

@ -16,6 +16,7 @@
#include "HostMonitoringTemplate.h"
#include "ObjectXML.h"
#include "NebulaLog.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -73,6 +74,174 @@ int SystemMonitoring::from_template(const Template &tmpl)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string NUMAMonitoring::to_xml() const
{
ostringstream oss;
string node_str;
for (const auto& node : nodes)
{
oss << node.second.to_xml(node_str);
}
return oss.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int NUMAMonitoring::from_xml(ObjectXML& xml, const std::string& xpath_prefix)
{
vector<xmlNodePtr> content;
xml.get_nodes(xpath_prefix + "NUMA_NODE", content);
for (const auto node_xml : content)
{
NUMAMonitoringNode node;
node.from_xml_node(node_xml);
unsigned int id;
node.get("NODE_ID", id);
nodes[id] = node;
}
xml.free_nodes(content);
content.clear();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int NUMAMonitoring::from_template(const Template &tmpl)
{
// Parse HugePages
vector<const VectorAttribute*> huge_pages;
tmpl.get("HUGEPAGE", huge_pages);
for (const auto* page : huge_pages)
{
int node_id;
unsigned long size;
unsigned long fr;
ostringstream oss;
if (page->vector_value("NODE_ID", node_id) != 0)
{
page->to_token(oss);
NebulaLog::warn("HMM", "Hugepage doesn't contain node ID: "
+ oss.str());
continue;
}
if (page->vector_value("SIZE", size) != 0)
{
page->to_token(oss);
NebulaLog::warn("HMM", "Hugepage doesn't contain size: "
+ oss.str());
continue;
}
page->vector_value("FREE", fr);
set_huge_page(node_id, size, fr);
}
// Parse Memory nodes
vector<const VectorAttribute*> mem_nodes;
tmpl.get("MEMORY_NODE", mem_nodes);
for (const auto* mem : mem_nodes)
{
int node_id;
unsigned long used;
unsigned long fr;
ostringstream oss;
if (mem->vector_value("NODE_ID", node_id) != 0)
{
mem->to_token(oss);
NebulaLog::warn("HMM", "Memory node doesn't contain node ID: "
+ oss.str());
continue;
}
mem->vector_value("USED", used);
mem->vector_value("FREE", fr);
set_memory(node_id, used, fr);
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void NUMAMonitoring::set_huge_page(unsigned int node_id, unsigned long size, unsigned long fr)
{
NUMAMonitoringNode* node;
auto it = nodes.find(node_id);
if ( it != nodes.end())
{
node = &it->second;
}
else
{
auto res = nodes.insert(make_pair(node_id, NUMAMonitoringNode()));
node = &res.first->second;
node->add("NODE_ID", node_id);
}
auto vatt = new VectorAttribute("HUGEPAGE");
vatt->replace("SIZE", size);
vatt->replace("FREE", fr);
node->set(vatt);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void NUMAMonitoring::set_memory(unsigned int node_id, unsigned long used, unsigned long fr)
{
NUMAMonitoringNode* node;
auto it = nodes.find(node_id);
if ( it != nodes.end())
{
node = &it->second;
}
else
{
auto res = nodes.insert(make_pair(node_id, NUMAMonitoringNode()));
node = &res.first->second;
node->add("NODE_ID", node_id);
}
auto vatt = new VectorAttribute("MEMORY");
vatt->replace("USED", used);
vatt->replace("FREE", fr);
node->set(vatt);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string HostMonitoringTemplate::to_xml() const
{
if (_oid == -1)
@ -91,6 +260,7 @@ string HostMonitoringTemplate::to_xml() const
oss << xml_print(ID, _oid);
oss << capacity.to_xml(capacity_s);
oss << system.to_xml(system_s);
oss << numa.to_xml();
oss << "</MONITORING>";
@ -135,6 +305,9 @@ int HostMonitoringTemplate::from_xml(const std::string& xml_string)
content.clear();
}
// ------------ NUMA ---------------
numa.from_xml(xml, "/MONITORING/");
return 0;
}
@ -156,6 +329,7 @@ int HostMonitoringTemplate::from_template(const Template &tmpl)
int rc = capacity.from_template(tmpl);
rc += system.from_template(tmpl);
rc += numa.from_template(tmpl);
return rc;
}

View File

@ -232,13 +232,12 @@ VectorAttribute * HostShareNode::Core::to_attribute()
// -----------------------------------------------------------------------------
VectorAttribute * HostShareNode::HugePage::to_attribute()
VectorAttribute * HostShareNode::HugePage::to_attribute() const
{
VectorAttribute * vpage = new VectorAttribute("HUGEPAGE");
vpage->replace("SIZE", size_kb);
vpage->replace("PAGES", nr);
vpage->replace("FREE", free);
vpage->replace("USAGE", usage);
return vpage;
@ -342,15 +341,13 @@ int HostShareNode::from_xml_node(const xmlNodePtr &node, unsigned int _vt)
unsigned long size_kb, usage_kb;
unsigned int nr;
unsigned int free;
(*vp_it)->vector_value("SIZE", size_kb);
(*vp_it)->vector_value("PAGES",nr);
(*vp_it)->vector_value("FREE", free);
(*vp_it)->vector_value("USAGE", usage_kb);
set_hugepage(size_kb, nr, free, usage_kb, false);
set_hugepage(size_kb, nr, usage_kb, false);
}
std::string distance_s;
@ -359,8 +356,6 @@ int HostShareNode::from_xml_node(const xmlNodePtr &node, unsigned int _vt)
if (memory != 0)
{
memory->vector_value("TOTAL", total_mem);
memory->vector_value("FREE", free_mem);
memory->vector_value("USED", used_mem);
memory->vector_value("USAGE", mem_usage);
@ -580,8 +575,6 @@ void HostShareNode::set_memory()
VectorAttribute * mem = new VectorAttribute("MEMORY");
mem->replace("TOTAL", total_mem);
mem->replace("USED", used_mem);
mem->replace("FREE", free_mem);
mem->replace("USAGE", mem_usage);
@ -625,16 +618,15 @@ void HostShareNode::set_core(unsigned int id, std::string& cpus,
// -----------------------------------------------------------------------------
void HostShareNode::set_hugepage(unsigned long size, unsigned int nr,
unsigned int fr, unsigned long usage, bool update)
unsigned long usage, bool update)
{
auto pt = pages.find(size);
if ( pt != pages.end() )
{
if ( nr != pt->second.nr || fr != pt->second.free )
if ( nr != pt->second.nr )
{
pt->second.nr = nr;
pt->second.free = fr;
update_hugepages();
}
@ -642,7 +634,7 @@ void HostShareNode::set_hugepage(unsigned long size, unsigned int nr,
return;
}
HugePage h = {size, nr, fr, usage, 0};
HugePage h = {size, nr, usage, 0};
pages.insert(make_pair(h.size_kb, h));
@ -802,7 +794,6 @@ void HostShareNUMA::set_monitorization(Template &ht, unsigned int _vt)
for (auto it = pages.begin(); it != pages.end(); ++it)
{
unsigned int pages = 0;
unsigned int free = 0;
unsigned long size = 0;
@ -812,12 +803,11 @@ void HostShareNUMA::set_monitorization(Template &ht, unsigned int _vt)
}
(*it)->vector_value("SIZE", size);
(*it)->vector_value("FREE", free);
(*it)->vector_value("PAGES",pages);
HostShareNode& node = get_node(node_id);
node.set_hugepage(size, pages, free, 0, true);
node.set_hugepage(size, pages, 0, true);
}
std::vector<VectorAttribute *> memory;
@ -836,8 +826,6 @@ void HostShareNUMA::set_monitorization(Template &ht, unsigned int _vt)
HostShareNode& node = get_node(node_id);
(*it)->vector_value("TOTAL", node.total_mem);
(*it)->vector_value("FREE", node.free_mem);
(*it)->vector_value("USED", node.used_mem);
(*it)->vector_value("DISTANCE", distance_s);

View File

@ -105,7 +105,6 @@ type NumaNode struct {
}
type HugePage struct {
Free int `xml:"FREE,omitempty"`
Pages int `xml:"PAGES,omitempty"`
Size int `xml:"SIZE,omitempty"`
Usage int `xml:"USAGE,omitempty"`
@ -113,10 +112,8 @@ type HugePage struct {
type Memory struct {
Distance string `xml:"DISTANCE,omitempty"`
Free int `xml:"FREE,omitempty"`
Total int `xml:"TOTAL,omitempty"`
Usage int `xml:"USAGE,omitempty"`
Used int `xml:"USED,omitempty"`
}
type Core struct {