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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
#!/usr/bin/python3
# vim: set fileencoding=utf-8 :
#
# Munin plugin to show the amount of memory used by libvirt managed virtual
# machines
#
# Copyright 2008,2012 Guido Guenther <agx@sigxcpu.org>
#
# License: GPLv2
#
# depends: python-libvirt, python-libxml2
#
#%# capabilities=autoconf
#%# family=contrib
from __future__ import print_function
import re, sys, os
import libxml2
import libvirt
def canon(name):
return re.sub(r"[^a-zA-Z0-9_]", "_", name)
def print_config(uri):
"""print the plugin config, determine the domains"""
try:
conn = libvirt.openReadOnly(uri)
except libvirt.libvirtError as err:
print("Error opening to %s connection: %s" % (uri, err), file=sys.stderr)
return 1
hostname = conn.getHostname()
print("""graph_title Virtual Domain Memory Usage
graph_vlabel Memory Usage / Bytes
graph_category Virtual Machines
graph_info This graph shows the current amount of memory used by each virtual machine
graph_args --base 1024 -l 0""")
ids = conn.listDomainsID()
draw = "AREA"
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_mem.label %s" % (canon(name), name))
print("%s_mem.type GAUGE" % canon(name))
print("%s_mem.min 0" % canon(name))
print("%s_mem.draw %s" % (canon(name), draw))
print("%s_mem.info memory used by virtual machine '%s'" % (canon(name), name))
if draw == "AREA":
draw = "STACK"
print("""
host_mem.label %(hostname)s (host)
host_mem.type GAUGE
host_mem.min 0
host_mem.draw LINE1
host_mem.info total memory of host '%(hostname)s'
total.type GAUGE
total.label total memory
total.info total memory used by virtual machines on host '%(hostname)s'
total.graph no
total.min 0
total_pc.type GAUGE
total_pc.label used memory percentage
total_pc.info memory in percent used by virtual machines on host '%(hostname)s'
total_pc.graph no
total_pc.min 0
total_pc.max 100
total_pc.warning 90
total_pc.critical 95
total_max.type GAUGE
total_max.label total max. mem
total_max.info maximum memory virtual machines can balloon to on host '%(hostname)s'
total_max.min 0
total_max_pc.type GAUGE
total_max_pc.label total maximum memory percentage
total_max_pc.graph no
total_max_pc.info maximum memory in percent virtual machines can balloon to on host '%(hostname)s'
total_max_pc.min 0
total_min_guarantee.type GAUGE
total_min_guarantee.label total mem minimum guarantee
total_min_guarantee.info min_guarantee minimum amount of memory guaranteed to all virtual machines on host '%(hostname)s'
total_min_guarantee.min 0
total_min_guarantee_pc.type GAUGE
total_min_guarantee_pc.label total mem minimum guarantee percentage
total_min_guarantee_pc.graph no
total_min_guarantee_pc.info min_guarantee minimum amount of memory in percent guaranteed to all virtual machines on host '%(hostname)s'
total_min_guarantee_pc.min 0
total_hard_limit.type GAUGE
total_hard_limit.label total mem hard limit
total_hard_limit.info memory hard_limit of all virtual machines on host '%(hostname)s'
total_hard_limit.min 0
total_hard_limit_pc.type GAUGE
total_hard_limit_pc.label total mem hard limit percentage
total_hard_limit_pc.graph no
total_hard_limit_pc.info memory hard_limit percentage of all virtual machines on host '%(hostname)s'
total_hard_limit_pc.min 0
total_soft_limit.type GAUGE
total_soft_limit.label total mem soft limit
total_soft_limit.info memory soft_limit of all virtual machines on host '%(hostname)s'
total_soft_limit.min 0
total_soft_limit_pc.type GAUGE
total_soft_limit_pc.label total mem soft limit percentage
total_soft_limit_pc.graph no
total_soft_limit_pc.info memory soft_limit percentage of all virtual machines on host '%(hostname)s'
total_soft_limit_pc.min 0
""" % dict(hostname=hostname))
return 0
def get_memtune(dom):
memtune = {'min_guarantee': 0, 'soft_limit': 0, 'hard_limit': 0}
xml = dom.XMLDesc(0)
try:
doc = libxml2.parseDoc(xml)
except Exception:
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 is not None:
ctx.xpathFreeContext()
if doc is not None:
doc.freeDoc()
return memtune
def fetch_values(uri):
"""Fetch values in the <memtune/> block"""
total = 0
total_max = 0
min_guarantee = 0
hard_limit = 0
soft_limit = 0
try:
conn = libvirt.openReadOnly(uri)
except libvirt.libvirtError as err:
print("Error opening to %s connection: %s" % (uri, err), file=sys.stderr)
return 1
ids = conn.listDomainsID()
hostmem = conn.getInfo()[1] * 1024 * 1024
print("host_mem.value %d" % hostmem)
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
maxmem, mem = dom.info()[1:3]
mem *= 1024
maxmem *= 1024
total += mem
total_max += maxmem
print("%s_mem.value %d" % (canon(name), mem))
memtune = get_memtune(dom)
min_guarantee += memtune['min_guarantee'] * 1024
hard_limit += memtune['hard_limit'] * 1024
soft_limit += memtune['soft_limit'] * 1024
print("total.value %d" % total)
print("total_pc.value %.0f" % (100.0 * total / float(hostmem)))
print("total_max.value %d" % total_max)
print("total_max_pc.value %.0f" % (100.0 * total_max / float(hostmem)))
print("total_min_guarantee.value %d" % min_guarantee)
print("total_min_guarantee_pc.value %.0f" % (100.0 * min_guarantee / float(hostmem)))
print("total_soft_limit.value %d" % soft_limit)
print("total_soft_limit_pc.value %.0f" % (100.0 * soft_limit / float(hostmem)))
print("total_hard_limit.value %d" % hard_limit)
print("total_hard_limit_pc.value %.0f" % (100.0 * hard_limit / float(hostmem)))
return 0
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':
return print_config(uri)
return fetch_values(uri)
if __name__ == "__main__":
sys.exit(main(sys.argv))
# vim:et:ts=4:sw=4:
|