mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
perf(instances): the VM page reads each disk, the state and host info once
Measured on a VM with two disks, a CD-ROM and a NIC: 70 libvirt calls per page, now 43. Within the page's cached_reads block the VM's state, the host's info and domain capabilities, and each disk path's volume are read once; the running and the persistent disk lists share a path's volume. The ISO list takes the active pools in one call instead of looking each up by name; it still refreshes them, so an image copied in by hand shows up. The opt-in DRBD status waits at most 10 s for the compute's ssh, then leaves the status unknown instead of holding the page.
This commit is contained in:
parent
95b4418c96
commit
439f24041e
6 changed files with 278 additions and 52 deletions
|
|
@ -480,9 +480,10 @@ class wvmInstance(wvmConnect):
|
|||
@contextlib.contextmanager
|
||||
def cached_reads(self):
|
||||
"""
|
||||
Within the block the domain XML (per flags value) and the host
|
||||
capabilities are read from libvirt once, for pages that only read: a
|
||||
VM page reads the XML in some 30 getters. Code that changes the VM
|
||||
Within the block the domain XML (per flags value), the VM's state,
|
||||
the host's capabilities and info, and each disk's volume are read
|
||||
from libvirt once, for pages that only read: a VM page reads the XML
|
||||
in some 30 getters and each disk in two lists. Code that changes the VM
|
||||
must not run inside: most changes (devices, QoS, memory) do not go
|
||||
through _defineXML, the only call that drops the cache.
|
||||
"""
|
||||
|
|
@ -494,27 +495,31 @@ class wvmInstance(wvmConnect):
|
|||
finally:
|
||||
self._read_cache = None
|
||||
|
||||
def _XMLDesc(self, flag):
|
||||
def _cached(self, key, read):
|
||||
cache = self._read_cache
|
||||
if cache is None:
|
||||
return self.instance.XMLDesc(flag)
|
||||
key = ("xml", flag)
|
||||
return read()
|
||||
if key not in cache:
|
||||
cache[key] = self.instance.XMLDesc(flag)
|
||||
cache[key] = read()
|
||||
return cache[key]
|
||||
|
||||
def _XMLDesc(self, flag):
|
||||
return self._cached(("xml", flag), lambda: self.instance.XMLDesc(flag))
|
||||
|
||||
def _defineXML(self, xml):
|
||||
if self._read_cache is not None:
|
||||
self._read_cache.clear()
|
||||
return self.wvm.defineXML(xml)
|
||||
|
||||
def get_cap_xml(self):
|
||||
cache = self._read_cache
|
||||
if cache is None:
|
||||
return super().get_cap_xml()
|
||||
if "capabilities" not in cache:
|
||||
cache["capabilities"] = super().get_cap_xml()
|
||||
return cache["capabilities"]
|
||||
return self._cached("capabilities", super().get_cap_xml)
|
||||
|
||||
def get_dom_cap_xml(self, arch, machine):
|
||||
read = super().get_dom_cap_xml
|
||||
return self._cached(("domain capabilities", arch, machine), lambda: read(arch, machine))
|
||||
|
||||
def _host_info(self):
|
||||
return self._cached("host info", self.wvm.getInfo)
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
|
|
@ -523,7 +528,7 @@ class wvmInstance(wvmConnect):
|
|||
VIR_DOMAIN_PAUSED = 3
|
||||
VIR_DOMAIN_SHUTOFF = 5
|
||||
"""
|
||||
return self.instance.info()[0]
|
||||
return self._cached("status", lambda: self.instance.info()[0])
|
||||
|
||||
def get_autostart(self):
|
||||
return self.instance.autostart()
|
||||
|
|
@ -608,11 +613,11 @@ class wvmInstance(wvmConnect):
|
|||
return description or ""
|
||||
|
||||
def get_max_memory(self):
|
||||
return self.wvm.getInfo()[1] * 1048576
|
||||
return self._host_info()[1] * 1048576
|
||||
|
||||
def get_max_cpus(self):
|
||||
"""Get number of physical CPUs."""
|
||||
hostinfo = self.wvm.getInfo()
|
||||
hostinfo = self._host_info()
|
||||
pcpus = hostinfo[4] * hostinfo[5] * hostinfo[6] * hostinfo[7]
|
||||
return range(1, int(pcpus + 1))
|
||||
|
||||
|
|
@ -775,15 +780,10 @@ class wvmInstance(wvmConnect):
|
|||
else None
|
||||
)
|
||||
|
||||
try:
|
||||
vol = self.get_volume_by_path(src_file)
|
||||
volume = vol.name()
|
||||
|
||||
disk_size = vol.info()[1]
|
||||
used_size = vol.info()[2]
|
||||
stg = vol.storagePoolLookupByVolume()
|
||||
storage = stg.name()
|
||||
except libvirtError:
|
||||
details = self._volume_details(src_file)
|
||||
if details:
|
||||
volume, disk_size, used_size, storage = details
|
||||
else:
|
||||
volume = src_file
|
||||
except Exception as e:
|
||||
print(f"Exception: {e}")
|
||||
|
|
@ -813,6 +813,20 @@ class wvmInstance(wvmConnect):
|
|||
flags = VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE if config else 0
|
||||
return util.get_xml_path(self._XMLDesc(flags), func=disks)
|
||||
|
||||
def _volume_details(self, path):
|
||||
"""(name, capacity, allocation, pool name) of the volume at path, or
|
||||
None when no pool holds it."""
|
||||
|
||||
def read():
|
||||
try:
|
||||
vol = self.get_volume_by_path(path)
|
||||
info = vol.info()
|
||||
return vol.name(), info[1], info[2], vol.storagePoolLookupByVolume().name()
|
||||
except libvirtError:
|
||||
return None
|
||||
|
||||
return self._cached(("volume", path), read)
|
||||
|
||||
def get_media_devices(self):
|
||||
def disks(doc):
|
||||
result = []
|
||||
|
|
@ -1541,16 +1555,15 @@ class wvmInstance(wvmConnect):
|
|||
|
||||
def get_iso_media(self):
|
||||
iso = []
|
||||
storages = self.get_storages(only_actives=True)
|
||||
for storage in storages:
|
||||
stg = self.get_storage(storage)
|
||||
if stg.info()[0] != 0:
|
||||
with contextlib.suppress(Exception):
|
||||
stg.refresh(0)
|
||||
|
||||
for img in stg.listVolumes():
|
||||
if img.lower().endswith(".iso"):
|
||||
iso.append(img)
|
||||
for pool in self.wvm.listAllStoragePools(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE):
|
||||
# refreshed so that an image copied to the pool by hand shows up
|
||||
with contextlib.suppress(libvirtError):
|
||||
pool.refresh(0)
|
||||
try:
|
||||
names = pool.listVolumes()
|
||||
except libvirtError: # stopped or removed meanwhile
|
||||
continue
|
||||
iso.extend(name for name in names if name.lower().endswith(".iso"))
|
||||
return iso
|
||||
|
||||
def paths_used_by_other_domains(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue