1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
#!/usr/bin/python3
# vim: set fileencoding=utf-8 :
#
# Munin plugin to show the I/O load of libvirt managed virtual machines
#
# Copyright 2008 Guido Guenther <agx@sigxcpu.org>
#
# Licesnse: GPLv2
#
# depends: python-libvirt, python-libxml2
#
#%# capabilities=autoconf
#%# family=contrib
from __future__ import print_function
import re, sys, os
import libvirt
import libxml2
def canon(name):
return re.sub(r"[^a-zA-Z0-9_]", "_", name)
def print_config(uri):
"""print the plugin config, determine the domains"""
print("""graph_title Virtual Domain Block Device I/O
graph_vlabel Bytes read (-)/ written (+) per ${graph_period}
graph_category Virtual Machines
graph_info This graph shows the block device I/O of the virtual machines""")
conn = libvirt.openReadOnly(uri)
ids = conn.listDomainsID()
for id in ids:
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
print("%s_read.label %s" % (canon(name), name))
print("%s_read.type DERIVE" % canon(name))
print("%s_read.min 0" % canon(name))
print("%s_read.graph no" % canon(name))
print("%s_read.draw LINE1" % canon(name))
print("%s_write.label %s" % (canon(name), name))
print("%s_write.type DERIVE" % canon(name))
print("%s_write.min 0" % canon(name))
print("%s_write.negative %s_read" % (canon(name), canon(name)))
print("%s_write.draw LINE1" % canon(name))
def get_disks(dom):
xml = dom.XMLDesc(0)
doc = None
try:
doc = libxml2.parseDoc(xml)
except Exception:
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 is None:
continue
disks.append(devdst)
finally:
if ctx is not None:
ctx.xpathFreeContext()
if doc is not None:
doc.freeDoc()
return disks
def fetch_values(uri):
conn = libvirt.openReadOnly(uri)
ids = conn.listDomainsID()
for id in ids:
rd = 0
wr = 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 = get_disks(dom)
for disk in disks:
try:
rd_req, rd_bytes, wr_req, wr_bytes, errs = dom.blockStats(disk)
rd += rd_bytes
wr += wr_bytes
except TypeError:
print("Cannot get blockstats for '%s' on '%s'" % (disk, name), file=sys.stderr)
print("%s_read.value %d" % (canon(name), rd))
print("%s_write.value %d" % (canon(name), wr))
def main(sys):
uri = os.getenv("uri", "qemu:///system")
if len(sys) > 1:
if sys[1] in ['autoconf', 'detect']:
if libvirt.openReadOnly(uri):
print("yes")
return 0
else:
print("no")
return 1
elif sys[1] == 'config':
print_config(uri)
return 0
fetch_values(uri)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))
# vim:et:ts=4:sw=4:
|