mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 02:33:18 +00:00
the line length change doesn't make the world better... without pyflakes I already wondered, why there is an additional linebreak. now it needs two additional one to stay below 99 changes here are tested and work on Python 3.7.3 (debian buster).
137 lines
3.2 KiB
Python
Executable file
137 lines
3.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""
|
|
=encoding utf8
|
|
|
|
=head1 NAME
|
|
|
|
kvm_cpu - show CPU usage of VM
|
|
|
|
|
|
=head1 CONFIGURATION
|
|
|
|
Parsed environment variables:
|
|
|
|
vmsuffix: part of VM name to be removed
|
|
|
|
|
|
=head1 LICENSE
|
|
|
|
GPLv3
|
|
|
|
SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
|
=head1 AUTHORS
|
|
|
|
Maxence Dunnewind
|
|
|
|
Rodolphe Quiédeville
|
|
|
|
|
|
=head1 MAGIC MARKERS
|
|
|
|
#%# capabilities=autoconf
|
|
#%# family=contrib
|
|
|
|
=cut
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
from subprocess import Popen, PIPE
|
|
|
|
|
|
def config(vm_names):
|
|
''' Print the plugin's config
|
|
@param vm_names : a list of "cleaned" vms' name
|
|
'''
|
|
percent = 100 * len(
|
|
list(
|
|
filter(
|
|
lambda x: x[0:3] == 'cpu' and x[3] != ' ', open('/proc/stat', 'r').readlines())))
|
|
|
|
base_config = """graph_title KVM Virtual Machine CPU usage
|
|
graph_vlabel %%
|
|
graph_category virtualization
|
|
graph_scale no
|
|
graph_period second
|
|
graph_info This graph shows the current CPU used by virtual machines
|
|
graph_args --base 1000 -r --lower-limit 0 --upper-limit %d""" % percent
|
|
print(base_config)
|
|
for vm in vm_names:
|
|
print("%s_cpu.label %s" % (vm, vm))
|
|
print("%s_cpu.min 0" % vm)
|
|
print("%s_cpu.type DERIVE" % vm)
|
|
print("%s_cpu.draw AREASTACK" % vm)
|
|
print("%s_cpu.info percent of cpu time used by virtual machine" % vm)
|
|
|
|
|
|
def clean_vm_name(vm_name):
|
|
''' Replace all special chars
|
|
@param vm_name : a vm's name
|
|
@return cleaned vm's name
|
|
'''
|
|
# suffix part defined in conf
|
|
suffix = os.getenv('vmsuffix')
|
|
if suffix:
|
|
vm_name = re.sub(suffix, '', vm_name)
|
|
# proxmox uses kvm with -name parameter
|
|
parts = vm_name.split('\x00')
|
|
if parts[0].endswith('kvm'):
|
|
try:
|
|
return parts[parts.index('-name') + 1]
|
|
except ValueError:
|
|
pass
|
|
return re.sub(r"[^a-zA-Z0-9_]", "_", vm_name)
|
|
|
|
|
|
def detect_kvm():
|
|
''' Check if kvm is installed '''
|
|
kvm = Popen("which kvm", shell=True, stdout=PIPE)
|
|
kvm.communicate()
|
|
return not bool(kvm.returncode)
|
|
|
|
|
|
def find_vm_names(pids):
|
|
'''Find and clean vm names from pids
|
|
@return a dictionary of {pids : cleaned vm name}
|
|
'''
|
|
result = {}
|
|
for pid in pids:
|
|
cmdline = open("/proc/%s/cmdline" % pid, "r")
|
|
result[pid] = clean_vm_name(
|
|
re.sub(r"^.*guest=([a-zA-Z0-9.-_-]*).*$", r"\1", cmdline.readline()))
|
|
return result
|
|
|
|
|
|
def list_pids():
|
|
''' Find the pid of kvm processes
|
|
@return a list of pids from running kvm
|
|
'''
|
|
pid = Popen("pidof qemu-kvm qemu-system-x86_64 kvm", shell=True, stdout=PIPE)
|
|
return pid.communicate()[0].decode().split()
|
|
|
|
|
|
def fetch(vms):
|
|
''' Fetch values for a list of pids
|
|
@param dictionary {kvm_pid: cleaned vm name}
|
|
'''
|
|
for pid, name in vms.items():
|
|
user, system = open("/proc/%s/stat" % pid, 'r').readline().split(' ')[13:15]
|
|
print('%s_cpu.value %d' % (name, int(user) + int(system)))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) > 1:
|
|
if sys.argv[1] in ['autoconf', 'detect']:
|
|
if detect_kvm():
|
|
print("yes")
|
|
else:
|
|
print("no")
|
|
elif sys.argv[1] == "config":
|
|
config(find_vm_names(list_pids()).values())
|
|
else:
|
|
fetch(find_vm_names(list_pids()))
|
|
else:
|
|
fetch(find_vm_names(list_pids()))
|