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
|
#!/usr/bin/python3
# vim: set fileencoding=utf-8 :
#
# Munin plugin to show the network traffic of libvirt managed virtual machines
#
# Copyright 2008 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 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 Network I/O
graph_vlabel Bytes rx (-)/ tx (+) per ${graph_period}
graph_category Virtual Machines
graph_info This graph shows the network 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_rx.label %s" % (canon(name), name))
print("%s_rx.type DERIVE" % canon(name))
print("%s_rx.min 0" % canon(name))
print("%s_rx.graph no" % canon(name))
print("%s_rx.draw LINE1" % canon(name))
print("%s_tx.label %s" % (canon(name), name))
print("%s_tx.type DERIVE" % canon(name))
print("%s_tx.min 0" % canon(name))
print("%s_tx.negative %s_rx" % (canon(name), canon(name)))
print("%s_tx.draw LINE1" % canon(name))
def get_ifaces(dom):
xml = dom.XMLDesc(0)
doc = None
try:
doc = libxml2.parseDoc(xml)
except Exception:
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 is None:
continue
ifaces.append(devdst)
finally:
if ctx is not None:
ctx.xpathFreeContext()
if doc is not None:
doc.freeDoc()
return ifaces
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
ifaces = get_ifaces(dom)
for iface in ifaces:
try:
stats = dom.interfaceStats(iface)
rd += stats[0]
wr += stats[4]
except TypeError:
print("Cannot get ifstats for '%s' on '%s'" % (iface, name), file=sys.stderr)
print("%s_rx.value %d" % (canon(name), rd))
print("%s_tx.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:
|