-
Notifications
You must be signed in to change notification settings - Fork 682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kvm plugins improvements #186
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,7 +38,7 @@ graph_args --base 1000 -r --lower-limit 0 --upper-limit %d""" % percent | |
print "%s_cpu.type DERIVE" % vm | ||
print "%s_cpu.draw %s" % (vm, draw) | ||
print "%s_cpu.info percent of cpu time used by virtual machine" % vm | ||
draw = "STACK" | ||
draw = "STACK" | ||
|
||
|
||
def clean_vm_name(vm_name): | ||
|
@@ -57,9 +57,12 @@ def clean_vm_name(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) | ||
if os.path.isfile("/usr/libexec/qemu-kvm"): | ||
return True | ||
else: | ||
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 | ||
|
@@ -70,12 +73,12 @@ def find_vm_names(pids): | |
cmdline = open("/proc/%s/cmdline" % pid, "r") | ||
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",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-system-x86_64", shell=True, stdout=PIPE) | ||
pid = Popen("pidof qemu-kvm qemu-system-x86_64 kvm", shell=True, stdout=PIPE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this list of names lack "qemu-system-i386"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above I did not change the original behavior. So I just kept |
||
return pid.communicate()[0].split() | ||
|
||
def fetch(vms): | ||
|
@@ -85,7 +88,7 @@ def fetch(vms): | |
for ( pid, name ) in vms.iteritems(): | ||
( 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']: | ||
|
@@ -99,4 +102,3 @@ if __name__ == "__main__": | |
fetch(find_vm_names(list_pids())) | ||
else: | ||
fetch(find_vm_names(list_pids())) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,7 @@ graph_args --base 1024 | |
print "%s_read.info I/O used by virtual machine %s" % (vm, vm) | ||
print "%s_write.label %s" % (vm, vm) | ||
print "%s_write.type COUNTER" % vm | ||
print "%s_write.min 0" % vm | ||
print "%s_write.min 0" % vm | ||
print "%s_write.draw LINE1" % vm | ||
print "%s_write.negative %s_read" % (vm, vm) | ||
print "%s_write.info I/O used by virtual machine %s" % (vm, vm) | ||
|
@@ -53,7 +53,7 @@ def clean_vm_name(vm_name): | |
vm_name = re.sub(suffix,'',vm_name) | ||
|
||
return re.sub(r"[^a-zA-Z0-9_]", "_", vm_name) | ||
|
||
def fetch(vms): | ||
''' Fetch values for a list of pids | ||
@param dictionnary {kvm_pid: cleaned vm name} | ||
|
@@ -68,15 +68,18 @@ def fetch(vms): | |
if "write_bytes" in line: | ||
write = line.split()[1] | ||
print "%s_write.value %s" % (vms[pid], write) | ||
break | ||
break | ||
f.close() | ||
|
||
def detect_kvm(): | ||
''' Check if kvm is installed | ||
''' | ||
kvm = Popen("which kvm", shell=True, stdout=PIPE) | ||
kvm.communicate() | ||
return not bool(kvm.returncode) | ||
if os.path.isfile("/usr/libexec/qemu-kvm"): | ||
return True | ||
else: | ||
kvm = Popen("which kvm", shell=True, stdout=PIPE) | ||
kvm.communicate() | ||
return not bool(kvm.returncode) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||
|
||
def find_vm_names(pids): | ||
'''Find and clean vm names from pids | ||
|
@@ -87,14 +90,14 @@ def find_vm_names(pids): | |
cmdline = open("/proc/%s/cmdline" % pid, "r") | ||
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",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-system-x86_64", shell=True, stdout=PIPE) | ||
pid = Popen("pidof qemu-kvm qemu-system-x86_64 kvm", shell=True, stdout=PIPE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||
return pid.communicate()[0].split() | ||
|
||
if __name__ == "__main__": | ||
if len(sys.argv) > 1: | ||
if sys.argv[1] in ['autoconf', 'detect']: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,7 +36,7 @@ graph_args --base 1024 | |
print "%s_mem.min 0" % vm | ||
print "%s_mem.draw %s" % (vm, draw) | ||
print "%s_mem.info memory used by virtual machine %s" % (vm, vm) | ||
draw = "STACK" | ||
draw = "STACK" | ||
|
||
|
||
def clean_vm_name(vm_name): | ||
|
@@ -50,7 +50,7 @@ def clean_vm_name(vm_name): | |
vm_name = re.sub(suffix,'',vm_name) | ||
|
||
return re.sub(r"[^a-zA-Z0-9_]", "_", vm_name) | ||
|
||
def fetch(vms): | ||
''' Fetch values for a list of pids | ||
@param dictionnary {kvm_pid: cleaned vm name} | ||
|
@@ -61,19 +61,22 @@ def fetch(vms): | |
cmdline = open("/proc/%s/cmdline" % pid, "r") | ||
amount = re.sub(r"^.*-m\x00(.*)\x00-smp.*$",r"\1", cmdline.readline()) | ||
amount = int(amount) * 1024 * 1024 | ||
print "%s_mem.value %s" % (vms[pid], amount) | ||
print "%s_mem.value %s" % (vms[pid], amount) | ||
except: | ||
cmdline = open("/proc/%s/cmdline" % pid, "r") | ||
amount = re.sub(r"^.*-m\x00(\d+).*$",r"\1", cmdline.readline()) | ||
amount = int(amount) * 1024 * 1024 | ||
print "%s_mem.value %s" % (vms[pid], amount) | ||
print "%s_mem.value %s" % (vms[pid], amount) | ||
|
||
def detect_kvm(): | ||
''' Check if kvm is installed | ||
''' | ||
kvm = Popen("which kvm", shell=True, stdout=PIPE) | ||
kvm.communicate() | ||
return not bool(kvm.returncode) | ||
if os.path.isfile("/usr/libexec/qemu-kvm"): | ||
return True | ||
else: | ||
kvm = Popen("which kvm", shell=True, stdout=PIPE) | ||
kvm.communicate() | ||
return not bool(kvm.returncode) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||
|
||
def find_vm_names(pids): | ||
'''Find and clean vm names from pids | ||
|
@@ -84,14 +87,14 @@ def find_vm_names(pids): | |
cmdline = open("/proc/%s/cmdline" % pid, "r") | ||
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",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-system-x86_64", shell=True, stdout=PIPE) | ||
pid = Popen("pidof qemu-kvm qemu-system-x86_64 kvm", shell=True, stdout=PIPE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||
return pid.communicate()[0].split() | ||
|
||
if __name__ == "__main__": | ||
if len(sys.argv) > 1: | ||
if sys.argv[1] in ['autoconf', 'detect']: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
# vim: set fileencoding=utf-8 | ||
# | ||
# Munin plugin to show the network I/O per vm | ||
# On redhat based systems | ||
# | ||
# Copyright Igor Borodikhin | ||
# Copyright Peter Meier | ||
# | ||
# License : GPLv3 | ||
# | ||
# | ||
# parsed environment variables: | ||
# vmsuffix: part of vm name to be removed | ||
# | ||
#%# capabilities=autoconf | ||
#%# family=contrib | ||
|
||
import re, os, sys | ||
from subprocess import Popen, PIPE | ||
|
||
def config(vms): | ||
''' Print the plugin's config | ||
@param vm_names : a list of "cleaned" vms' name | ||
''' | ||
base_config = """graph_title KVM Network I/O | ||
graph_vlabel Bytes rx(-)/tx(+) per second | ||
graph_category Virtualization | ||
graph_info This graph shows the network I/O of the virtual machines | ||
graph_args --base 1024 | ||
""" | ||
print base_config | ||
for pid in vms: | ||
macs = get_vm_macs(pid) | ||
i = 0 | ||
for mac in macs: | ||
print "%s_eth%s_in.label %s_eth%s" % (vms[pid],i, vms[pid], i) | ||
print "%s_eth%s_in.type COUNTER" % (vms[pid], i) | ||
print "%s_eth%s_in.min 0" % (vms[pid],i) | ||
print "%s_eth%s_in.draw LINE2" % (vms[pid],i) | ||
print "%s_eth%s_out.negative %s_eth%s_in" % (vms[pid], i, vms[pid], i) | ||
print "%s_eth%s_out.label %s_eth%s" % (vms[pid], i, vms[pid], i) | ||
print "%s_eth%s_out.type COUNTER" % (vms[pid], i) | ||
print "%s_eth%s_out.min 0" % (vms[pid], i) | ||
print "%s_eth%s_out.draw LINE2" % (vms[pid], i) | ||
i += 1 | ||
|
||
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) | ||
|
||
return re.sub(r"[^a-zA-Z0-9_]", "_", vm_name) | ||
|
||
def fetch(vms): | ||
''' Fetch values for a list of pids | ||
@param dictionnary {kvm_pid: cleaned vm name} | ||
''' | ||
res = {} | ||
macs_to_inf = find_macs_to_inf() | ||
interfaces = {} | ||
for pid in vms: | ||
macs = get_vm_macs(pid) | ||
i = 0 | ||
for mac in macs: | ||
inf = macs_to_inf[mac] | ||
with open("/sys/class/net/%s/statistics/rx_packets" % inf, 'r') as f: | ||
print "%s_eth%s_in.value %s" % (vms[pid], i, f.readline()), | ||
with open("/sys/class/net/%s/statistics/tx_packets" % inf, 'r') as f: | ||
print "%s_eth%s_out.value %s" % (vms[pid], i, f.readline()), | ||
i += 1 | ||
|
||
def detect_kvm(): | ||
''' Check if kvm is installed | ||
''' | ||
if os.path.isfile("/usr/libexec/qemu-kvm"): | ||
return True | ||
else: | ||
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 dictionnary 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"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",r"\1", cmdline.readline())) | ||
return result | ||
|
||
def get_vm_macs(pid): | ||
'''Find macs for a pid | ||
@return the mac addresses for a specified pid | ||
''' | ||
cmdline = open("/proc/%s/cmdline" % pid, "r") | ||
line = cmdline.readline() | ||
# macs are fe:... on the host | ||
macs = [ re.sub(r"^\d{2}",'fe',p.split('=')[1]) for p in line.split(",") if re.match(r"^mac(addr)?=",p) ] | ||
return macs | ||
|
||
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].split() | ||
|
||
def find_macs_to_inf(): | ||
''' Find interfaces for vms | ||
@return a dictionary of macs to inf | ||
''' | ||
result = {} | ||
inf = "" | ||
kvm = Popen("ip a | grep -E -A 1 '(tap|vnet)' | awk '{print $2}' | grep -v '^$'", shell=True, stdout=PIPE) | ||
res = kvm.communicate()[0].split('\n') | ||
for line in res: | ||
if len(line) > 0: | ||
if re.match(r"^tap.*", line): | ||
inf = re.sub(r"(tap[^:]+):", r"\1", line) | ||
elif re.match(r"^vnet.*", line): | ||
inf = re.sub(r"(vnet[^:]+):", r"\1", line) | ||
else: | ||
result[line] = inf | ||
|
||
return result | ||
|
||
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())) | ||
else: | ||
fetch(find_vm_names(list_pids())) | ||
else: | ||
fetch(find_vm_names(list_pids())) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would propose to phrase this clearer (instead of relying on the coincidence of the implicit interger/boolean conversion):
return kvm.returncode == 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't change the original behavior. Just added one that fits more for RHEL/CentOS.
In general this part is from my point of view problematic in 2 cases:
I can change it in general, but as I said the intend of my PR was not to change the original behavior. But I can come up with general improvements, if people would like to see that.