[virt-tools-list] [PATCH 2/2] Domain: Implement new stats class.
Simon Kobyda
skobyda at redhat.com
Fri Oct 5 14:54:26 UTC 2018
Had to make several domain properties which were related to stats
public, since stats handling was pulled out of domain class.
Pulled _sample_*_stats functions.
Signed-off-by: Simon Kobyda <skobyda at redhat.com>
---
virtManager/domain.py | 256 ++++++------------------------------------
1 file changed, 32 insertions(+), 224 deletions(-)
diff --git a/virtManager/domain.py b/virtManager/domain.py
index 0f7410ff..1c4ffe90 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -211,7 +211,7 @@ class vmmDomain(vmmLibvirtObject):
self.cloning = False
- self._stats = []
+ self.stats = []
self._stats_rates = {
"diskRdRate": 10.0,
"diskWrRate": 10.0,
@@ -233,18 +233,18 @@ class vmmDomain(vmmLibvirtObject):
self.mem_stats_supported = False
self._domain_state_supported = False
- self._enable_mem_stats = False
- self._enable_cpu_stats = False
- self._mem_stats_period_is_set = False
+ self.enable_mem_stats = False
+ self.enable_cpu_stats = False
+ self.mem_stats_period_is_set = False
- self._enable_net_poll = False
- self._stats_net_supported = True
- self._stats_net_skip = []
+ self.enable_net_poll = False
+ self.stats_net_supported = True
+ self.stats_net_skip = []
- self._enable_disk_poll = False
- self._stats_disk_supported = True
- self._stats_disk_skip = []
- self._summary_disk_stats_skip = False
+ self.enable_disk_poll = False
+ self.stats_disk_supported = True
+ self.stats_disk_skip = []
+ self.summary_disk_stats_skip = False
self.inspection = vmmInspectionData()
@@ -276,7 +276,7 @@ class vmmDomain(vmmLibvirtObject):
# Prime caches
info = self._backend.info()
self._refresh_status(newstatus=info[0])
- self._tick_stats(info)
+ self._tick_stats()
self.has_managed_save()
self.snapshots_supported()
@@ -1536,48 +1536,12 @@ class vmmDomain(vmmLibvirtObject):
# Stats helpers #
#################
- def _sample_cpu_stats(self, info, now):
- if not self._enable_cpu_stats:
- return 0, 0, 0, 0
- if not info:
- info = self._backend.info()
-
- prevCpuTime = 0
- prevTimestamp = 0
- cpuTime = 0
- cpuTimeAbs = 0
- pcentHostCpu = 0
- pcentGuestCpu = 0
-
- if len(self._stats) > 0:
- prevTimestamp = self._stats[0]["timestamp"]
- prevCpuTime = self._stats[0]["cpuTimeAbs"]
-
- if not (info[0] in [libvirt.VIR_DOMAIN_SHUTOFF,
- libvirt.VIR_DOMAIN_CRASHED]):
- guestcpus = info[3]
- cpuTime = info[4] - prevCpuTime
- cpuTimeAbs = info[4]
- hostcpus = self.conn.host_active_processor_count()
-
- pcentbase = (((cpuTime) * 100.0) /
- ((now - prevTimestamp) * 1000.0 * 1000.0 * 1000.0))
- pcentHostCpu = pcentbase / hostcpus
- # Under RHEL-5.9 using a XEN HV guestcpus can be 0 during shutdown
- # so play safe and check it.
- pcentGuestCpu = guestcpus > 0 and pcentbase / guestcpus or 0
-
- pcentHostCpu = max(0.0, min(100.0, pcentHostCpu))
- pcentGuestCpu = max(0.0, min(100.0, pcentGuestCpu))
-
- return cpuTime, cpuTimeAbs, pcentHostCpu, pcentGuestCpu
-
def _get_cur_rate(self, what):
- if len(self._stats) > 1:
- ret = (float(self._stats[0][what] -
- self._stats[1][what]) /
- float(self._stats[0]["timestamp"] -
- self._stats[1]["timestamp"]))
+ if len(self.stats) > 1:
+ ret = (float(self.stats[0][what] -
+ self.stats[1][what]) /
+ float(self.stats[0]["timestamp"] -
+ self.stats[1]["timestamp"]))
else:
ret = 0.0
return max(ret, 0, 0) # avoid negative values at poweroff
@@ -1589,9 +1553,9 @@ class vmmDomain(vmmLibvirtObject):
return float(max(self._stats_rates[name1], self._stats_rates[name2]))
def _get_record_helper(self, record_name):
- if len(self._stats) == 0:
+ if len(self.stats) == 0:
return 0
- return self._stats[0][record_name]
+ return self.stats[0][record_name]
def _vector_helper(self, record_name, limit, ceil=100.0):
vector = []
@@ -1600,8 +1564,8 @@ class vmmDomain(vmmLibvirtObject):
statslen = min(statslen, limit)
for i in range(statslen):
- if i < len(self._stats):
- vector.append(self._stats[i][record_name] / ceil)
+ if i < len(self.stats):
+ vector.append(self.stats[i][record_name] / ceil)
else:
vector.append(0)
@@ -1759,13 +1723,13 @@ class vmmDomain(vmmLibvirtObject):
def _on_config_sample_network_traffic_changed(self, ignore=None):
- self._enable_net_poll = self.config.get_stats_enable_net_poll()
+ self.enable_net_poll = self.config.get_stats_enable_net_poll()
def _on_config_sample_disk_io_changed(self, ignore=None):
- self._enable_disk_poll = self.config.get_stats_enable_disk_poll()
+ self.enable_disk_poll = self.config.get_stats_enable_disk_poll()
def _on_config_sample_mem_stats_changed(self, ignore=None):
- self._enable_mem_stats = self.config.get_stats_enable_memory_poll()
+ self.enable_mem_stats = self.config.get_stats_enable_memory_poll()
def _on_config_sample_cpu_stats_changed(self, ignore=None):
- self._enable_cpu_stats = self.config.get_stats_enable_cpu_poll()
+ self.enable_cpu_stats = self.config.get_stats_enable_cpu_poll()
def get_cache_dir(self):
ret = os.path.join(self.conn.get_cache_dir(), self.get_uuid())
@@ -1778,148 +1742,11 @@ class vmmDomain(vmmLibvirtObject):
# Polling helpers #
###################
- def _sample_network_traffic(self):
- rx = 0
- tx = 0
- if (not self._stats_net_supported or
- not self._enable_net_poll or
- not self.is_active()):
- self._stats_net_skip = []
- return rx, tx
-
- for netdev in self.get_interface_devices_norefresh():
- dev = netdev.target_dev
- if not dev:
- continue
-
- if dev in self._stats_net_skip:
- continue
-
- try:
- io = self._backend.interfaceStats(dev)
- if io:
- rx += io[0]
- tx += io[4]
- except libvirt.libvirtError as err:
- if util.is_error_nosupport(err):
- logging.debug("Net stats not supported: %s", err)
- self._stats_net_supported = False
- else:
- logging.error("Error reading net stats for "
- "'%s' dev '%s': %s",
- self.get_name(), dev, err)
- if self.is_active():
- logging.debug("Adding %s to skip list", dev)
- self._stats_net_skip.append(dev)
- else:
- logging.debug("Aren't running, don't add to skiplist")
-
- return rx, tx
-
- def _sample_disk_io(self):
- rd = 0
- wr = 0
- if (not self._stats_disk_supported or
- not self._enable_disk_poll or
- not self.is_active()):
- self._stats_disk_skip = []
- return rd, wr
-
- # Some drivers support this method for getting all usage at once
- if not self._summary_disk_stats_skip:
- try:
- io = self._backend.blockStats('')
- if io:
- rd = io[1]
- wr = io[3]
- return rd, wr
- except libvirt.libvirtError:
- self._summary_disk_stats_skip = True
-
- # did not work, iterate over all disks
- for disk in self.get_disk_devices_norefresh():
- dev = disk.target
- if not dev:
- continue
-
- if dev in self._stats_disk_skip:
- continue
-
- try:
- io = self._backend.blockStats(dev)
- if io:
- rd += io[1]
- wr += io[3]
- except libvirt.libvirtError as err:
- if util.is_error_nosupport(err):
- logging.debug("Disk stats not supported: %s", err)
- self._stats_disk_supported = False
- else:
- logging.error("Error reading disk stats for "
- "'%s' dev '%s': %s",
- self.get_name(), dev, err)
- if self.is_active():
- logging.debug("Adding %s to skip list", dev)
- self._stats_disk_skip.append(dev)
- else:
- logging.debug("Aren't running, don't add to skiplist")
-
- return rd, wr
-
- def _set_mem_stats_period(self):
- # QEMU requires to explicitly enable memory stats polling per VM
- # if we want fine grained memory stats
- if not self.conn.check_support(
- self.conn.SUPPORT_CONN_MEM_STATS_PERIOD):
- return
-
- # Only works for virtio balloon
- if not any([b for b in self.get_xmlobj().devices.memballoon if
- b.model == "virtio"]):
- return
-
- try:
- secs = 5
- self._backend.setMemoryStatsPeriod(secs,
- libvirt.VIR_DOMAIN_AFFECT_LIVE)
- except Exception as e:
- logging.debug("Error setting memstats period: %s", e)
-
- def _sample_mem_stats(self):
- if (not self.mem_stats_supported or
- not self._enable_mem_stats or
- not self.is_active()):
- self._mem_stats_period_is_set = False
- return 0, 0
-
- if self._mem_stats_period_is_set is False:
- self._set_mem_stats_period()
- self._mem_stats_period_is_set = True
-
- curmem = 0
- totalmem = 1
- try:
- stats = self._backend.memoryStats()
- totalmem = stats.get("actual", 1)
- curmem = stats.get("rss", 0)
-
- if "unused" in stats:
- curmem = max(0, totalmem - stats.get("unused", totalmem))
- except libvirt.libvirtError as err:
- logging.error("Error reading mem stats: %s", err)
-
- pcentCurrMem = (curmem / float(totalmem)) * 100
- pcentCurrMem = max(0.0, min(pcentCurrMem, 100.0))
-
- return pcentCurrMem, curmem
-
-
def tick(self, stats_update=True):
if (not self._using_events() and
not stats_update):
return
- info = []
dosignal = False
if not self._using_events():
# For domains it's pretty important that we are always using
@@ -1930,44 +1757,25 @@ class vmmDomain(vmmLibvirtObject):
dosignal = self._refresh_status(newstatus=info[0], cansignal=False)
if stats_update:
- self._tick_stats(info)
+ self._tick_stats()
if dosignal:
self.idle_emit("state-changed")
if stats_update:
self.idle_emit("resources-sampled")
- def _tick_stats(self, info):
+ def _tick_stats(self):
expected = self.config.get_stats_history_length()
- current = len(self._stats)
+ current = len(self.stats)
if current > expected:
- del self._stats[expected:current]
-
- now = time.time()
- (cpuTime, cpuTimeAbs,
- pcentHostCpu, pcentGuestCpu) = self._sample_cpu_stats(info, now)
- pcentCurrMem, curmem = self._sample_mem_stats()
- rdBytes, wrBytes = self._sample_disk_io()
- rxBytes, txBytes = self._sample_network_traffic()
-
- newStats = {
- "timestamp": now,
- "cpuTime": cpuTime,
- "cpuTimeAbs": cpuTimeAbs,
- "cpuHostPercent": pcentHostCpu,
- "cpuGuestPercent": pcentGuestCpu,
- "curmem": curmem,
- "currMemPercent": pcentCurrMem,
- "diskRdKiB": rdBytes // 1024,
- "diskWrKiB": wrBytes // 1024,
- "netRxKiB": rxBytes // 1024,
- "netTxKiB": txBytes // 1024,
- }
+ del self.stats[expected:current]
+
+ newStats = self.conn.statsmanager.get_vm_stats(self)
for r in ["diskRd", "diskWr", "netRx", "netTx"]:
newStats[r + "Rate"] = self._get_cur_rate(r + "KiB")
self._set_max_rate(newStats, r + "Rate")
- self._stats.insert(0, newStats)
+ self.stats.insert(0, newStats)
########################
--
2.17.1
More information about the virt-tools-list
mailing list