mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 11:16:47 +00:00
The capacity read lived in its own module with raw libvirt calls and a thread pool with a deadline, beside helpers that already read the same things. It now uses them: - wvmHostDetails.get_capacity() sums the vCPUs and memory of all and of the running VMs from get_host_instances(), against the host's info. - get_storages_info() also gives each pool's free space. - Compute.capacity joins the two, like cpu_count and ram_size, and is None when the host is down or the read fails. The page reads the hosts one after another, as it already connected to each of them; a host that cannot be reached is given up after the connect timeout. computes/capacity.py and its thread handling are gone. The page looks and sorts as before.
100 lines
3.8 KiB
Python
100 lines
3.8 KiB
Python
import time
|
|
|
|
from libvirt import VIR_DOMAIN_SHUTOFF, VIR_NODE_CPU_STATS_ALL_CPUS
|
|
|
|
from vrtManager.connection import wvmConnect
|
|
from vrtManager.util import get_xml_path
|
|
|
|
|
|
# the times of virNodeGetCPUStats that add up to the elapsed CPU time; guest is
|
|
# already part of user and utilization is a percentage
|
|
CPU_TIMES = ("kernel", "user", "idle", "iowait")
|
|
|
|
|
|
def cpu_percent(before, after):
|
|
"""Busy share in percent between two (idle, total) samples, or None when
|
|
the second does not follow the first."""
|
|
idle = after[0] - before[0]
|
|
total = after[1] - before[1]
|
|
if total <= 0 or not 0 <= idle <= total:
|
|
return None
|
|
return round(100 * (total - idle) / total, 1)
|
|
|
|
|
|
def cpu_version(doc):
|
|
for info in doc.xpath("/sysinfo/processor/entry"):
|
|
elem = info.xpath("@name")[0]
|
|
if elem == "version":
|
|
return info.text
|
|
return "Unknown"
|
|
|
|
|
|
class wvmHostDetails(wvmConnect):
|
|
def get_memory_usage(self):
|
|
"""
|
|
Function return memory usage on node.
|
|
"""
|
|
all_mem = self.host_info[1] * 1048576
|
|
freemem = self.wvm.getMemoryStats(-1, 0)
|
|
if isinstance(freemem, dict):
|
|
free = (freemem["buffers"] + freemem["free"] + freemem["cached"]) * 1024
|
|
percent = abs(100 - free * 100 // all_mem)
|
|
usage = all_mem - free
|
|
return {"total": all_mem, "usage": usage, "percent": percent}
|
|
else:
|
|
return {"total": None, "usage": None, "percent": None}
|
|
|
|
def _cpu_times(self):
|
|
"""(idle, total) nanoseconds of all host CPUs, from one reading."""
|
|
stats = self.wvm.getCPUStats(VIR_NODE_CPU_STATS_ALL_CPUS, 0)
|
|
return stats["idle"], sum(stats.get(name, 0) for name in CPU_TIMES)
|
|
|
|
def get_cpu_usage(self, previous=None):
|
|
"""
|
|
Busy share of all host CPUs in percent since previous, an (idle, total,
|
|
time) sample this method returned, or over one second when there is
|
|
none or it does not lead to this one (the host restarted). Also returns
|
|
the closing sample and the seconds the usage covers.
|
|
"""
|
|
times = self._cpu_times()
|
|
now = time.time()
|
|
usage = None
|
|
if previous is not None:
|
|
usage = cpu_percent(previous[:2], times)
|
|
start = previous[2]
|
|
if usage is None:
|
|
before, start = times, now
|
|
time.sleep(1)
|
|
times = self._cpu_times()
|
|
now = time.time()
|
|
usage = cpu_percent(before, times)
|
|
return {"usage": usage, "sample": (*times, now), "window": now - start}
|
|
|
|
def get_node_info(self):
|
|
"""
|
|
Function return host server information: hostname, cpu, memory, ...
|
|
"""
|
|
info = [self.wvm.getHostname()] # hostname
|
|
info.append(self.host_info[0]) # architecture
|
|
info.append(self.host_info[1] * 1048576) # memory
|
|
info.append(self.host_info[2]) # cpu core count
|
|
info.append(
|
|
get_xml_path(self.wvm.getSysinfo(0), func=cpu_version)
|
|
) # cpu version
|
|
info.append(self.wvm.getURI()) # uri
|
|
return info
|
|
|
|
def get_capacity(self):
|
|
"""
|
|
What the host has given its VMs: vCPUs and memory (bytes) of all VMs
|
|
and of the running ones, against its CPUs and memory. A shut-off VM
|
|
takes its share again when it starts.
|
|
"""
|
|
vcpus = {"all": 0, "running": 0}
|
|
assigned = {"all": 0, "running": 0}
|
|
for vm in self.get_host_instances(raw_mem_size=True).values():
|
|
for share in ("all",) if vm["status"] == VIR_DOMAIN_SHUTOFF else ("all", "running"):
|
|
vcpus[share] += int(vm["vcpu"])
|
|
assigned[share] += vm["memory"]
|
|
return {"cpus": self.host_info[2], "memory": self.host_info[1] * 1048576,
|
|
"vcpus": vcpus, "assigned": assigned}
|