Projet

Général

Profil

Révision e0df6aa7

IDe0df6aa788ae74fb4db16c220cd0d872279cdc19
Parent b6c6a02e
Enfant e0b74c69

Ajouté par Lars Kruse il y a plus de 7 ans

kvm_net: improve the network interface name parser and admit its limits

The network interface parser of this plugin was overly specific before.
It relied on a specific format of the arguments handed over to kvm while
starting the VM. For example the following format was usable:

... -netdev tap,ifname=foo,...

But kvm/qemu support a variety of ways for configuring network
interfaces via the commandline. E.g. libvirt does not use the "ifname"
parameter above. Thus VMs running on a host controlled via libvirt
cannot be tracked with this plugin.

This limititation is now clearly documented in the header of the plugin.

Voir les différences:

plugins/libvirt/kvm_net
6 6
kvm_net - Munin plugin to show the network I/O per VM
7 7

  
8 8

  
9
=head1 APPLICABLE SYSTEMS
10

  
11
Virtualization server with VMs based on KVM may be able to track the network
12
traffic of their VMs, if the KVM processes are started in a specific way.
13

  
14
Probably proxmox-based virtualization hosts fit into this category.
15

  
16
You can easily check if your KVM processes are started in the expected way, by
17
running the following command:
18

  
19
  ps -ef | grep "netdev.*ifname="
20

  
21
The plugin can be used, if the above command outputs one line for every
22
currently running VM.
23

  
24
In all other cases you need to use other munin plugins instead, e.g. "libvirt".
25

  
26

  
9 27
=head1 CONFIGURATION
10 28

  
11 29
parsed environment variables:
......
39 57

  
40 58

  
41 59
VM_NAME_REGEX = re.compile("^.*\x00-{arg_name}\x00(.+)\x00.*$")
60
KVM_INTERFACE_NAME_REGEX = re.compile("(?:^|,)ifname=([^,]+)(?:,|$)")
42 61

  
43 62

  
44 63
def config(vm_names):
......
83 102

  
84 103
    @param dictionnary {kvm_pid: cleaned vm name}
85 104
    """
86
    for pid in vms:
87
        tap = get_vm_mac(pid)
88
        try:
89
            f = open("/proc/net/dev", "r")
90
            for line in f.readlines():
91
                if tap in line:
92
                    print("%s_in.value %s" % (vms[pid], line.split()[1]))
93
                    print("%s_out.value %s" % (vms[pid], line.split()[9]))
94
                    break
95
        except Exception as inst:
96
            print(inst)
97
            continue
105
    for pid, vm_data in vms.items():
106
        vm_interface_names = get_vm_network_interface_names(pid)
107
        sum_incoming = 0
108
        sum_outgoing = 0
109
        interface_found = False
110
        with open("/proc/net/dev", "r") as net_file:
111
            for line in net_file.readlines():
112
                tokens = line.split()
113
                current_interface_name = tokens[0].rstrip(":").strip()
114
                if current_interface_name in vm_interface_names:
115
                    sum_incoming += int(tokens[1])
116
                    sum_outgoing += int(tokens[9])
117
                    interface_found = True
118
            if not interface_found:
119
                # we want to distinguish "no traffic" from "not found"
120
                sum_incoming = "U"
121
                sum_outgoing = "U"
122
            print("%s_in.value %s" % (vm_data, sum_incoming))
123
            print("%s_out.value %s" % (vm_data, sum_outgoing))
124

  
125

  
126
def get_vm_network_interface_names(pid):
127
    """ return the MAC addresses configured for network interfacs of a PID """
128
    result = set()
129
    for netdev_description in _get_kvm_process_arguments(pid, "netdev"):
130
        match = KVM_INTERFACE_NAME_REGEX.search(netdev_description)
131
        if match:
132
            result.add(match.groups()[0])
133
    return result
98 134

  
99 135

  
100 136
def detect_kvm():
......
139 175
    return result
140 176

  
141 177

  
142
def get_vm_mac(pid):
143
    """Find and clean vm names from pids
144

  
145
    @return the mac address for a specified pid
146
    """
147
    cmdline = open("/proc/%s/cmdline" % pid, "r")
148
    line = cmdline.readline()
149
    mac = re.sub(r"^.*ifname=(tap[^,]+),.*$", r"\1", line)
150
    return mac
151

  
152

  
153 178
def _get_kvm_process_arguments(pid, arg_name):
154 179
    """ parse all value with the given name from the process identified by PID
155 180

  

Formats disponibles : Unified diff