822b3e06239602028df077dd55d7a31373138983
[invirt/packages/xvm-munin-config.git] / host / usr / share / xvm-munin-host-config / plugins / xen_net
1 #!/usr/bin/python
2
3 import sys
4 sys.path.append('/usr/lib/xen-default/lib/python/')
5 from xen.lowlevel import xs
6 from collections import defaultdict
7 import os
8 import re
9
10 xsc = xs.xs()
11
12 def live_vms():
13     domids = set(xsc.ls('', '/local/domain'))
14
15     vms = dict()
16
17     for domid in domids:
18         try:
19             uuid, data = get_dom(int(domid))
20         except (xs.Error, TypeError, AttributeError):
21             continue # went down since we started
22         vms[uuid] = data
23     return vms
24
25 def get_dom(domid):
26     data = dict(domid=domid)
27     data['name'] = xsc.read('', '/local/domain/%d/name' % domid)
28     data['uuid'] = xsc.read('', '/local/domain/%d/vm' % domid)[4:]
29     if data['name'][0:2] == 'd_':
30         data['munin_name'] = 'db domid %d' % domid
31     else:
32         data['munin_name'] = data['name']
33     data['munin_var'] = 'uuid_'+data['uuid'].replace('-', '_')
34     return data['munin_var'], data
35
36 def parse_net_dev():
37     """Parse /proc/net/dev to determine down/up counters for each interface.
38
39     N.B. Note that "down" and "up" are with respect to the host.
40     """
41     usage = {}
42     for line in open('/proc/net/dev', 'r'):
43         if ':' not in line:
44             continue # skip header lines
45         iface, fields = line.split(':')
46         iface = iface.strip()
47         fields = fields.split()
48         usage[iface] = {'down': int(fields[0]),
49                         'up': int(fields[8])}
50     return usage
51
52 IFACE_NAME_RE = re.compile(r'^(vif|tap)(\d+)\.(\d+)$')
53
54 def get_net_usage():
55     """Group /proc/net/dev counters by domain.
56
57     N.B. Note that "down" and "up" are reversed - from the perspective of the guest.
58     """
59     by_dev = parse_net_dev()
60     by_domain = defaultdict(lambda: {'down': 0, 'up': 0})
61     for iface in by_dev:
62         m = IFACE_NAME_RE.match(iface)
63         if m:
64             viftype, domid, ifcount = m.groups()
65             domid = int(domid)
66             by_domain[domid]['down'] += by_dev[iface]['up']
67             by_domain[domid]['up'] += by_dev[iface]['down']
68     return by_domain
69
70 if __name__ == '__main__':
71     if len(sys.argv) > 1:
72         cmd = sys.argv[1]
73     else:
74         cmd = None
75
76     domains = live_vms()
77
78     if cmd == 'config':
79         print """
80     graph_title Xen domain network usage
81     graph_args --base 1000
82     graph_vlabel bits in (-) / out (+) per ${graph_period}
83     graph_info This graph shows how network is utilized by Xen domains.
84     graph_category network
85     graph_period second"""
86         for d in sorted(domains):
87             for direction in ('down', 'up'):
88                 key = "%s_%s" % (d, direction)
89                 print "%s.label %s" % (key, domains[d]['munin_name'])
90                 print "%s.draw AREASTACK" % key
91                 print "%s.max 10000000000" % key
92                 print "%s.min 0" % key
93                 print "%s.type DERIVE" % key
94                 print "%s.cdef %s,8,*" % (key, key)
95                 if direction == 'down':
96                     print "%s.graph no" % key
97                 else:
98                     print "%s.negative %s_down" % (key, d)
99                 print "%s.info uuid %s" % (key, domains[d]['uuid'])
100         sys.exit(0)
101
102     net_usage = get_net_usage()
103
104     for d in sorted(domains):
105         for direction in ('down', 'up'):
106             print "%s_%s.value %d" % (d, direction, net_usage[domains[d]['domid']][direction])