mirror of
https://github.com/munin-monitoring/contrib.git
synced 2018-11-08 00:59:34 +01:00
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.
This commit is contained in:
parent
b6c6a02efe
commit
e0df6aa788
@ -6,6 +6,24 @@
|
|||||||
kvm_net - Munin plugin to show the network I/O per VM
|
kvm_net - Munin plugin to show the network I/O per VM
|
||||||
|
|
||||||
|
|
||||||
|
=head1 APPLICABLE SYSTEMS
|
||||||
|
|
||||||
|
Virtualization server with VMs based on KVM may be able to track the network
|
||||||
|
traffic of their VMs, if the KVM processes are started in a specific way.
|
||||||
|
|
||||||
|
Probably proxmox-based virtualization hosts fit into this category.
|
||||||
|
|
||||||
|
You can easily check if your KVM processes are started in the expected way, by
|
||||||
|
running the following command:
|
||||||
|
|
||||||
|
ps -ef | grep "netdev.*ifname="
|
||||||
|
|
||||||
|
The plugin can be used, if the above command outputs one line for every
|
||||||
|
currently running VM.
|
||||||
|
|
||||||
|
In all other cases you need to use other munin plugins instead, e.g. "libvirt".
|
||||||
|
|
||||||
|
|
||||||
=head1 CONFIGURATION
|
=head1 CONFIGURATION
|
||||||
|
|
||||||
parsed environment variables:
|
parsed environment variables:
|
||||||
@ -39,6 +57,7 @@ import sys
|
|||||||
|
|
||||||
|
|
||||||
VM_NAME_REGEX = re.compile("^.*\x00-{arg_name}\x00(.+)\x00.*$")
|
VM_NAME_REGEX = re.compile("^.*\x00-{arg_name}\x00(.+)\x00.*$")
|
||||||
|
KVM_INTERFACE_NAME_REGEX = re.compile("(?:^|,)ifname=([^,]+)(?:,|$)")
|
||||||
|
|
||||||
|
|
||||||
def config(vm_names):
|
def config(vm_names):
|
||||||
@ -83,18 +102,35 @@ def fetch(vms):
|
|||||||
|
|
||||||
@param dictionnary {kvm_pid: cleaned vm name}
|
@param dictionnary {kvm_pid: cleaned vm name}
|
||||||
"""
|
"""
|
||||||
for pid in vms:
|
for pid, vm_data in vms.items():
|
||||||
tap = get_vm_mac(pid)
|
vm_interface_names = get_vm_network_interface_names(pid)
|
||||||
try:
|
sum_incoming = 0
|
||||||
f = open("/proc/net/dev", "r")
|
sum_outgoing = 0
|
||||||
for line in f.readlines():
|
interface_found = False
|
||||||
if tap in line:
|
with open("/proc/net/dev", "r") as net_file:
|
||||||
print("%s_in.value %s" % (vms[pid], line.split()[1]))
|
for line in net_file.readlines():
|
||||||
print("%s_out.value %s" % (vms[pid], line.split()[9]))
|
tokens = line.split()
|
||||||
break
|
current_interface_name = tokens[0].rstrip(":").strip()
|
||||||
except Exception as inst:
|
if current_interface_name in vm_interface_names:
|
||||||
print(inst)
|
sum_incoming += int(tokens[1])
|
||||||
continue
|
sum_outgoing += int(tokens[9])
|
||||||
|
interface_found = True
|
||||||
|
if not interface_found:
|
||||||
|
# we want to distinguish "no traffic" from "not found"
|
||||||
|
sum_incoming = "U"
|
||||||
|
sum_outgoing = "U"
|
||||||
|
print("%s_in.value %s" % (vm_data, sum_incoming))
|
||||||
|
print("%s_out.value %s" % (vm_data, sum_outgoing))
|
||||||
|
|
||||||
|
|
||||||
|
def get_vm_network_interface_names(pid):
|
||||||
|
""" return the MAC addresses configured for network interfacs of a PID """
|
||||||
|
result = set()
|
||||||
|
for netdev_description in _get_kvm_process_arguments(pid, "netdev"):
|
||||||
|
match = KVM_INTERFACE_NAME_REGEX.search(netdev_description)
|
||||||
|
if match:
|
||||||
|
result.add(match.groups()[0])
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def detect_kvm():
|
def detect_kvm():
|
||||||
@ -139,17 +175,6 @@ def find_vm_names(pids):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_vm_mac(pid):
|
|
||||||
"""Find and clean vm names from pids
|
|
||||||
|
|
||||||
@return the mac address for a specified pid
|
|
||||||
"""
|
|
||||||
cmdline = open("/proc/%s/cmdline" % pid, "r")
|
|
||||||
line = cmdline.readline()
|
|
||||||
mac = re.sub(r"^.*ifname=(tap[^,]+),.*$", r"\1", line)
|
|
||||||
return mac
|
|
||||||
|
|
||||||
|
|
||||||
def _get_kvm_process_arguments(pid, arg_name):
|
def _get_kvm_process_arguments(pid, arg_name):
|
||||||
""" parse all value with the given name from the process identified by PID
|
""" parse all value with the given name from the process identified by PID
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user