Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / virtualization / kvm_net @ e5ce7492

Historique | Voir | Annoter | Télécharger (3,91 ko)

1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
# vim: set fileencoding=utf-8
4
#
5
# Munin plugin to show the network I/O per vm
6
#
7
# Copyright Igor Borodikhin
8
#
9
# License : GPLv3
10
#
11
#
12
# parsed environment variables:
13
# vmsuffix: part of vm name to be removed
14
#
15
#%# capabilities=autoconf
16
#%# family=contrib
17

    
18
import re, os, sys
19
from subprocess import Popen, PIPE
20

    
21
def config(vm_names):
22
    ''' Print the plugin's config
23
    @param vm_names : a list of "cleaned" vms' name
24
    '''
25
    base_config = """graph_title KVM Network I/O
26
graph_vlabel Bytes rx(-)/tx(+) per second
27
graph_category KVM
28
graph_info This graph shows the network I/O of the virtual machines
29
graph_args --base 1024
30
    """
31
    print base_config
32
    for vm in vm_names:
33
        print "%s_in.label %s" % (vm, vm)
34
        print "%s_in.type COUNTER" % vm
35
        print "%s_in.min 0" % vm
36
        print "%s_in.draw LINE2" % vm
37
        print "%s_out.negative %s_in" % (vm, vm)
38
        print "%s_out.label %s" % (vm, vm)
39
        print "%s_out.type COUNTER" % vm
40
        print "%s_out.min 0" % vm
41
        print "%s_out.draw LINE2" % vm
42

    
43
def clean_vm_name(vm_name):
44
    ''' Replace all special chars
45
    @param vm_name : a vm's name
46
    @return cleaned vm's name
47
    '''
48
    # suffix part defined in conf
49
    suffix = os.getenv('vmsuffix')
50
    if suffix:
51
        vm_name = re.sub(suffix,'',vm_name)
52

    
53
    return re.sub(r"[^a-zA-Z0-9_]", "_", vm_name)
54
    
55
def fetch(vms):
56
    ''' Fetch values for a list of pids
57
    @param dictionnary {kvm_pid: cleaned vm name}
58
    '''
59
    res = {}
60
    for pid in vms:
61
        tap = get_vm_mac(pid)
62
        try:
63
            f = open("/proc/net/dev", "r")
64
            for line in f.readlines():
65
                if tap in line:
66
                    print "%s_in.value %s" % (vms[pid], re.sub(r"%s:"%tap, "", line.split()[0]))
67
                    print "%s_out.value %s" % (vms[pid], line.split()[8])
68
                    break
69
        except Exception as inst:
70
            print inst
71
            continue
72

    
73
def detect_kvm():
74
    ''' Check if kvm is installed
75
    '''
76
    kvm = Popen("which kvm", shell=True, stdout=PIPE)
77
    kvm.communicate()
78
    return not bool(kvm.returncode)
79

    
80
def find_vm_names(pids):
81
    '''Find and clean vm names from pids
82
    @return a dictionnary of {pids : cleaned vm name}
83
    '''
84
    result = {}
85
    for pid in pids:
86
        cmdline = open("/proc/%s/cmdline" % pid, "r")
87
        result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-]*)\x00\-.*$",r"\1", cmdline.readline()))        
88
    return result
89
    
90
def get_vm_mac(pid):
91
    '''Find and clean vm names from pids
92
    @return the mac address for a specified pid
93
    '''
94
    cmdline = open("/proc/%s/cmdline" % pid, "r")
95
    line = cmdline.readline()
96
    mac = re.sub(r"^.*ifname=(tap[^,]+),.*$",r"\1", line)
97
    return mac
98

    
99
def list_pids():
100
    ''' Find the pid of kvm processes
101
    @return a list of pids from running kvm
102
    '''
103
    pid = Popen("pidof kvm", shell=True, stdout=PIPE)
104
    return pid.communicate()[0].split()
105

    
106
def find_vms_tap():
107
    ''' Check if kvm is installed
108
    @return a list of pids from running kvm
109
    '''
110
    result = []
111
    tap = ""
112
    mac = ""
113
    kvm = Popen("ip a | grep -A 1 tap | awk '{print $2}' | grep -v '^$'", shell=True, stdout=PIPE)
114
    res = kvm.communicate()[0].split('\n')
115
    for line in res:
116
        try:
117
            if len(line) > 0:
118
                if re.match(r"^tap.*", line):
119
                    tap = re.sub(r"(tap[^:]+):", r"\1", line)
120
                else:
121
                    result.append(tap)
122
        except Exception as inst:
123
            continue
124

    
125
    return result
126
    
127
if __name__ == "__main__":
128
    if len(sys.argv) > 1:
129
        if sys.argv[1] in ['autoconf', 'detect']:
130
            if detect_kvm():
131
                print "yes"
132
            else:
133
                print "no"
134
        elif sys.argv[1] == "config":
135
            config(find_vm_names(list_pids()).values())
136
        else:
137
            fetch(find_vm_names(list_pids()))
138
    else:
139
        fetch(find_vm_names(list_pids()))
140

    
141