PatchInventory: kvm_io

File kvm_io, 3.2 kB (added by admin, 3 years ago)
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# vim: set fileencoding=utf-8
4#
5# Munin plugin to show io by vm
6#
7# Copyright Maxence Dunnewind, Rodolphe Quiédeville
8#
9# License : GPLv3
10#
11# parsed environment variables:
12# vmsuffix: part of vm name to be removed
13#
14#%# capabilities=autoconf
15#%# family=contrib
16
17import re, os, sys
18from subprocess import Popen, PIPE
19
20def config(vm_names):
21    ''' Print the plugin's config
22    @param vm_names : a list of "cleaned" vms' name
23    '''
24    base_config = """graph_title KVM Virtual Machine IO usage
25graph_vlabel Bytes read(-)/written(+) per second
26graph_category KVM
27graph_info This graph shows the block device I/O used of virtual machines
28graph_args --base 1024
29    """
30    print base_config
31
32    for vm in vm_names:
33        print "%s_read.label %s" % (vm, vm)
34        print "%s_read.type COUNTER" % vm
35        print "%s_read.min 0" % vm
36        print "%s_read.draw LINE1" % vm
37        print "%s_read.info I/O used by virtual machine %s" % (vm, vm)
38        print "%s_write.label %s" % (vm, vm)
39        print "%s_write.type COUNTER" % vm
40        print "%s_write.min 0" % vm       
41        print "%s_write.draw LINE1" % vm
42        print "%s_write.negative %s_read" % (vm, vm)
43        print "%s_write.info I/O used by virtual machine %s" % (vm, vm)
44
45def clean_vm_name(vm_name):
46    ''' Replace all special chars
47    @param vm_name : a vm's name
48    @return cleaned vm's name
49    '''
50    # suffix part defined in conf
51    suffix = os.getenv('vmsuffix')
52    if suffix:
53        vm_name = re.sub(suffix,'',vm_name)
54
55    return re.sub(r"[^a-zA-Z0-9_]", "_", vm_name)
56   
57def fetch(vms):
58    ''' Fetch values for a list of pids
59    @param dictionnary {kvm_pid: cleaned vm name}
60    '''
61    res = {}
62    for pid in vms:
63        f = open("/proc/%s/io" % pid, "r")
64        for line in f.readlines():
65            if "read_bytes" in line:
66                read = line.split()[1]
67                print "%s_read.value %s" % (vms[pid], read) 
68            if "write_bytes" in line:
69                write = line.split()[1]
70                print "%s_write.value %s" % (vms[pid], write) 
71                break           
72        f.close()
73
74def detect_kvm():
75    ''' Check if kvm is installed
76    '''
77    kvm = Popen("which kvm", shell=True, stdout=PIPE)
78    kvm.communicate()
79    return not bool(kvm.returncode)
80
81def find_vm_names(pids):
82    '''Find and clean vm names from pids
83    @return a dictionnary of {pids : cleaned vm name}
84    '''
85    result = {}
86    for pid in pids:
87        cmdline = open("/proc/%s/cmdline" % pid, "r")
88        result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-]*)\x00\-.*$",r"\1", cmdline.readline()))
89    return result
90   
91def list_pids():
92    ''' Find the pid of kvm processes
93    @return a list of pids from running kvm
94    '''
95    pid = Popen("pidof kvm", shell=True, stdout=PIPE)
96    return pid.communicate()[0].split()
97   
98if __name__ == "__main__":
99    if len(sys.argv) > 1:
100        if sys.argv[1] in ['autoconf', 'detect']:
101            if detect_kvm():
102                print "yes"
103            else:
104                print "no"
105        elif sys.argv[1] == "config":
106            config(find_vm_names(list_pids()).values())
107        else:
108            fetch(find_vm_names(list_pids()))
109    else:
110        fetch(find_vm_names(list_pids()))