????
Current Path : /usr/local/lib/python3.9/site-packages/agent360/plugins/ |
Current File : //usr/local/lib/python3.9/site-packages/agent360/plugins/vms.py |
from __future__ import print_function import re, sys, os import libvirt import libxml2 import time import plugins import psutil class Plugin(plugins.BasePlugin): __name__ = 'vms' def run(self, config): ''' Using the libvirt API to fetch statistics from guests running KVM, QEMU, Xen, Virtuozzo, VMWare ESX, LXC, BHyve and more ''' results = {} last_value = {} prev_cache = self.get_agent_cache() # Get absolute values from previous check uri = os.getenv("uri", "qemu:///system") values = self.fetch_values(uri) deltas = {} for key, value in values.items(): deltas[key] = {} for subkey, subvalue in value.items(): if subkey == 'mem_bytes' or subkey == 'soft_limit_bytes' or subkey == 'min_guarantee_bytes' or subkey == 'hard_limit_bytes': deltas[key][subkey] = value[subkey] else: deltas[key][subkey] = self.absolute_to_per_second('%s_%s' % (key, subkey), float(subvalue), prev_cache) last_value['%s_%s' % (key, subkey)] = float(value[subkey]) last_value['ts'] = time.time() self.set_agent_cache(last_value) return deltas def canon(self, name): return re.sub(r"[^a-zA-Z0-9_]", "_", name) def get_ifaces(self, dom): xml = dom.XMLDesc(0) doc = None try: doc = libxml2.parseDoc(xml) except: return [] ctx = doc.xpathNewContext() ifaces = [] try: ret = ctx.xpathEval("/domain/devices/interface") for node in ret: devdst = None for child in node.children: if child.name == "target": devdst = child.prop("dev") if devdst == None: continue ifaces.append(devdst) finally: if ctx != None: ctx.xpathFreeContext() if doc != None: doc.freeDoc() return ifaces def get_memtune(self, dom): memtune = { 'min_guarantee': 0, 'soft_limit': 0, 'hard_limit': 0 } xml = dom.XMLDesc(0) try: doc = libxml2.parseDoc(xml) except: return [] ctx = doc.xpathNewContext() try: for key in memtune: ret = ctx.xpathEval("/domain/memtune/%s" % key) try: for child in ret[0].children: memtune[key] = int(child.content) break except IndexError: # key not found in xml pass finally: if ctx != None: ctx.xpathFreeContext() if doc != None: doc.freeDoc() return memtune def fetch_values(self, uri): conn = libvirt.openReadOnly(uri) ids = conn.listDomainsID() results = {} for id in ids: data = {} data['net_rx_bytes'] = 0 data['net_tx_bytes'] = 0 try: dom = conn.lookupByID(id) name = dom.name() except libvirt.libvirtError as err: print("Id: %s: %s" % (id, err), file=sys.stderr) continue if name == "Domain-0": continue ifaces = self.get_ifaces(dom) for iface in ifaces: try: stats = dom.interfaceStats(iface) data['net_rx_bytes'] += stats[0] data['net_tx_bytes'] += stats[4] except: print >>sys.stderr, "Cannot get ifstats for '%s' on '%s'" % (iface, name) cputime = float(dom.info()[4]) cputime_percentage = 1.0e-7 * cputime data['cpu'] = cputime_percentage try: data['cpu_percentage'] = cputime_percentage / psutil.cpu_count() except Exception as e: pass maxmem, mem = dom.info()[1:3] mem *= 1024 maxmem *= 1024 data['mem_bytes'] = mem memtune = self.get_memtune(dom) data['min_guarantee_bytes'] = memtune['min_guarantee'] * 1024 data['hard_limit_bytes'] = memtune['hard_limit'] * 1024 data['soft_limit_bytes'] = memtune['soft_limit'] * 1024 data['disk_rd_bytes'] = 0 data['disk_wr_bytes'] = 0 data['disk_wr_req'] = 0 data['disk_rd_req'] = 0 try: dom = conn.lookupByID(id) name = dom.name() except libvirt.libvirtError as err: print("Id: %s: %s" % (id, err), file=sys.stderr) continue if name == "Domain-0": continue disks = self.get_disks(dom) for disk in disks: try: rd_req, rd_bytes, wr_req, wr_bytes, errs = dom.blockStats(disk) data['disk_rd_bytes'] += rd_bytes data['disk_wr_bytes'] += wr_bytes data['disk_rd_req'] += rd_req data['disk_wr_req'] += wr_req except TypeError: print >>sys.stderr, "Cannot get blockstats for '%s' on '%s'" % (disk, name) results[self.canon(name)] = data return results def get_disks(self, dom): xml = dom.XMLDesc(0) doc = None try: doc = libxml2.parseDoc(xml) except: return [] ctx = doc.xpathNewContext() disks = [] try: ret = ctx.xpathEval("/domain/devices/disk") for node in ret: devdst = None for child in node.children: if child.name == "target": devdst = child.prop("dev") if devdst == None: continue disks.append(devdst) finally: if ctx != None: ctx.xpathFreeContext() if doc != None: doc.freeDoc() return disks if __name__ == '__main__': Plugin().execute()