mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-22 02:51:03 +00:00
More housekeeping.
This commit is contained in:
parent
038c3ce96b
commit
e5ce74926d
43 changed files with 0 additions and 0 deletions
101
plugins/virtualization/kvm_cpu
Executable file
101
plugins/virtualization/kvm_cpu
Executable file
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: set fileencoding=utf-8
|
||||
#
|
||||
# Munin plugin to show CPU used by vm
|
||||
#
|
||||
# Copyright Maxence Dunnewind, Rodolphe Quiédeville
|
||||
#
|
||||
# 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(vm_names):
|
||||
''' Print the plugin's config
|
||||
@param vm_names : a list of "cleaned" vms' name
|
||||
'''
|
||||
percent = len(filter(lambda x: x[0:3] == 'cpu' and x[3] != ' ', open('/proc/stat', 'r').readlines())) * 100
|
||||
|
||||
base_config = """graph_title KVM Virtual Machine CPU usage
|
||||
graph_vlabel %%
|
||||
graph_category KVM
|
||||
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
|
||||
draw = "AREA"
|
||||
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 %s" % (vm, draw)
|
||||
print "%s_cpu.info percent of cpu time used by virtual machine" % vm
|
||||
draw = "STACK"
|
||||
|
||||
|
||||
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 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 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 list_pids():
|
||||
''' Find the pid of kvm processes
|
||||
@return a list of pids from running kvm
|
||||
'''
|
||||
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
|
||||
return pid.communicate()[0].split()
|
||||
|
||||
def fetch(vms):
|
||||
''' Fetch values for a list of pids
|
||||
@param dictionnary {kvm_pid: cleaned vm name}
|
||||
'''
|
||||
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']:
|
||||
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()))
|
110
plugins/virtualization/kvm_io
Executable file
110
plugins/virtualization/kvm_io
Executable file
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: set fileencoding=utf-8
|
||||
#
|
||||
# Munin plugin to show io by vm
|
||||
#
|
||||
# Copyright Maxence Dunnewind, Rodolphe Quiédeville
|
||||
#
|
||||
# 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(vm_names):
|
||||
''' Print the plugin's config
|
||||
@param vm_names : a list of "cleaned" vms' name
|
||||
'''
|
||||
base_config = """graph_title KVM Virtual Machine IO usage
|
||||
graph_vlabel Bytes read(-)/written(+) per second
|
||||
graph_category KVM
|
||||
graph_info This graph shows the block device I/O used of virtual machines
|
||||
graph_args --base 1024
|
||||
"""
|
||||
print base_config
|
||||
|
||||
for vm in vm_names:
|
||||
print "%s_read.label %s" % (vm, vm)
|
||||
print "%s_read.type COUNTER" % vm
|
||||
print "%s_read.min 0" % vm
|
||||
print "%s_read.draw LINE1" % vm
|
||||
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.draw LINE1" % vm
|
||||
print "%s_write.negative %s_read" % (vm, vm)
|
||||
print "%s_write.info I/O used by virtual machine %s" % (vm, 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)
|
||||
|
||||
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 = {}
|
||||
for pid in vms:
|
||||
f = open("/proc/%s/io" % pid, "r")
|
||||
for line in f.readlines():
|
||||
if "read_bytes" in line:
|
||||
read = line.split()[1]
|
||||
print "%s_read.value %s" % (vms[pid], read)
|
||||
if "write_bytes" in line:
|
||||
write = line.split()[1]
|
||||
print "%s_write.value %s" % (vms[pid], write)
|
||||
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)
|
||||
|
||||
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 list_pids():
|
||||
''' Find the pid of kvm processes
|
||||
@return a list of pids from running kvm
|
||||
'''
|
||||
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
|
||||
return pid.communicate()[0].split()
|
||||
|
||||
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()))
|
107
plugins/virtualization/kvm_mem
Executable file
107
plugins/virtualization/kvm_mem
Executable file
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: set fileencoding=utf-8
|
||||
#
|
||||
# Munin plugin to show amount of memory used by vm
|
||||
#
|
||||
# Copyright Maxence Dunnewind, Rodolphe Quiédeville, Adrien Pujol
|
||||
#
|
||||
# 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(vm_names):
|
||||
''' Print the plugin's config
|
||||
@param vm_names : a list of "cleaned" vms' name
|
||||
'''
|
||||
base_config = """graph_title KVM Virtual Machine Memory usage
|
||||
graph_vlabel Bytes
|
||||
graph_category KVM
|
||||
graph_info This graph shows the current amount of memory used by virtual machines
|
||||
graph_args --base 1024
|
||||
"""
|
||||
print base_config
|
||||
draw = "AREA"
|
||||
for vm in vm_names:
|
||||
print "%s_mem.label %s" % (vm, vm)
|
||||
print "%s_mem.type GAUGE" % vm
|
||||
if draw == 'AREA':
|
||||
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"
|
||||
|
||||
|
||||
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 = {}
|
||||
for pid in vms:
|
||||
try:
|
||||
cmdline = open("/proc/%s/cmdline" % pid, "r")
|
||||
amount = re.sub(r"^.*-m\x00(.*)\x00-smp.*$",r"\1", cmdline.readline())
|
||||
ammount = int(amount) * 1024 * 1024
|
||||
print "%s_mem.value %s" % (vms[pid], ammount)
|
||||
except:
|
||||
cmdline = open("/proc/%s/cmdline" % pid, "r")
|
||||
amount = re.sub(r"^.*-m\x00(\d+).*$",r"\1", cmdline.readline())
|
||||
ammount = int(amount) * 1024 * 1024
|
||||
print "%s_mem.value %s" % (vms[pid], ammount)
|
||||
|
||||
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 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 list_pids():
|
||||
''' Find the pid of kvm processes
|
||||
@return a list of pids from running kvm
|
||||
'''
|
||||
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
|
||||
return pid.communicate()[0].split()
|
||||
|
||||
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()))
|
141
plugins/virtualization/kvm_net
Executable file
141
plugins/virtualization/kvm_net
Executable file
|
@ -0,0 +1,141 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: set fileencoding=utf-8
|
||||
#
|
||||
# Munin plugin to show the network I/O per vm
|
||||
#
|
||||
# Copyright Igor Borodikhin
|
||||
#
|
||||
# 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(vm_names):
|
||||
''' 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 KVM
|
||||
graph_info This graph shows the network I/O of the virtual machines
|
||||
graph_args --base 1024
|
||||
"""
|
||||
print base_config
|
||||
for vm in vm_names:
|
||||
print "%s_in.label %s" % (vm, vm)
|
||||
print "%s_in.type COUNTER" % vm
|
||||
print "%s_in.min 0" % vm
|
||||
print "%s_in.draw LINE2" % vm
|
||||
print "%s_out.negative %s_in" % (vm, vm)
|
||||
print "%s_out.label %s" % (vm, vm)
|
||||
print "%s_out.type COUNTER" % vm
|
||||
print "%s_out.min 0" % vm
|
||||
print "%s_out.draw LINE2" % 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)
|
||||
|
||||
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 = {}
|
||||
for pid in vms:
|
||||
tap = get_vm_mac(pid)
|
||||
try:
|
||||
f = open("/proc/net/dev", "r")
|
||||
for line in f.readlines():
|
||||
if tap in line:
|
||||
print "%s_in.value %s" % (vms[pid], re.sub(r"%s:"%tap, "", line.split()[0]))
|
||||
print "%s_out.value %s" % (vms[pid], line.split()[8])
|
||||
break
|
||||
except Exception as inst:
|
||||
print inst
|
||||
continue
|
||||
|
||||
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 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_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 list_pids():
|
||||
''' Find the pid of kvm processes
|
||||
@return a list of pids from running kvm
|
||||
'''
|
||||
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
|
||||
return pid.communicate()[0].split()
|
||||
|
||||
def find_vms_tap():
|
||||
''' Check if kvm is installed
|
||||
@return a list of pids from running kvm
|
||||
'''
|
||||
result = []
|
||||
tap = ""
|
||||
mac = ""
|
||||
kvm = Popen("ip a | grep -A 1 tap | awk '{print $2}' | grep -v '^$'", shell=True, stdout=PIPE)
|
||||
res = kvm.communicate()[0].split('\n')
|
||||
for line in res:
|
||||
try:
|
||||
if len(line) > 0:
|
||||
if re.match(r"^tap.*", line):
|
||||
tap = re.sub(r"(tap[^:]+):", r"\1", line)
|
||||
else:
|
||||
result.append(tap)
|
||||
except Exception as inst:
|
||||
continue
|
||||
|
||||
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()).values())
|
||||
else:
|
||||
fetch(find_vm_names(list_pids()))
|
||||
else:
|
||||
fetch(find_vm_names(list_pids()))
|
||||
|
||||
|
59
plugins/virtualization/munin-libvirtpy
Executable file
59
plugins/virtualization/munin-libvirtpy
Executable file
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Revision 1.0 2008/05/16 - Steven Wagner
|
||||
# First functional release. Works for me.
|
||||
#
|
||||
# Revision 0.5 2008/05/01 - Julien Rottenberg
|
||||
# initial display of variables from libvirt
|
||||
|
||||
#python-libvirt is required
|
||||
|
||||
import libvirt
|
||||
import sys
|
||||
|
||||
conn = libvirt.openReadOnly("qemu:///system")
|
||||
if conn == None:
|
||||
print 'Failed to open connection to the hypervisor'
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
(model, memory, cpus, mhz, nodes, socket, cores, threads) = conn.getInfo()
|
||||
except:
|
||||
print 'getInfo failed'
|
||||
sys.exit(1)
|
||||
|
||||
#print
|
||||
#print "KVM running on %d %s %d mhz CPUs w/ %d MB RAM." % (cpus, model, mhz, memory)
|
||||
#print
|
||||
|
||||
ids = conn.listDomainsID()
|
||||
if ids == None or len(ids) == 0:
|
||||
print 'No running domains found.'
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == "config":
|
||||
print "graph_title KVM Domain CPU Utilization"
|
||||
print "graph_vlabel CPU use in seconds"
|
||||
print "graph_args --base 1000"
|
||||
print "graph_category kvm"
|
||||
|
||||
for id in ids:
|
||||
dom = conn.lookupByID(id)
|
||||
nodeName = dom.name()
|
||||
print "%s.type COUNTER" %(nodeName)
|
||||
print "%s.label %s" %(nodeName, nodeName)
|
||||
sys.exit(1)
|
||||
|
||||
for id in ids:
|
||||
dom = conn.lookupByID(id)
|
||||
state, maxMem, memory, numVirtCpu, cpuTime = dom.info()
|
||||
nodeName = dom.name()
|
||||
# uuid = dom.UUID()
|
||||
# ostype = dom.OSType()
|
||||
# print """Domain: %s, %s state (%s), %d CPUs, %d seconds, %d milliseconds, mem/max (%d/%d) """ \
|
||||
# % (nodeName, ostype, state, numVirtCpu, cpuTime/float(1000000000), cpuTime/float(1000000), memory, maxMem )
|
||||
print "%s.value %d" % (nodeName, cpuTime/float(1000000))
|
||||
|
||||
|
668
plugins/virtualization/vmware/esx_
Executable file
668
plugins/virtualization/vmware/esx_
Executable file
|
@ -0,0 +1,668 @@
|
|||
#!/usr/bin/perl -w
|
||||
=HEADER
|
||||
-== Munin plugin for VMware ESXi/vSphere monitoring ==-
|
||||
|
||||
Copyright (c) 2012 - Stefan Seidel <munin@stefanseidel.info>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
This plugin uses the vSphere SDK for Perl available at
|
||||
http://www.vmware.com/support/developer/viperltoolkit/
|
||||
or included in the vSphere CLI available at
|
||||
http://www.vmware.com/support/developer/vcli/
|
||||
The use of the SDK is subject to the terms and condition
|
||||
of VMware, Inc. to which you must agree upon installation.
|
||||
=cut
|
||||
|
||||
=USAGE
|
||||
-== Usage ==-
|
||||
Put this file in /usr/share/munin/plugins, `chmod +x` it and
|
||||
`ln -s` it to /etc/munin/plugins/esx_<hostname of server to monitor>
|
||||
Add a file "esx_" /etc/munin/plugin-conf.d with content like this
|
||||
(omit the "# " at the beginning of each line)
|
||||
|
||||
---- snip ----
|
||||
[esx_*]
|
||||
timeout 60
|
||||
env.user <username on ESX server or vCenter>
|
||||
env.password <password of user on ESX server or vCenter>
|
||||
---- snip ----
|
||||
|
||||
Then you need to add this host to your munin.conf on the munin server
|
||||
(often this is the same as your munin node, i.e. this host) and restart
|
||||
munin-node, and wait for the data to populate.
|
||||
|
||||
|
||||
-== Query all hosts of a vCenter ==-
|
||||
An alternate way of using this plugin is to link it to
|
||||
/etc/munin/plugins/vcenter_<hostname_of_vcenter>
|
||||
In this mode, the vCenter server specified in the filename is queried
|
||||
for a list of hosts it manages, and graphs are created for all these
|
||||
hosts. The option "flatview" is implied in this mode, since one munin
|
||||
plugin can only be assigned to one host. The option "vCenter" is ignored
|
||||
since the vCenter server is given through the file name. You can, however
|
||||
still use the option "flatview" to override the "host_name" under which
|
||||
the results are reported. Make sure to read the section below about
|
||||
this option!
|
||||
|
||||
|
||||
-== Graphs don't render ==-
|
||||
Munin 1.4 has a bug with complex multigraphs like this, see
|
||||
http://munin-monitoring.org/ticket/1224 for details and a fix if
|
||||
your graphs don't render!
|
||||
|
||||
|
||||
-== Option flatview ==-
|
||||
There is an option to render all VMs and Host Systems in a flat
|
||||
structure, i.e. not rendering VMs as sub-items of their host.
|
||||
This is useful if you frequently move VMs between hosts and want to
|
||||
keep the VM graphs running. To activate this option, add
|
||||
|
||||
---- snip ----
|
||||
env.flatview top_level_entry
|
||||
---- snip ----
|
||||
|
||||
to the entry in your config file in /etc/munin/plugin-conf.d (see above).
|
||||
Be aware that this has some drawbacks:
|
||||
- you cannot have the same VM name in two hosts you monitor
|
||||
(the VM name is the unique identifier for the graphs)
|
||||
- you will only indirectly be able to see which VM is on which host
|
||||
(running VMs will appear in the CPU graphs of their hosts)
|
||||
- it's a flat structure, so it can become quite a long list
|
||||
- because of the way Munin works, all hosts will be queried serially,
|
||||
not in parallel as it would be the case without "flat view" - this
|
||||
MAY lead to timing problems if you have a large number of hosts or VMs
|
||||
|
||||
|
||||
-== Option vCenter ==-
|
||||
If you wish to access the host system indirectly through a vCenter, just
|
||||
specify this parameter:
|
||||
|
||||
---- snip ----
|
||||
env.vCenter <address or hostname of the vCenter>
|
||||
---- snip ----
|
||||
|
||||
This option can be used with or without the "flatview" option. Make sure your
|
||||
password and username are valid on the vCenter. The plugin name will still have
|
||||
to contain the hostname of the host you want to monitor - be aware that you have
|
||||
to use the hostname exactly as it is registered in the vCenter, so IPs and
|
||||
hostnames are NOT interchangeable.
|
||||
=cut
|
||||
|
||||
=ACK
|
||||
-== Ackknowledgements ==-
|
||||
I would like to thank VMware for their SDK and the good documentation.
|
||||
|
||||
Special thanks go to MEGABIT Informationstechnik GmbH (www.megabit.net)
|
||||
who graciously sponsored the development of the "flat view" option
|
||||
and the ability to access hosts via vCenter as well as the feature to
|
||||
query all hosts on the vCenter.
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use sort 'stable'; # guarantee stability
|
||||
no warnings; # don't want warnings in output
|
||||
|
||||
use VMware::VIRuntime; # need to install VIM SDK (vSphere CLI/SDK 4.1 or newer)
|
||||
use VMware::VILib;
|
||||
use VMware::VIExt;
|
||||
use Data::Dumper;
|
||||
use DateTime::Format::ISO8601; # may need to install "libdatetime-format-iso8601-perl" on Debian-based systems
|
||||
use List::Util qw(sum max);
|
||||
use List::MoreUtils qw(all);
|
||||
use Munin::Plugin;
|
||||
use Time::HiRes qw(time);
|
||||
my $DEBUG = ${Munin::Plugin::DEBUG};
|
||||
|
||||
# Important: this is needed if you do not use a "proper" SSL certificate
|
||||
# on your vSphere/vCenter/ESX(i) server (which is the default)
|
||||
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
|
||||
|
||||
# for datetime parsing later on
|
||||
my $iso8601 = DateTime::Format::ISO8601->new;
|
||||
my @host_names = ();
|
||||
my $host_name;
|
||||
my $host_view;
|
||||
my $dtsys;
|
||||
my $perfMan;
|
||||
my %perfCounter;
|
||||
# IDs/UUIDs to human readable names
|
||||
my $resolveNames;
|
||||
|
||||
if ($0 =~ /vcenter_(.+)$/) {
|
||||
$ENV{vCenter} = $1;
|
||||
$ENV{flatview} = $ENV{flatview} || $ENV{vCenter};
|
||||
my $vpid = open(FH, "-|");
|
||||
if ($vpid == 0) {
|
||||
Opts::set_option ('username', $ENV{user} || 'root');
|
||||
Opts::set_option ('password', $ENV{password} || '');
|
||||
Opts::set_option ('server', $ENV{vCenter});
|
||||
Util::connect();
|
||||
foreach (@{Vim::find_entity_views(view_type => 'HostSystem', properties => ['name'])}) {
|
||||
print $_->{name}, "\n";
|
||||
}
|
||||
Util::disconnect();
|
||||
exit 0;
|
||||
} else {
|
||||
while (<FH>) {
|
||||
push @host_names, trim($_);
|
||||
print "# found host ",trim($_)," on vCenter\n" if $DEBUG;
|
||||
}
|
||||
close FH;
|
||||
}
|
||||
} else {
|
||||
# get hostname from filename and blurt it out immediately
|
||||
# so that when something goes wrong, at least the plugin
|
||||
# output is linked with the right host
|
||||
$0 =~ /esx_(.+)$/;
|
||||
push @host_names, $1;
|
||||
}
|
||||
|
||||
my @returns = ();
|
||||
|
||||
foreach $host_name (@host_names) {
|
||||
# make sure we only print one host_name statement per plugin
|
||||
if ((@returns == 0) and (defined $ARGV[0]) and ($ARGV[0] eq "config")) {
|
||||
if ($ENV{flatview}) {
|
||||
print "host_name $ENV{flatview}\n";
|
||||
print "# for host $host_name\n" if $DEBUG;
|
||||
} else {
|
||||
print "host_name $host_name\n";
|
||||
}
|
||||
}
|
||||
local *FH;
|
||||
my $pid = open(FH, "-|");
|
||||
if ($pid == 0) {
|
||||
# CHILD
|
||||
|
||||
|
||||
# env.user and env.password need to be set in plugin-conf.d
|
||||
Opts::set_option ('username', $ENV{user} || 'root');
|
||||
Opts::set_option ('password', $ENV{password} || '');
|
||||
if ($ENV{vCenter}) {
|
||||
print "# vCenter: $ENV{vCenter} - host $host_name\n" if $DEBUG;
|
||||
Opts::add_options ( (vihost => { alias => "h", type => "=s", required => 0 }) );
|
||||
Opts::set_option ('vihost',$host_name);
|
||||
Opts::set_option ('server',$ENV{vCenter});
|
||||
} else {
|
||||
Opts::set_option ('server',$host_name);
|
||||
}
|
||||
|
||||
|
||||
# plugin needs Munin 1.4 or later
|
||||
need_multigraph();
|
||||
|
||||
my $sstarttime = time();
|
||||
|
||||
# connect to vSphere host
|
||||
Util::connect();
|
||||
|
||||
# central object host_view holds all relevant items (VMs, network, etc.)
|
||||
$host_view = VIExt::get_host_view(1, ['summary', 'network', 'datastore', 'vm', 'runtime', 'configManager.networkSystem', 'configManager.dateTimeSystem']);
|
||||
Opts::assert_usage(defined($host_view), "Invalid host.");
|
||||
|
||||
my $serviceInst = Vim::get_view (mo_ref => ManagedObjectReference->new(type => 'ServiceInstance', value => 'ServiceInstance'));
|
||||
# Performance Manager for getting the actual values
|
||||
$perfMan = Vim::get_view (mo_ref => $serviceInst->content->perfManager);
|
||||
Opts::assert_usage(defined($perfMan), "No PerformanceManager.");
|
||||
|
||||
# may be needed later
|
||||
#my $netsys = Vim::get_view(mo_ref => ManagedObjectReference->new(type => 'HostNetworkSystem', value => 'networkSystem'));
|
||||
#Opts::assert_usage(defined($netsys), "No NetworkSystem.");
|
||||
|
||||
# used for getting the current vSphere server time and then
|
||||
# defining the (now - 5minutes) interval
|
||||
$dtsys = Vim::get_view(mo_ref => $host_view->{'configManager.dateTimeSystem'});
|
||||
Opts::assert_usage(defined($dtsys), "No DateTimeSystem.");
|
||||
|
||||
print "# time to connect and get objects: ", time() - $sstarttime, "\n" if $DEBUG;
|
||||
|
||||
# enumerate all performance counters by their IDs
|
||||
%perfCounter = map { $_->key => $_ } @{$perfMan->perfCounter};
|
||||
# holds all performance data
|
||||
my @all_perf_data = ();
|
||||
# store VM ids for iteration later on
|
||||
my @all_vms = ();
|
||||
|
||||
$host_view->update_view_data();
|
||||
# retrieve performance counters for host
|
||||
push @all_perf_data, get_perf_data($host_view);
|
||||
# manually set UF name for host system
|
||||
$resolveNames->{vm}->{""} = "Host System";
|
||||
|
||||
# only purpose of this loop is getting the UF network names
|
||||
# network ManagedObjects do not have performance counters
|
||||
for ($host_view->network) {
|
||||
for (@$_) {
|
||||
my $network = Vim::get_view (mo_ref => $_);
|
||||
$resolveNames->{net}->{$_->{value}} = $_->{value}." (".$network->summary->name.")";
|
||||
}
|
||||
}
|
||||
|
||||
# purpose of this loop is getting the UF datastore names
|
||||
# and retrieving capacity and free/uncommitted space
|
||||
# datastore ManagedObjects do not have performance counters
|
||||
for ($host_view->datastore) {
|
||||
for (@$_) {
|
||||
my $datastore = Vim::get_view (mo_ref => $_);
|
||||
# update freeSpace values (doesn't work on free ESXi)
|
||||
eval { $datastore->RefreshDatastore(); };
|
||||
$datastore->update_view_data();
|
||||
my $uuid =$datastore->summary->url;
|
||||
$uuid =~ s!.+/!!;
|
||||
$resolveNames->{datastore}->{$uuid} = $datastore->name;
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "datastore",
|
||||
name => "capacity",
|
||||
value => $datastore->summary->capacity,
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => "Capacity", summary => "Maximum amount of storage space on this datastore")),
|
||||
vm => "",
|
||||
instance => $uuid,
|
||||
unit => "Bytes" });
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "datastore",
|
||||
name => "freeSpace",
|
||||
value => $datastore->summary->freeSpace,
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => "Free", summary => "Total amount of unused, available storage space on this datastore")),
|
||||
vm => "",
|
||||
instance => $uuid,
|
||||
unit => "Bytes" });
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "datastore",
|
||||
name => "uncommitted",
|
||||
value => $datastore->summary->uncommitted,
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => "Uncommitted", summary => "Total additional storage space, potentially used by all virtual machines on this datastore")),
|
||||
vm => "",
|
||||
instance => $uuid,
|
||||
unit => "Bytes" });
|
||||
}
|
||||
}
|
||||
|
||||
# iterate over all vms
|
||||
for ($host_view->vm) {
|
||||
for (@$_) {
|
||||
my $vm = Vim::get_view (mo_ref => $_);
|
||||
$vm->update_view_data();
|
||||
# store VM id for later iteration
|
||||
my $vmId = $_->{value};
|
||||
push @all_vms, $vmId;
|
||||
# ID to VM name
|
||||
$resolveNames->{vm}->{$vmId} = "VM ".$vm->summary->config->name;
|
||||
$resolveNames->{vmuuid}->{$vmId} = $vm->summary->config->uuid;
|
||||
# fetch disk space usage per datastore
|
||||
for (@{$vm->storage->perDatastoreUsage}) {
|
||||
my $uuid = Vim::get_view(mo_ref => $_->datastore)->summary->url;
|
||||
$uuid =~ s!.+/!!;
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "datastore",
|
||||
name => "committed",
|
||||
value => $_->committed,
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => "Comitted", summary => "Storage space, in bytes, on this datastore that is actually being used by the virtual machine.\n\nIt includes space actually occupied by disks, logs, snapshots, configuration files etc. Files of the virtual machine which are present on a different datastore (e.g. a virtual disk on another datastore) are not included here.\n\n")),
|
||||
vm => $vmId,
|
||||
instance => $uuid,
|
||||
unit => "Bytes" });
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "datastore",
|
||||
name => "uncommitted",
|
||||
value => $_->uncommitted,
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => "Uncomitted", summary => "Additional storage space, in bytes, potentially used by the virtual machine on this datastore.\n\nAdditional space may be needed for example when lazily allocated disks grow, or storage for swap is allocated when powering on the virtual machine.\n\nIf the virtual machine is running off delta disks (for example because a snapshot was taken), then only the potential growth of the currently used delta-disks is considered.\n\n")),
|
||||
vm => $vmId,
|
||||
instance => $uuid,
|
||||
unit => "Bytes" });
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "datastore",
|
||||
name => "unshared",
|
||||
value => $_->unshared,
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => "Unshared", summary => "Storage space, in bytes, occupied by the virtual machine on this datastore that is not shared with any other virtual machine.\n\n")),
|
||||
vm => $vmId,
|
||||
instance => $uuid,
|
||||
unit => "Bytes" });
|
||||
}
|
||||
# retrieve performance counters for this VM
|
||||
push @all_perf_data, get_perf_data ($_);
|
||||
}
|
||||
}
|
||||
|
||||
# keep track of how many sensors are in which state
|
||||
my %sensorCount = ( green => 0, red => 0, unknown => 0, yellow => 0 );
|
||||
|
||||
# iterate over all sensor data
|
||||
my $index = 0;
|
||||
for (@{$host_view->runtime->healthSystemRuntime->systemHealthInfo->numericSensorInfo}) {
|
||||
# update counters
|
||||
$sensorCount{$_->healthState->key}++;
|
||||
# do not create entries for unmonitorable things like software components
|
||||
next unless ($_->baseUnits =~ /.+/);
|
||||
# create entry with sensor data
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "sensors",
|
||||
name => "sensor_".($index++),
|
||||
value => $_->currentReading,
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => $_->name, summary => "Sensor data for the ".$_->sensorType." sensor ".$_->name.". ".$_->healthState->summary." (".$_->healthState->label.")")),
|
||||
vm => "",
|
||||
instance => "",
|
||||
unitModifier => $_->unitModifier,
|
||||
unit => $_->baseUnits });
|
||||
}
|
||||
|
||||
# we're finished querying the server, so we can disconnect now
|
||||
Util::disconnect();
|
||||
|
||||
# create entries for the green/red/yellow/unknown counters
|
||||
for (keys %sensorCount) {
|
||||
push (@all_perf_data,
|
||||
{ rollup => "latest",
|
||||
group => "sensors",
|
||||
name => $_."_sensors",
|
||||
value => $sensorCount{$_},
|
||||
counter => PerfCounterInfo->new(nameInfo => ElementDescription->new(label => ucfirst($_), summary => "Count of sensors in the $_ state")),
|
||||
vm => "",
|
||||
instance => "",
|
||||
unit => "Numbers" });
|
||||
}
|
||||
|
||||
if ($DEBUG) {
|
||||
foreach (sort { $a->{group} cmp $b->{group} || $a->{instance} cmp $b->{instance} || $a->{name} cmp $b->{name} || $a->{rollup} cmp $b->{rollup} || $a->{vm} cmp $b->{vm} } @all_perf_data) {
|
||||
print "# $_->{vm}\t$_->{rollup}\t$_->{group}\t$_->{instance}\t$_->{name}\t$_->{value}\t$_->{unit}\n";
|
||||
}
|
||||
}
|
||||
|
||||
# which graphs to draw
|
||||
my @all_graphs = ();
|
||||
|
||||
# host system
|
||||
push @all_graphs, (
|
||||
{ selector => { group => qr/^cpu$/i, name => qr/^usagemhz$/i, instance => qr/^$/ },
|
||||
config => { groupBy => "group", graphName => "host_cpu", graphTitle => "CPU usage per " }
|
||||
},
|
||||
{ selector => { group => qr/^disk$/i, name => qr/^(read|usage|write)$/i, instance => qr/.+/ },
|
||||
config => { groupBy => "group", graphName => "host_disk_transfer", graphTitle => "Disk Transfer Rates per " }
|
||||
},
|
||||
{ selector => { group => qr/^disk$/i, name => qr/^.+Averaged$/i, instance => qr/.+/ },
|
||||
config => { groupBy => "group", graphName => "host_disk_iops", graphTitle => "Disk I/O operations per " }
|
||||
},
|
||||
{ selector => { group => qr/^disk$/i, name => qr/^.+Latency$/i, instance => qr/.+/, vm => qr/^$/ },
|
||||
config => { groupBy => "vm", graphName => "host_disk_latency", graphTitle => "Disk latency for " }
|
||||
},
|
||||
{ selector => { group => qr/^mem$/i, unit => qr/^KB$/i, rollup => qr/^none$/, vm => qr/^$/ },
|
||||
config => { groupBy => "vm", graphName => "host_memory", graphTitle => "Memory usage for " }
|
||||
},
|
||||
{ selector => { group => qr/^datastore$/i, unit => qr/^Bytes$/i, vm => qr/^$/ },
|
||||
config => { groupBy => "vm", graphName => "usage_datastore", graphTitle => "Disk space usage for ", graphArgs => "--lower-limit 10737418240 --logarithmic --alt-autoscale-min --units=si" }
|
||||
},
|
||||
{ selector => { group => qr/^net$/i, unit => qr/^KBps$/i, vm => qr/^$/ },
|
||||
config => { groupBy => "vm", graphName => "host_traffic_net", graphTitle => "Network traffic for " }
|
||||
},
|
||||
{ selector => { group => qr/^net$/i, unit => qr/^Number$/i, vm => qr/^$/ },
|
||||
config => { groupBy => "vm", graphName => "host_packets_net", graphTitle => "Network packets for " }
|
||||
},
|
||||
{ selector => { group => qr/^power$/i, name => qr/^power$/i },
|
||||
config => { groupBy => "group", graphName => "power_usage", graphTitle => "Host System and VM " }
|
||||
},
|
||||
{ selector => { group => qr/^sys$/i, name => qr/^diskUsage$/i },
|
||||
config => { groupBy => "name", graphName => "host_disk_usage", graphTitle => "Host System " }
|
||||
},
|
||||
{ selector => { group => qr/^sys$/i, name => qr/^uptime$/i },
|
||||
config => { groupBy => "name", graphName => "uptimes", graphTitle => "Host System and VM ", graphArgs => "--lower-limit 1000 --logarithmic --alt-autoscale-min" }
|
||||
}
|
||||
);
|
||||
|
||||
# graphs per VM
|
||||
foreach (@all_vms) {
|
||||
my $vmName = clean_fieldname($resolveNames->{vm}->{$_});
|
||||
push @all_graphs, (
|
||||
{ selector => { group => qr/^cpu$/i, name => qr/^usagemhz$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_cpu", graphTitle => "CPU usage for " }
|
||||
},
|
||||
{ selector => { group => qr/^mem$/i, unit => qr/^KB$/i, rollup => qr/^none$/, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_memory", graphTitle => "Memory usage for " }
|
||||
},
|
||||
{ selector => { group => qr/^datastore$/i, unit => qr/^Bytes$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_datastore", graphTitle => "Disk space usage for ", graphArgs => "--lower-limit 10485760 --logarithmic --alt-autoscale-min --units=si" }
|
||||
},
|
||||
{ selector => { group => qr/^virtualDisk$/i, unit => qr/^Millisecond$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_disklat", graphTitle => "Disk latency for " }
|
||||
},
|
||||
{ selector => { group => qr/^virtualDisk$/i, unit => qr/^Number$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_diskiops", graphTitle => "Disk I/O operations for " }
|
||||
},
|
||||
{ selector => { group => qr/^virtualDisk$/i, unit => qr/^KBps$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_disktrans", graphTitle => "Disk transfer rates for " }
|
||||
},
|
||||
{ selector => { group => qr/^net$/i, unit => qr/^KBps$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_traffic_net", graphTitle => "Network traffic for " }
|
||||
},
|
||||
{ selector => { group => qr/^net$/i, unit => qr/^Number$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_packets_net", graphTitle => "Network packets for " }
|
||||
},
|
||||
{ selector => { group => qr/^sys$/i, name => qr/^uptime$/i, vm => qr/^$_$/ },
|
||||
config => { groupBy => "vm", graphName => "$vmName.vm_uptime", graphTitle => "VM uptime " }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
# sensor graphs
|
||||
push @all_graphs, (
|
||||
{ selector => { group => qr/^sensors$/i },
|
||||
config => { groupBy => "unit", graphName => "sensor_", graphTitle => "Sensors ", multiGraph => 1 }
|
||||
});
|
||||
|
||||
print "# time to collect all data: ", time() - $sstarttime, "\n" if $DEBUG;
|
||||
|
||||
# actual processing
|
||||
foreach (@all_graphs) {
|
||||
if ((defined $ARGV[0]) and ($ARGV[0] eq "config")) {
|
||||
munin_print("config", \@all_perf_data, $_);
|
||||
munin_print("values", \@all_perf_data, $_) if $ENV{MUNIN_CAP_DIRTYCONFIG}; # this doesn't seem to work even on Munin 1.4.6
|
||||
} else {
|
||||
munin_print("values", \@all_perf_data, $_);
|
||||
}
|
||||
}
|
||||
|
||||
print "# time of the script: ", time() - $sstarttime, "\n" if $DEBUG;
|
||||
|
||||
exit 0;
|
||||
} else {
|
||||
# PARENT
|
||||
push @returns, *FH;
|
||||
}
|
||||
}
|
||||
|
||||
# gather and print the output of the forked processes
|
||||
foreach my $fh (@returns) {
|
||||
while (<$fh>) {
|
||||
print $_;
|
||||
}
|
||||
close ($fh);
|
||||
}
|
||||
|
||||
exit 0;
|
||||
|
||||
####################################################################
|
||||
|
||||
# calculate sum, max or avg from performance data values
|
||||
sub process_value_array {
|
||||
my $arr = shift;
|
||||
my $pd = shift;
|
||||
my @vs = ();
|
||||
if ($pd->unitInfo->key eq "percent") {
|
||||
@vs = map { $_ / 100 } @$arr ;
|
||||
} else {
|
||||
@vs = @$arr;
|
||||
}
|
||||
return sum(@vs) if $pd->rollupType->val eq "summation";
|
||||
return max(@vs) if $pd->nameInfo->key =~ /max/i;
|
||||
return sum(@vs)/@$arr;
|
||||
}
|
||||
|
||||
# query performance data for object
|
||||
sub get_perf_data {
|
||||
my $entity = shift;
|
||||
my @ret = ();
|
||||
my $gathstart = time();
|
||||
# get the current server time
|
||||
my $curtime = $iso8601->parse_datetime($dtsys->QueryDateTime());
|
||||
# and subtract 5 minutes to get all values for the last period
|
||||
my $oldtime = $curtime->clone->add(minutes => -5);
|
||||
|
||||
# actual query, intervalId is 20 because that's the default
|
||||
my $perfQ = $perfMan->QueryPerf(querySpec => PerfQuerySpec->new(entity => $entity, intervalId => 20, startTime => $oldtime));
|
||||
|
||||
# loop over PerfEntityMetric
|
||||
foreach (defined $perfQ ? @$perfQ : ()) {
|
||||
my $vm = ($_->entity->type eq 'VirtualMachine')?$_->entity->value:"";
|
||||
# loop over PerfMetricIntSeries
|
||||
foreach (@{$_->{value}}) {
|
||||
my $perfDesc = $perfCounter{$_->id->counterId};
|
||||
next unless defined $perfDesc;
|
||||
push @ret, { rollup => $perfDesc->rollupType->val,
|
||||
group => $perfDesc->groupInfo->key,
|
||||
name => $perfDesc->nameInfo->key,
|
||||
value => process_value_array(\@{$_->{value}}, $perfDesc),
|
||||
counter => $perfDesc,
|
||||
vm => $vm,
|
||||
instance => $_->id->instance,
|
||||
unit => $perfDesc->unitInfo->label };
|
||||
}
|
||||
}
|
||||
print "# time to gather info for $entity :", time() - $gathstart, "\n" if $DEBUG;
|
||||
return @ret;
|
||||
}
|
||||
|
||||
# generate a munin-friendly and unique field name
|
||||
sub gen_dp_name {
|
||||
my $fname = $_[0]->{name};
|
||||
$fname .= "v".$resolveNames->{vmuuid}->{$_[0]->{vm}} unless $_[1] eq "vm" or $_[0]->{vm} eq "";
|
||||
$fname .= "i$_[0]->{instance}" unless $_[1] eq "instance" or $_[0]->{instance} eq "";
|
||||
return clean_fieldname($fname);
|
||||
}
|
||||
|
||||
# trim white spaces
|
||||
sub trim {
|
||||
my $string = shift;
|
||||
$string =~ s/^\s+//;
|
||||
$string =~ s/\s+$//;
|
||||
return $string;
|
||||
}
|
||||
|
||||
# print values and configs for graphs
|
||||
sub munin_print {
|
||||
# action
|
||||
my $act = shift || "";
|
||||
# values
|
||||
my $arr = shift || ();
|
||||
# parameters
|
||||
my $par = shift || {};
|
||||
my $cfg = $par->{config};
|
||||
$par = $par->{selector};
|
||||
my $oldGroup = "_-_";
|
||||
my $factor;
|
||||
if ($ENV{flatview}) {
|
||||
$cfg->{graphName} = clean_fieldname("Host_".$host_view->name).".".$cfg->{graphName} unless $cfg->{graphName} =~ m/\./;
|
||||
}
|
||||
|
||||
# find values according to criteria in $par and sort by grouping parameter
|
||||
#foreach (sort { $a->{$cfg->{groupBy}} cmp $b->{$cfg->{groupBy}} } grep { my $d = $_; all { (not exists $d->{$_}) || $d->{$_} =~ /$par->{$_}/ } keys %$par; } @$arr) {
|
||||
foreach (sort { $a->{$cfg->{groupBy}} cmp $b->{$cfg->{groupBy}} } grep { my $d = $_; all { (not exists $d->{$_}) || $d->{$_} =~ /$par->{$_}/ } keys %$par; } @$arr) {
|
||||
my $groupCrit = $cfg->{groupBy} || "";
|
||||
my $curGroup = $_->{$groupCrit} || "";
|
||||
|
||||
if (!($curGroup eq $oldGroup)) {
|
||||
# we're in a new group, meaning a new graph starts
|
||||
$factor = 0;
|
||||
# clean up group name for multigraph name
|
||||
my $ccurGroup = $curGroup;
|
||||
$ccurGroup =~ s/ |\./_/g;
|
||||
print "multigraph ",$cfg->{graphName},(exists $cfg->{multiGraph}?$ccurGroup:""),"\n";
|
||||
|
||||
if ("config" eq $act) {
|
||||
# want configuration
|
||||
print "graph_title ",$cfg->{graphTitle},$resolveNames->{$groupCrit}->{$curGroup} || $curGroup,"\n";
|
||||
#print "graph_order xxx yyy\n";
|
||||
|
||||
my $unit = $_->{unit};
|
||||
my $base = 1000;
|
||||
|
||||
# since the y-axis markers are going to be wrong with source units like
|
||||
# KB, MB, MHz etc., we define a correction factor via cdef later
|
||||
# this way, if 1024 MB is reported, the graph shows 1G and not 1k
|
||||
# (although 1k MB is technically also correct, but confusing)
|
||||
if ($unit =~ /^Bytes$/i) {
|
||||
$base = 1024;
|
||||
} elsif ($unit =~ /^KBps$/i) {
|
||||
$unit = "Bytes/s";
|
||||
$factor = 1024;
|
||||
$base = 1024;
|
||||
} elsif ($unit =~ /^KB$/i) {
|
||||
$unit = "Bytes";
|
||||
$factor = 1024;
|
||||
$base = 1024;
|
||||
} elsif ($unit =~ /^MB$/i) {
|
||||
$unit = "Bytes";
|
||||
$factor = 1024*1024;
|
||||
$base = 1024;
|
||||
} elsif ($unit =~ /^MHz$/i) {
|
||||
$unit = "Hz";
|
||||
$factor = 1000000;
|
||||
} elsif ($unit =~ /^Millisecond$/i) {
|
||||
$unit = "Second";
|
||||
$factor = 1/1000;
|
||||
}
|
||||
print "graph_vlabel $unit\n";
|
||||
print "graph_category $_->{group}\n";
|
||||
print "graph_args --base=$base --alt-autoscale-max ",(defined $cfg->{graphArgs})?$cfg->{graphArgs}:"","\n";
|
||||
}
|
||||
|
||||
}
|
||||
$oldGroup = $curGroup;
|
||||
my $dpName = gen_dp_name($_, $groupCrit);
|
||||
if ("config" eq $act) {
|
||||
# want configuration
|
||||
# get instance and VM names and UF names, if applicable
|
||||
my $iName = $resolveNames->{$_->{group}}->{$_->{instance}} || (("" eq $_->{instance})?"":$_->{group}." ".$_->{instance});
|
||||
$iName = " $iName" if $iName;
|
||||
my $vmName = $resolveNames->{vm}->{$_->{vm}};
|
||||
$vmName = " $vmName" if $vmName;
|
||||
# all values are drawn as lines for now
|
||||
print "$dpName.draw LINE2\n";
|
||||
print "$dpName.label ",$_->{counter}->nameInfo->label,$iName,("vm" eq $groupCrit)?"":$vmName || "","\n";
|
||||
my $summary = $_->{counter}->nameInfo->summary;
|
||||
$summary =~ s!\n!\\n!g;
|
||||
print "$dpName.info ",$summary,$iName?", instance$iName ($_->{instance})":"",$vmName?",$vmName":"","\n";
|
||||
# declare CDEF if we want to apply a factor
|
||||
if ($factor > 1) {
|
||||
print "$dpName.cdef $dpName,$factor,*\n";
|
||||
} elsif ($factor <= 0) {
|
||||
if (defined $_->{unitModifier}) {
|
||||
# sensor values have a unit modifier M attached to them so that REALVAL=VAL*10^M
|
||||
# y,x,LOG,*,EXP is x^y, just in case this is not obvious to the reader
|
||||
print "$dpName.cdef $dpName,",$_->{unitModifier},",10,LOG,*,EXP,*\n";
|
||||
}
|
||||
} elsif ($factor < 1) {
|
||||
print "$dpName.cdef $dpName,",1/$factor,",/\n";
|
||||
}
|
||||
} else {
|
||||
# just print value
|
||||
print "$dpName.value $_->{value}\n";
|
||||
}
|
||||
}
|
||||
}
|
264
plugins/virtualization/vmware/esxi
Executable file
264
plugins/virtualization/vmware/esxi
Executable file
|
@ -0,0 +1,264 @@
|
|||
#!/bin/bash
|
||||
|
||||
GREP="/bin/grep"
|
||||
SED="/bin/sed"
|
||||
TAIL="/usr/bin/tail"
|
||||
SSH="/usr/bin/ssh"
|
||||
BASENAME="/usr/bin/basename"
|
||||
|
||||
# script name must be like esx_cpu_machine.domain or esx_mem_machine.domain
|
||||
temp="$(basename $0 | $SED 's/^esx_//g')"
|
||||
which_info="${temp%%_*}"
|
||||
HOST="${temp##*_}"
|
||||
|
||||
case "$which_info" in
|
||||
"cpu" | "mem" | "hmem" | "gmem" ) ;;
|
||||
* ) echo "Script name incorrect, should be esx_xxx_hostname where xxx in {cpu,mem,hmem,gmem}"
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
# ---------------
|
||||
|
||||
function get_infos () {
|
||||
summary="$($SSH "$HOST" \
|
||||
vim-cmd hostsvc/hostsummary \; \
|
||||
vim-cmd vmsvc/getallvms)"
|
||||
}
|
||||
|
||||
function get_vmlist () {
|
||||
total_linenumber="$(echo "$summary" | wc -l)"
|
||||
|
||||
vmlist_linenumber="$(echo "$summary" | $GREP -n "^Vmid")"
|
||||
vmlist_linenumber="${vmlist_linenumber/:*/}"
|
||||
|
||||
vmlist="$(echo "$summary" | $TAIL -n $(($total_linenumber - $vmlist_linenumber)) | tr -s " ")"
|
||||
}
|
||||
|
||||
function overallCpuUsage () {
|
||||
cpu="$(echo "$1" | $GREP "overallCpuUsage")"
|
||||
cpu="${cpu/*overallCpuUsage = /}"
|
||||
cpu="${cpu/,*/}"
|
||||
}
|
||||
|
||||
function overallMemoryUsage () {
|
||||
mem="$(echo "$1" | $GREP "overallMemoryUsage")"
|
||||
mem="${mem/*overallMemoryUsage = /}"
|
||||
mem="${mem/,*/}"
|
||||
}
|
||||
|
||||
# ---------------
|
||||
|
||||
function get_vmsvcsummaries () {
|
||||
n=0
|
||||
cmd=""
|
||||
# echo "$vmlist" | \
|
||||
while read vmline ; do
|
||||
id[$n]="${vmline%% *}"
|
||||
temp="${vmline#${id[$n]} }"
|
||||
name[$n]="${temp%% *}"
|
||||
cmd="$cmd""vim-cmd vmsvc/get.summary ${id[$n]} \\\; "
|
||||
(( n++ ))
|
||||
done <<EOF
|
||||
$vmlist
|
||||
EOF
|
||||
|
||||
vmsummaries="$($SSH "$HOST" $cmd)"
|
||||
}
|
||||
|
||||
# ---------------
|
||||
|
||||
function VMoverallCpuUsage () {
|
||||
cpulist="$(echo "$1" | $GREP "overallCpuUsage")"
|
||||
n=0
|
||||
while read c ; do
|
||||
temp="${c/*overallCpuUsage = /}"
|
||||
vmcpu[$n]="${temp/,*/}"
|
||||
if [ "${vmcpu[$n]}" == "<unset>" ]; then
|
||||
vmcpu[$n]="0"
|
||||
fi
|
||||
(( n++ ))
|
||||
done <<EOF
|
||||
$cpulist
|
||||
EOF
|
||||
}
|
||||
|
||||
function VMoverallGuestMemUsage () {
|
||||
memlist="$(echo "$1" | $GREP "guestMemoryUsage")"
|
||||
n=0
|
||||
while read m ; do
|
||||
temp="${m/*guestMemoryUsage = /}"
|
||||
vmmem[$n]="${temp/,*/}"
|
||||
if [ "${vmmem[$n]}" == "<unset>" ]; then
|
||||
vmmem[$n]="0"
|
||||
fi
|
||||
(( n++ ))
|
||||
done <<EOF
|
||||
$memlist
|
||||
EOF
|
||||
}
|
||||
|
||||
function VMoverallHostMemUsage () {
|
||||
memlist="$(echo "$1" | $GREP "hostMemoryUsage")"
|
||||
n=0
|
||||
while read m ; do
|
||||
temp="${m/*hostMemoryUsage = /}"
|
||||
vmmem[$n]="${temp/,*/}"
|
||||
if [ "${vmmem[$n]}" == "<unset>" ]; then
|
||||
vmmem[$n]="0"
|
||||
fi
|
||||
(( n++ ))
|
||||
done <<EOF
|
||||
$memlist
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
# ---------------
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
get_infos
|
||||
if [ -n "$summary" ]; then
|
||||
echo yes
|
||||
exit 0
|
||||
else
|
||||
echo "Cannot connect to ESX server $HOST"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
get_infos
|
||||
if [ -z "$summary" ]; then
|
||||
echo "Cannot connect to ESX server $HOST"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$which_info" in
|
||||
"cpu" )
|
||||
echo 'graph_title ESXi Domain CPU Usage'
|
||||
echo 'graph_args -l 0'
|
||||
echo 'graph_scale no'
|
||||
echo 'graph_vlabel CPU usage in MHz'
|
||||
echo 'graph_category esx'
|
||||
echo 'graph_info This graph shows the average CPU MHz used by each domain'
|
||||
|
||||
name="Domain_0"
|
||||
echo "$name.label $name"
|
||||
echo "$name.type GAUGE"
|
||||
echo "$name.draw AREA"
|
||||
echo "$name.min 0"
|
||||
echo "$name.info CPU MHz used by $name"
|
||||
|
||||
|
||||
get_vmlist
|
||||
if [ -n "$vmlist" ]; then
|
||||
n=0
|
||||
cmd=""
|
||||
while read vmline ; do
|
||||
id="${vmline%% *}"
|
||||
temp="${vmline#$id }"
|
||||
name="${temp%% *}"
|
||||
|
||||
name=`echo $name | sed -e"s/[-\.]/_/g"`
|
||||
echo "$name.label $name"
|
||||
echo "$name.type GAUGE"
|
||||
echo "$name.draw STACK"
|
||||
echo "$name.min 0"
|
||||
echo "$name.info CPU MHz used by $name"
|
||||
|
||||
(( n++ ))
|
||||
done <<EOF
|
||||
$vmlist
|
||||
EOF
|
||||
fi;;
|
||||
"mem" | "hmem" | "gmem" )
|
||||
echo 'graph_title ESXi Domain '"$which_info"' Usage'
|
||||
echo 'graph_args -l 0'
|
||||
echo 'graph_scale no'
|
||||
echo 'graph_vlabel Memory usage in Megabytes'
|
||||
echo 'graph_category esx'
|
||||
echo 'graph_info This graph shows the average Memory used by each domain'
|
||||
|
||||
name="Domain_0"
|
||||
echo "$name.label $name"
|
||||
echo "$name.type GAUGE"
|
||||
echo "$name.draw AREA"
|
||||
echo "$name.min 0"
|
||||
echo "$name.info Memory usage for $name"
|
||||
|
||||
|
||||
get_vmlist
|
||||
if [ -n "$vmlist" ]; then
|
||||
n=0
|
||||
cmd=""
|
||||
while read vmline ; do
|
||||
id="${vmline%% *}"
|
||||
temp="${vmline#$id }"
|
||||
name="${temp%% *}"
|
||||
|
||||
name=`echo $name | sed -e"s/[-\.]/_/g"`
|
||||
echo "$name.label $name"
|
||||
echo "$name.type GAUGE"
|
||||
echo "$name.draw STACK"
|
||||
echo "$name.min 0"
|
||||
echo "$name.info Memory usage for $name"
|
||||
|
||||
(( n++ ))
|
||||
done <<EOF
|
||||
$vmlist
|
||||
EOF
|
||||
fi;;
|
||||
|
||||
esac
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ---------------
|
||||
# Get the informations
|
||||
|
||||
get_infos
|
||||
if [ -z "$summary" ]; then
|
||||
echo "Cannot connect to ESX server $HOST"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $which_info in
|
||||
"cpu" ) overallCpuUsage "$summary" ;;
|
||||
"mem" | "hmem" | "gmem" ) overallMemoryUsage "$summary" ;;
|
||||
esac
|
||||
|
||||
|
||||
get_vmlist
|
||||
if [ -n "$vmlist" ]; then
|
||||
|
||||
get_vmsvcsummaries
|
||||
|
||||
case $which_info in
|
||||
"cpu" ) VMoverallCpuUsage "$vmsummaries";;
|
||||
"mem" | "hmem" ) VMoverallHostMemUsage "$vmsummaries";;
|
||||
"gmem" ) VMoverallGuestMemUsage "$vmsummaries";;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# ---------------
|
||||
# Print information Munin style
|
||||
case $which_info in
|
||||
"cpu" ) echo "Domain_0.value ""$cpu";;
|
||||
"mem" | "gmem" | "hmem" ) echo "Domain_0.value ""$(($mem))";;
|
||||
esac
|
||||
|
||||
|
||||
if [ -n "$vmlist" ]; then
|
||||
n=0
|
||||
while [ -n "${id[$n]}" ]; do
|
||||
#echo ${id[$n]} ${name[$n]} ${vmcpu[$n]} ${vmmem[$n]}
|
||||
nicename=`echo ${name[$n]} | sed 's/[^a-z|A-Z|0-9]/\_/g'`
|
||||
case $which_info in
|
||||
"cpu" ) echo "$nicename".value "${vmcpu[$n]}";;
|
||||
"mem" | "gmem" | "hmem" ) echo "$nicename".value "$((${vmmem[$n]}))";;
|
||||
esac
|
||||
(( n++ ))
|
||||
done
|
||||
fi
|
47
plugins/virtualization/vmware/vm_cpu_load
Executable file
47
plugins/virtualization/vmware/vm_cpu_load
Executable file
|
@ -0,0 +1,47 @@
|
|||
#!/bin/bash
|
||||
|
||||
i=0
|
||||
VMX[0]='/var/lib/vmware/Virtual Machines/<VM Name>/Other Linux.vmx';
|
||||
VMX[1]='another VM';
|
||||
VMX[2]='and one more :)';
|
||||
VMX[3]='add as much as you like!';
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
echo yes
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
|
||||
echo 'graph_title VMware CPU-Load'
|
||||
echo 'graph_args --base 1000 -l 0'
|
||||
echo 'graph_vlabel Load of VMware VMs'
|
||||
echo 'graph_category VMware'
|
||||
|
||||
while [ $i -lt ${#VMX[*]} ]
|
||||
do
|
||||
|
||||
NAME=`vmware-cmd "${VMX[i]}" getconfig displayName |sed 's!getconfig(displayName) = !!' | sed 's! !!g' | sed 's!-!_!g'`
|
||||
echo $NAME.label $NAME
|
||||
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
i=0
|
||||
|
||||
while [ $i -lt ${#VMX[*]} ]
|
||||
do
|
||||
|
||||
PID=`vmware-cmd "${VMX[$i]}" getpid | sed 's!getpid() = !!'`
|
||||
NAME=`vmware-cmd "${VMX[i]}" getconfig displayName |sed 's!getconfig(displayName) = !!' | sed 's! !!g' | sed 's!-!_!g'`
|
||||
CPU=`ps -o %cpu -p $PID --no-header`
|
||||
|
||||
echo $NAME."value" $CPU
|
||||
|
||||
|
||||
i=`expr $i + 1`
|
||||
|
||||
done
|
||||
|
77
plugins/virtualization/vserver/vserver_jiffies
Executable file
77
plugins/virtualization/vserver/vserver_jiffies
Executable file
|
@ -0,0 +1,77 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Created by Jan Rękorajski <baggins@pld-linux.org> based on vserver_cpu_ plugin.
|
||||
#
|
||||
# Graph Vserver cumulative cpu usage stats
|
||||
#
|
||||
# Configuration variables
|
||||
# vservers - specify the vservers to include in the graph (default: all)
|
||||
#
|
||||
# NOTE: If no configuration variable is set, the default will be used
|
||||
#
|
||||
# see vserver_resources for example uses of configuration files
|
||||
|
||||
VSERVERS="$vservers"
|
||||
|
||||
INFO=(`sed 's/.*:\t//' /proc/virtual/info 2>/dev/null || echo '<none>'`)
|
||||
KCIN="$[ 16#${INFO[2]} ]";
|
||||
|
||||
# If this is 1, then VCI_SPACES is present in the kernel (new in 2.6.19)
|
||||
if [ $[ (KCIN >> 10) & 1 ] -eq 1 ]
|
||||
then
|
||||
NAMELOC="nsproxy"
|
||||
else
|
||||
NAMELOC="cvirt"
|
||||
fi
|
||||
|
||||
if [ -z "$VSERVERS" ] ; then
|
||||
XIDS=`find /proc/virtual/* -type d -exec basename {} \;`
|
||||
else
|
||||
# it's really more performant to specify vservers by ids or by linking but not in the configuration-file by name
|
||||
XIDS=""
|
||||
for i in $VSERVERS ; do
|
||||
if [ -d /proc/virtual/$i ] ; then
|
||||
XIDS="${XIDS}${i} "
|
||||
else
|
||||
for j in `find /proc/virtual/* -type d -exec basename {} \;` ; do
|
||||
if [ "$i" = "`cat /proc/virtual/$j/$NAMELOC |grep NodeName |cut -f2`" ] ; then
|
||||
XIDS="${XIDS}${j} "
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
echo 'graph_category vserver'
|
||||
echo 'graph_args --base 1000'
|
||||
echo 'graph_title Vserver cpu usage'
|
||||
echo 'graph_vlabel jiffies used per ${graph_period}'
|
||||
echo 'graph_info Shows jiffies used on each vserver.'
|
||||
|
||||
for i in $XIDS ; do
|
||||
LABEL=`grep NodeName /proc/virtual/$i/$NAMELOC | cut -f2`
|
||||
NAME=`echo $LABEL | tr '-' '_'`
|
||||
echo "${NAME}_hold.label on hold for cpu on $LABEL"
|
||||
echo "${NAME}_hold.info on hold for cpu on $LABEL."
|
||||
echo "${NAME}_hold.type COUNTER"
|
||||
echo "${NAME}_scpu.label system cpu usage for $LABEL"
|
||||
echo "${NAME}_scpu.info system cpu usage for $LABEL."
|
||||
echo "${NAME}_scpu.type COUNTER"
|
||||
echo "${NAME}_ucpu.label user cpu usage for $LABEL"
|
||||
echo "${NAME}_ucpu.info user cpu usage for $LABEL."
|
||||
echo "${NAME}_ucpu.type COUNTER"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for i in $XIDS ; do
|
||||
NAME=`grep NodeName /proc/virtual/$i/$NAMELOC | cut -f2 | tr '-' '_'`
|
||||
awk -v name=$NAME -v u=0 -v s=0 -v h=0 '
|
||||
/^cpu [0-9]+:/ { u+=$3; s+=$4; h+=$5}
|
||||
END {
|
||||
print name "_hold.value " h
|
||||
print name "_scpu.value " s
|
||||
print name "_ucpu.value " u
|
||||
}' /proc/virtual/$i/sched
|
||||
done
|
120
plugins/virtualization/vserver/vserver_limit_hits
Executable file
120
plugins/virtualization/vserver/vserver_limit_hits
Executable file
|
@ -0,0 +1,120 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2008 Chris Wilson
|
||||
# Copyright (C) 2006 Holger Levsen
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2 dated June,
|
||||
# 1991.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# Configuration variables
|
||||
# vservers - specify the vservers to include in the graph (default: all)
|
||||
# limits - if true, turn on limit graphing (default: false)
|
||||
#
|
||||
# NOTE: If no configuration variables are set, the defaults will be used
|
||||
|
||||
# Example /etc/munin/plugin-conf.d/munin-node
|
||||
#
|
||||
# The first group monitors the vservers named "vserver1 vserver2
|
||||
# vserver3 vserver4" and looks to see if the resource limit has been
|
||||
# breached, if so it sends a message to nagios via send_nsca, and
|
||||
# sends an email to notify that this has happened.
|
||||
#
|
||||
# The second monitors the vservers "vserver5 vserver6 vserver7" and
|
||||
# has no limit notifications turned on.
|
||||
#
|
||||
# The third monitors all vservers on the system, in one graph, and it has
|
||||
# no limit notifications defined.
|
||||
#
|
||||
# You can use any combination of these to fit your needs.
|
||||
#
|
||||
#
|
||||
# [vsrmem_group1]
|
||||
# user root
|
||||
# env.vservers vserver1 vserver2 vserver3 vserver4
|
||||
# env.limits 1
|
||||
# contacts nagios email
|
||||
# contact.nagios.command /usr/bin/send_nsca -H your.nagios-host.here -c /etc/send_nsca.cfg
|
||||
# contact.email.command mail -s "Munin-notification for ${var:group} :: ${var:host}" your@email.address.here
|
||||
#
|
||||
# [vsrmem_group2]
|
||||
# user root
|
||||
# env.vservers vserver5 vserver6 vserver7
|
||||
# env.limits 0
|
||||
#
|
||||
# [vserver_rmemory]
|
||||
# user root
|
||||
#
|
||||
# Graph Vserver RSS usage and limits
|
||||
#
|
||||
# Changelog
|
||||
# version 0.1 - 2006 April xx - Holger Levsen
|
||||
# - initial author
|
||||
# version 0.2 - 2006 April 24 - Micah Anderson <micah@riseup.net>
|
||||
# - Add dynamic arch page size determination
|
||||
# - Some cleanup and clarification
|
||||
# version 0.3 - 2006 May 3 - Micah Anderson <micah@riseup.net>
|
||||
# - Add ability to group vservers via environment vars
|
||||
# - Fix missing close quotes and standardize indents
|
||||
# - Add limit notification
|
||||
# - Update documentation to include info on groups and limits
|
||||
# version 0.4 - 2006 Jun 22 - Micah Anderson <micah@riseup.net>
|
||||
# - Fix error that results if NodeName is set to include a domain name
|
||||
# version 0.5 - 2008 Apr 12 - Chris Wilson <chris+munin@qwirx.com>
|
||||
# - Changed to display limit hits instead of resource usage
|
||||
# - Adapt to latest vserver kernel (lack of some variables in /proc/virtual)
|
||||
# Note that your vserver names may change if the contents of
|
||||
# /etc/vservers/* do not match the nodenames. Also you must specify
|
||||
# the vservers variable with context IDs (XIDs) rather than names.
|
||||
|
||||
scriptname=`basename $0`
|
||||
resource=`echo $scriptname | sed -e 's/.*_//'`
|
||||
vservers="$vservers"
|
||||
|
||||
if [ -z "$vservers" ]; then
|
||||
vservers=`ls -1 /proc/virtual | grep -v info | grep -v status`
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
echo "graph_title Vserver $resource limit hits"
|
||||
# echo 'graph_args --base 1024k -l 0'
|
||||
echo "graph_vlabel $resource limit hits"
|
||||
echo 'graph_category vserver'
|
||||
echo "graph_info Shows number of hits on $resource limits by each vserver.'"
|
||||
|
||||
for vserver_xid in $vservers ; do
|
||||
longname=`/usr/sbin/vuname --xid $vserver_xid NODENAME | cut -f2`
|
||||
name=`echo $longname | cut -d. -f1`
|
||||
echo "$vserver_xid.label $name"
|
||||
echo "$vserver_xid.info $resource limit hits by $longname"
|
||||
echo "$vserver_xid.critical 1"
|
||||
echo "$vserver_xid.min 0"
|
||||
echo "$vserver_xid.type DERIVE"
|
||||
done
|
||||
|
||||
exit 0
|
||||
elif [ "$1" = "suggest" ]; then
|
||||
if [ -z "$vservers" ]; then
|
||||
echo "No vservers running, cannot suggest!" >&2
|
||||
exit 2
|
||||
fi
|
||||
vserver1=`echo $vservers | sed -e 's/ .*//'`
|
||||
tail -n +2 /proc/virtual/$vserver1/limit | sed -e 's/:.*//'
|
||||
else
|
||||
for vserver_xid in $vservers; do
|
||||
cat /proc/virtual/$vserver_xid/limit \
|
||||
| awk -v xid="$vserver_xid" -v res="$resource:" \
|
||||
'{ if ( $1 == res )
|
||||
printf "%s.value %d\n", xid, $7 }'
|
||||
done
|
||||
fi
|
96
plugins/virtualization/vserver/vserver_limits
Executable file
96
plugins/virtualization/vserver/vserver_limits
Executable file
|
@ -0,0 +1,96 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2008 Chris Wilson
|
||||
# Copyright (C) 2006 Holger Levsen
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2 dated June,
|
||||
# 1991.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# Configuration variables
|
||||
# vservers - specify the vservers to include in the graph (default: all)
|
||||
# limits - if true, turn on limit graphing (default: false)
|
||||
#
|
||||
# NOTE: If no configuration variables are set, the defaults will be used
|
||||
|
||||
# Example /etc/munin/plugin-conf.d/munin-node
|
||||
#
|
||||
# [vserver_limits_RSS]
|
||||
# user root
|
||||
# env.vservers 7 18 20 42
|
||||
#
|
||||
# Graph Vserver resource limits. Useful to help you know when and how often
|
||||
# you changed the limits of each vserver, e.g. because customer needed more
|
||||
# RAM.
|
||||
#
|
||||
# Changelog
|
||||
# version 0.1 - 2006 April xx - Holger Levsen
|
||||
# - initial author
|
||||
# version 0.2 - 2006 April 24 - Micah Anderson <micah@riseup.net>
|
||||
# - Add dynamic arch page size determination
|
||||
# - Some cleanup and clarification
|
||||
# version 0.3 - 2006 May 3 - Micah Anderson <micah@riseup.net>
|
||||
# - Add ability to group vservers via environment vars
|
||||
# - Fix missing close quotes and standardize indents
|
||||
# - Add limit notification
|
||||
# - Update documentation to include info on groups and limits
|
||||
# version 0.4 - 2006 Jun 22 - Micah Anderson <micah@riseup.net>
|
||||
# - Fix error that results if NodeName is set to include a domain name
|
||||
# version 0.5 - 2008 Apr 12 - Chris Wilson <chris+munin@qwirx.com>
|
||||
# - Changed to display limits instead of resource usage
|
||||
# - Adapt to latest vserver kernel (lack of some variables in /proc/virtual)
|
||||
# Note that your vserver names may change if the contents of
|
||||
# /etc/vservers/* do not match the nodenames. Also you must specify
|
||||
# the vservers variable with context IDs (XIDs) rather than names.
|
||||
|
||||
|
||||
scriptname=`basename $0`
|
||||
resource=`echo $scriptname | sed -e 's/.*_//'`
|
||||
vservers="$vservers"
|
||||
|
||||
if [ -z "$vservers" ]; then
|
||||
vservers=`ls -1 /proc/virtual | grep -v info | grep -v status`
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
echo "graph_title Vserver $resource limits"
|
||||
# echo 'graph_args --base 1024k -l 0'
|
||||
echo "graph_vlabel $resource limits"
|
||||
echo 'graph_category vserver'
|
||||
echo "graph_info Shows current $resource limits for each vserver.'"
|
||||
|
||||
for vserver_xid in $vservers ; do
|
||||
longname=`/usr/sbin/vuname --xid $vserver_xid NODENAME | cut -f2`
|
||||
name=`echo $longname | cut -d. -f1`
|
||||
echo "$vserver_xid.label $name"
|
||||
echo "$vserver_xid.info $resource limits for $longname"
|
||||
echo "$vserver_xid.min 0"
|
||||
echo "$vserver_xid.type GAUGE"
|
||||
done
|
||||
|
||||
exit 0
|
||||
elif [ "$1" = "suggest" ]; then
|
||||
if [ -z "$vservers" ]; then
|
||||
echo "No vservers running, cannot suggest!" >&2
|
||||
exit 2
|
||||
fi
|
||||
vserver1=`echo $vservers | sed -e 's/ .*//'`
|
||||
tail -n +2 /proc/virtual/$vserver1/limit | sed -e 's/:.*//'
|
||||
else
|
||||
for vserver_xid in $vservers; do
|
||||
cat /proc/virtual/$vserver_xid/limit \
|
||||
| awk -v xid="$vserver_xid" -v res="$resource:" \
|
||||
'{ if ( $1 == res )
|
||||
printf "%s.value %d\n", xid, $6 }'
|
||||
done
|
||||
fi
|
77
plugins/virtualization/xen
Executable file
77
plugins/virtualization/xen
Executable file
|
@ -0,0 +1,77 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Script to monitor CPU usage of Xen domains
|
||||
#
|
||||
# Author: unknown
|
||||
# Modifications: Matthias Pfafferodt, syntron@web.de, Roland Mohrbacher
|
||||
# License: GPL v. 2
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# conifg (required)
|
||||
# autoconf (optional - used by munin-config)
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
# statefile: name of seen xen domains
|
||||
statefile="/var/lib/munin/plugin-state/munin-plugin-xen.state"
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
if which xm > /dev/null ; then
|
||||
echo yes
|
||||
exit 0
|
||||
fi
|
||||
echo "no (xm not found)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
|
||||
if [ ! -e $statefile ]; then
|
||||
touch $statefile
|
||||
fi
|
||||
|
||||
echo 'graph_title Xen Domain Utilerisation'
|
||||
echo 'graph_args --base 1000 -l 0 --upper-limit 100 --rigid'
|
||||
echo 'graph_scale no'
|
||||
echo 'graph_vlabel %'
|
||||
echo 'graph_category xen'
|
||||
echo 'graph_info This graph shows how many % of the CPU time where used by a domain'
|
||||
|
||||
xm list | grep -v "^Name .* Time(s)$" | \
|
||||
while read name domid mem cpu state time console; do
|
||||
name=`echo $name | sed -e"s/[-.]/_/g"`
|
||||
TEST=`less $statefile | grep "^${name}$" | wc -l`
|
||||
if [ $TEST -ne 1 ]; then
|
||||
echo "$name" >> $statefile
|
||||
fi
|
||||
done
|
||||
|
||||
FIRST=1
|
||||
cat $statefile | sort | \
|
||||
while read name; do
|
||||
echo "$name.label $name"
|
||||
echo "$name.type COUNTER"
|
||||
if [ $FIRST -eq 1 ]; then
|
||||
echo "$name.draw AREA"
|
||||
FIRST=0
|
||||
else
|
||||
echo "$name.draw STACK"
|
||||
fi
|
||||
echo "$name.min 0"
|
||||
echo "$name.max 100"
|
||||
echo "$name.info % of the CPU time spend for $name"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
xm list | grep -v "^Name .* Time(s)$" | \
|
||||
while read name domid mem cpu state time console; do
|
||||
name=`echo $name | sed -e "s/[-.]/_/g"`
|
||||
# only seconds
|
||||
time=`echo $time | sed -e "s/\..//"`
|
||||
# scale 60s/60s => 100%/60s
|
||||
time=`echo "$time*100/60" | bc`
|
||||
echo "$name.value $time"
|
||||
done
|
129
plugins/virtualization/xen-cpu
Executable file
129
plugins/virtualization/xen-cpu
Executable file
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/perl -wT
|
||||
#
|
||||
# Script to minitor the cpu usage of Xen domains
|
||||
#
|
||||
# Author: Adam Crews <doo <at> shroom <dot> com>
|
||||
#
|
||||
# License: GPL
|
||||
# Based on the origional xen script from Matthias Pfafferodt, syntron at web.de
|
||||
#
|
||||
# Note: Your munin config must run this as root.
|
||||
#
|
||||
# Parameters
|
||||
# config (required)
|
||||
# autoconf (optional - used by munin-config)
|
||||
#
|
||||
# Changelog:
|
||||
# Properly ignore the xentop output header line.
|
||||
# Ward Vandewege (ward@gnu.org), 2011-04-20
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
# Define where to find xm tools
|
||||
my $XM = '/usr/sbin/xm';
|
||||
my $XMTOP = '/usr/sbin/xentop';
|
||||
|
||||
##############
|
||||
# You should not need to edit anything below here
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
$ENV{PATH} = '/bin:/usr/bin:/usr/sbin';
|
||||
|
||||
my $arg; undef($arg);
|
||||
if (defined($ARGV[0])) {
|
||||
$arg = 'config' if ($ARGV[0] eq 'config');
|
||||
$arg = 'autoconf' if ($ARGV[0] eq 'autoconf');
|
||||
|
||||
if ( "$arg" eq 'autoconf') {
|
||||
if ( -e $XM && -e $XMTOP ) {
|
||||
print "yes\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "no ($XM and/or $XMTOP not found\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( "$arg" eq 'config') {
|
||||
my %cnf; undef(%cnf);
|
||||
%cnf = (
|
||||
'graph_title' => 'Xen Domain CPU Usage',
|
||||
'graph_args' => '--base 1000 -l 0 --upper-limit 100 --rigid',
|
||||
'graph_vlabel' => 'Percent (%)',
|
||||
'graph_category' => 'xen',
|
||||
'graph_info' => 'Display the % of CPU Usage for each domain',
|
||||
);
|
||||
|
||||
my @domains = `$XM list`;
|
||||
shift(@domains); # we dont need the header line
|
||||
my $cnt = "0";
|
||||
foreach my $domain ( @domains ) {
|
||||
my ($dom,undef) = split(/\s/, $domain, 2);
|
||||
# we need to change - and . to _ or things get weird with the graphs
|
||||
# some decent quoting would probably fix this, but this works for now
|
||||
$dom =~ s/[-.]/_/g;
|
||||
|
||||
$cnf{ "$dom" . '.label' } = "$dom";
|
||||
$cnf{ "$dom" . '.draw' } = 'STACK';
|
||||
$cnf{ "$dom" . '.min' } = '0';
|
||||
$cnf{ "$dom" . '.max' } = '100';
|
||||
$cnf{ "$dom" . '.info' } = '% CPU used for ' . "$dom";
|
||||
|
||||
if ( "$cnt" == "0") { $cnf{$dom.'.draw'} = 'AREA'; }
|
||||
$cnt++;
|
||||
}
|
||||
|
||||
foreach my $key (sort(keys(%cnf))) {
|
||||
print "$key $cnf{$key}\n";
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Nothing was passed as an argument, so let's just return the proper values
|
||||
|
||||
my @chunks; undef(@chunks);
|
||||
|
||||
{
|
||||
# run the xentop command a few times because the first reading is not always accurate
|
||||
local $/ = undef;
|
||||
@chunks = split(/^xentop - .*$/m, `$XMTOP -b -i2 -d2`);
|
||||
}
|
||||
|
||||
# Take only the last run of xentop
|
||||
my @stats = split (/\n/,pop(@chunks));
|
||||
|
||||
# remove the first 4 items that are junk that we don't need.
|
||||
shift(@stats);
|
||||
shift(@stats);
|
||||
shift(@stats);
|
||||
shift(@stats);
|
||||
|
||||
my %vals; undef(%vals);
|
||||
|
||||
foreach my $domain (@stats) {
|
||||
# trim the leading whitespace
|
||||
$domain =~ s/^\s+//;
|
||||
my @v_tmp = split(/\s+/, $domain);
|
||||
next if ($v_tmp[0] eq 'NAME');
|
||||
|
||||
# we need to change - and . to _ or things get weird with the graphs
|
||||
# some decent quoting would probably fix this, but this works for now
|
||||
$v_tmp[0] =~ s/[-.]/_/g;
|
||||
|
||||
$vals{$v_tmp[0]}{'cpu_percent'} = $v_tmp[3];
|
||||
$vals{$v_tmp[0]}{'vcpu'} = $v_tmp[8];
|
||||
if ( $vals{$v_tmp[0]}{'vcpu'} =~ m/n\/a/ ) {
|
||||
my $cpu = `grep -c "processor" < /proc/cpuinfo`;
|
||||
if ( $cpu =~ m/^(\d+)$/ ) {
|
||||
$vals{$v_tmp[0]}{'vcpu'} = $1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $key (sort(keys(%vals))) {
|
||||
print "$key.value " . ($vals{$key}{'cpu_percent'}/$vals{'Domain_0'}{'vcpu'}), "\n";
|
||||
}
|
242
plugins/virtualization/xen-multi
Executable file
242
plugins/virtualization/xen-multi
Executable file
|
@ -0,0 +1,242 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
# -*- perl -*-
|
||||
|
||||
=head1 NAME
|
||||
|
||||
xen_multi - Munin multigraph plugin to monitor Xen domains activity
|
||||
|
||||
=head1 APPLICABLE SYSTEMS
|
||||
|
||||
This plugin should work on any system running a Xen hypervisor and where xentop
|
||||
is installed. It also needs Munin 1.4.0 or higher, since it uses AREASTACK
|
||||
(available from 1.3.3) and multigraph (available from 1.4.0).
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
xentop requires superuser privileges, so you need to include in your
|
||||
configuration:
|
||||
|
||||
[xen-multi]
|
||||
user root
|
||||
|
||||
Then restart munin-node and you're done.
|
||||
|
||||
=head1 INTERPRETATION
|
||||
|
||||
This plugin produces four different graphs: CPU usage, memory usage, disk IOs
|
||||
and network traffic.
|
||||
|
||||
In each graph, all Xen domains (including dom0) have their data stacked, giving
|
||||
an overall amount of ressources used.
|
||||
|
||||
NOTE: xentop always reports 0 for dom0's disk IOs and network traffic, but
|
||||
both graphs show its entry all the same, so each domain can keep its own color
|
||||
along the different graphs.
|
||||
|
||||
=head2 CPU usage
|
||||
|
||||
This graph shows a percentage of the CPU time used by each domain.
|
||||
|
||||
=head2 Memory usage
|
||||
|
||||
This graph shows the amount of memory (in bytes) used by each domain.
|
||||
|
||||
=head2 Disk IOs
|
||||
|
||||
This graph shows the number of disk read and write operations for each domain.
|
||||
|
||||
=head2 Network traffic
|
||||
|
||||
This graph shows the amount of bits received and transmitted for each domain.
|
||||
|
||||
=head1 ACKNOWLEDGEMENTS
|
||||
|
||||
Michael Renner for the C<diskstats> plugin which I borrowed some code from.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
0.90
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Raphael HALIMI <raphael.halimi@gmail.com>
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Munin::Plugin;
|
||||
|
||||
# autoconf - quite simple
|
||||
if ($ARGV[0] eq "autoconf") {
|
||||
if (`which xentop`) {
|
||||
print "yes\n";
|
||||
} else {
|
||||
print "no (xentop not found)\n";
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Common steps for both "config" and a normal run
|
||||
#
|
||||
|
||||
#
|
||||
# trim_label
|
||||
#
|
||||
# Trims a given label to it's non-wrapping size
|
||||
# $type = 'pos' for normal graphs and 'neg' for mirror graphs
|
||||
# pos: nnn.nnU_ times 4
|
||||
# neg: nnn.nnU/nnn.nnU_ times 4
|
||||
|
||||
sub trim_label {
|
||||
my ($type, $label) = @_; my $data_characters;
|
||||
my ($graph_width, $graph_border_width, $padding_characters, $pixels_per_character) = (400,97,10,6);
|
||||
if ($type eq 'pos') {$data_characters = 32;} elsif ($type eq 'neg') {$data_characters = 64;} else {return $label;}
|
||||
|
||||
my $available_characters = abs(($graph_width+$graph_border_width)/$pixels_per_character)-$padding_characters-$data_characters;
|
||||
|
||||
# If the label is longer than the available space, we write as many
|
||||
# characters as we can on both left and right, and two dots in the middle
|
||||
if ( $available_characters < length $label ) {
|
||||
my $center = ($available_characters-2)/2;
|
||||
$label = substr($label,0,($center)) . '..' . substr($label,-$center);
|
||||
}
|
||||
|
||||
return $label;
|
||||
}
|
||||
|
||||
# Global variables
|
||||
my (%domains,$domain,$munindomain,$cpusecs,$memk,$nettxk,$netrxk,$vbdrd,$vbdwr);
|
||||
|
||||
open (XENTOP,"xentop -b -f -i1 |") or die "Could not execute xentop, $!";
|
||||
|
||||
# Now we build a hash of hashes to store information
|
||||
while (<XENTOP>) {
|
||||
# Some cleaning first
|
||||
s/^\s+//; chomp;
|
||||
# Skip the headers
|
||||
next if /^NAME/;
|
||||
|
||||
# We define only what we need
|
||||
($domain,undef,$cpusecs,undef,$memk,undef,undef,undef,undef,undef,$nettxk,$netrxk,undef,undef,$vbdrd,$vbdwr,undef,undef,undef) = split(/\s+/);
|
||||
|
||||
# We have to store the sanitised domain name in a separate variable
|
||||
$domains{$domain}{'munindomain'} = clean_fieldname($domain);
|
||||
|
||||
# We need the remaining data only for a normal run
|
||||
if ($ARGV[0] eq "") {
|
||||
$domains{$domain}{'cpusecs'} = $cpusecs;
|
||||
$domains{$domain}{'mem'} = $memk;
|
||||
$domains{$domain}{'nettx'} = $nettxk;
|
||||
$domains{$domain}{'netrx'} = $netrxk;
|
||||
$domains{$domain}{'vbdrd'} = $vbdrd;
|
||||
$domains{$domain}{'vbdwr'} = $vbdwr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# config - quite simple, too
|
||||
#
|
||||
|
||||
if ($ARGV[0] eq "config") {
|
||||
print "multigraph xen_cpu_time\n";
|
||||
print "graph_title Xen domains CPU time\n";
|
||||
print "graph_args --base 1000 -l 0\n";
|
||||
print "graph_vlabel %\n";
|
||||
print "graph_scale no\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows CPU time for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.label ".trim_label('pos',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.cdef $domains{$domain}{'munindomain'}_cpu_time,100,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.draw AREASTACK\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_mem\n";
|
||||
print "graph_title Xen domains memory usage\n";
|
||||
print "graph_args --base 1024 -l 0\n";
|
||||
print "graph_vlabel bytes\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows memory usage for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_mem.label ".trim_label('pos',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_mem.cdef $domains{$domain}{'munindomain'}_mem,1024,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_mem.draw AREASTACK\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_net\n";
|
||||
print "graph_title Xen domains network traffic\n";
|
||||
print "graph_args --base 1000\n";
|
||||
print "graph_vlabel bits per \${graph_period} in (-) / out (+)\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows network traffic for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_netrx.label none\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.cdef $domains{$domain}{'munindomain'}_netrx,8192,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.graph no\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.label ".trim_label('neg',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.cdef $domains{$domain}{'munindomain'}_nettx,8192,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.draw AREASTACK\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.negative $domains{$domain}{'munindomain'}_netrx\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_disk\n";
|
||||
print "graph_title Xen domains disk IOs\n";
|
||||
print "graph_args --base 1000\n";
|
||||
print "graph_vlabel IOs per \${graph_period} read (-) / write (+)\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows disk IOs for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.label none\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.graph no\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.label ".trim_label('neg',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.draw AREASTACK\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.negative $domains{$domain}{'munindomain'}_vbdrd\n";
|
||||
}
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Normal run
|
||||
#
|
||||
|
||||
print "multigraph xen_cpu_time\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.value $domains{$domain}{'cpusecs'}\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_mem\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_mem.value $domains{$domain}{'mem'}\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_net\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_nettx.value $domains{$domain}{'nettx'}\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.value $domains{$domain}{'netrx'}\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_disk\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.value $domains{$domain}{'vbdrd'}\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.value $domains{$domain}{'vbdwr'}\n";
|
||||
}
|
189
plugins/virtualization/xen_cpu_v2
Executable file
189
plugins/virtualization/xen_cpu_v2
Executable file
|
@ -0,0 +1,189 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# xen_cpu_v2.pl 1.00
|
||||
# Script to minitor the CPU usage of Xen domains
|
||||
# Zoltan HERPAI (c) 2009, wigyori@uid0.hu
|
||||
#
|
||||
# Based loosely on Adam Crews' xen_cpu script
|
||||
#
|
||||
# This script tries to measure the CPU usage of the Xen guests
|
||||
# accurately.
|
||||
# The problem with the current monitoring script is that these
|
||||
# scripts use the CPU output of xentop or xm list, which might be
|
||||
# inaccurate due to the resources used up at the time of the query by
|
||||
# the xm or xentop command.
|
||||
#
|
||||
# This script stores the previous value of the CPU sec value of the given
|
||||
# guests in a tempfile, then does some simple calculations to get the real
|
||||
# CPU usage percentage of the guests.
|
||||
#
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
use strict;
|
||||
use POSIX;
|
||||
|
||||
# Define where to find xm tools
|
||||
my $XM = '/usr/sbin/xm';
|
||||
my $XMTOP = '/usr/sbin/xentop';
|
||||
my $curtime = time();
|
||||
my $basename = `/usr/bin/basename $0`; chop ($basename);
|
||||
my $TEMPFILE = "/tmp/$basename";
|
||||
|
||||
my $debug = 0;
|
||||
|
||||
##############
|
||||
# You should not need to edit anything below here
|
||||
#
|
||||
|
||||
$ENV{PATH} = '/bin:/usr/bin:/usr/sbin';
|
||||
|
||||
my $arg;
|
||||
if ( defined($ARGV[0]) )
|
||||
{
|
||||
if ( $ARGV[0] eq 'config' )
|
||||
{
|
||||
$arg = 'config';
|
||||
}
|
||||
if ( $ARGV[0] eq 'autoconf' )
|
||||
{
|
||||
$arg = 'autoconf';
|
||||
}
|
||||
|
||||
if ( $arg eq 'autoconf')
|
||||
{
|
||||
if ( -e $XM && -e $XMTOP )
|
||||
{
|
||||
print "yes\n";
|
||||
exit 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
print "no ($XM and/or $XMTOP not found\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $arg eq 'config' )
|
||||
{
|
||||
my %cnf;
|
||||
%cnf = (
|
||||
'graph_title' => 'Xen Domain CPU Usage v2',
|
||||
'graph_args' => '--base 1000 -l 0 --upper-limit 100 --rigid',
|
||||
'graph_vlabel' => 'Percent (%)',
|
||||
'graph_category' => 'xen',
|
||||
'graph_info' => 'Display the % of CPU Usage for each domain',
|
||||
);
|
||||
|
||||
my @domains = `$XM list`;
|
||||
my $cnt = 0;
|
||||
shift(@domains); # we dont need the header line
|
||||
foreach my $domain ( @domains )
|
||||
{
|
||||
my ($dom,undef) = split(/\s/, $domain, 2);
|
||||
$dom =~ s/[-.]/_/g;
|
||||
$cnf{ "$dom" . '.label' } = "$dom";
|
||||
$cnf{ "$dom" . '.draw' } = 'STACK';
|
||||
$cnf{ "$dom" . '.min' } = '0';
|
||||
$cnf{ "$dom" . '.max' } = '100';
|
||||
$cnf{ "$dom" . '.info' } = '% CPU used for ' . "$dom";
|
||||
# $cnf{ "$dom" . '.draw' } = 'AREA';
|
||||
if ( $cnt == 0 )
|
||||
{
|
||||
$cnf{ "$dom" . '.draw' } = 'AREA';
|
||||
}
|
||||
$cnt++;
|
||||
}
|
||||
foreach my $key (sort(keys(%cnf)))
|
||||
{
|
||||
print "$key $cnf{$key}\n";
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
my @xmlist = `$XM list`;
|
||||
shift (@xmlist);
|
||||
|
||||
my %dom; my $name; my $oldtime;
|
||||
# Read old data
|
||||
if ( -e $TEMPFILE )
|
||||
{
|
||||
open(FH, "<", $TEMPFILE) or die $!;
|
||||
$oldtime = <FH>;
|
||||
|
||||
if ( $debug )
|
||||
{
|
||||
print "Oldtime: $oldtime\n";
|
||||
}
|
||||
|
||||
while (<FH>)
|
||||
{
|
||||
# Get the guest name and its CPU usage, and store it in $dom
|
||||
$_ =~ /(\S+)\s+\S+\s+\S+\s+\d+\s+\S+\s+(\S+)/;
|
||||
$dom{$1}->{'oldtime'} = $2;
|
||||
}
|
||||
|
||||
close FH;
|
||||
}
|
||||
|
||||
my $diff; my $cpusum = 0;
|
||||
foreach my $domain ( @xmlist )
|
||||
{
|
||||
# Get the domains' name and current CPU usage, store it in $dom
|
||||
$domain =~ /(\S+)\s+\S+\s+\S+\s+\d+\s+\S+\s+(\S+)/;
|
||||
$dom{$1}->{'newtime'} = $2;
|
||||
|
||||
$diff = $dom{$1}->{'newtime'} - $dom{$1}->{'oldtime'};
|
||||
$diff = sprintf("%.2f", $diff);
|
||||
|
||||
# Calc the diff between old and new cputime, or reset the counter
|
||||
if ( $diff < 0 )
|
||||
{
|
||||
$diff = $dom{$1}->{'newtime'};
|
||||
}
|
||||
$dom{$1}->{'diff'} = $diff;
|
||||
|
||||
# Calc a sum CPU usage
|
||||
$cpusum = $cpusum + $diff;
|
||||
}
|
||||
|
||||
my $numcpus = `$XM info |grep nr_cpus |cut -d \: -f 2`;
|
||||
my $timediff = $curtime - $oldtime;
|
||||
my $tcpuavail = $numcpus * $timediff;
|
||||
|
||||
if ( $debug )
|
||||
{
|
||||
print "UsedCPUtime sum: $cpusum\n";
|
||||
print "CPUs: $numcpus\n";
|
||||
print "Timediff: $timediff\n";
|
||||
print "Total CPU time available: $tcpuavail\n";
|
||||
}
|
||||
|
||||
my $key; my $value;
|
||||
while (($key, $value) = each %dom)
|
||||
{
|
||||
# Calc a percentage based on the used CPU time sum
|
||||
my $tmp = 0;
|
||||
$tmp = ( $dom{$key}->{'diff'} / $cpusum ) * 100;
|
||||
$dom{$key}->{'pc_time'} = sprintf("%.2f", $tmp);
|
||||
|
||||
# Calc a percentage based on the _total_ available CPU time
|
||||
$tmp = 0;
|
||||
$tmp = ( $dom{$key}->{'diff'} / $tcpuavail ) * 100;
|
||||
$dom{$key}->{'pc_tcpu'} = sprintf("%.2f", $tmp);
|
||||
|
||||
if ( $debug )
|
||||
{
|
||||
print "$key newtime: ".$dom{$key}->{'newtime'}.", oldtime: ".$dom{$key}->{'oldtime'}.", diff: ".$dom{$key}->{'diff'}.", pc_bytime ".$dom{$key}->{'pc_time'}.", pc_bytcpu ".$dom{$key}->{'pc_tcpu'}."\n";
|
||||
}
|
||||
print "$key.value ".$dom{$key}->{'pc_tcpu'}."\n";
|
||||
}
|
||||
|
||||
# We'll need to log out the current "xm list" output, and the current time also.
|
||||
open(FH, ">", $TEMPFILE) or die $!;
|
||||
print FH $curtime."\n";
|
||||
print FH @xmlist;
|
||||
close FH;
|
||||
|
67
plugins/virtualization/xen_memory
Executable file
67
plugins/virtualization/xen_memory
Executable file
|
@ -0,0 +1,67 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Script to monitor memory status of the xen host
|
||||
#
|
||||
# Written by immerda project (admin(_at_)immerda.ch)
|
||||
# 2007
|
||||
# License: GPL
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# config (required)
|
||||
# autoconf (optional - used by munin-config)
|
||||
#
|
||||
|
||||
XM='/usr/sbin/xm'
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
if [ -e $XM ]; then
|
||||
echo yes
|
||||
exit 0
|
||||
fi
|
||||
echo "no (xm not found)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
|
||||
echo 'graph_title Xen Memory'
|
||||
echo 'graph_args --base 1000 -l 0'
|
||||
echo 'graph_scale no'
|
||||
echo 'graph_vlabel MB'
|
||||
echo 'graph_category xen'
|
||||
echo 'graph_info This graph shows of many mS wall time where used by a domain'
|
||||
# xm info | while read name bla value; do echo "$name $value"; done
|
||||
$XM info | while read name bla value; do
|
||||
#total_memory 2047
|
||||
#free_memory 1476
|
||||
name=`echo $name | sed -e"s/-/_/"`
|
||||
|
||||
if [ "$name" = "total_memory" ]; then
|
||||
echo "$name.label $name"
|
||||
echo "$name.type GAUGE"
|
||||
echo "$name.min 0"
|
||||
echo "$name.info total memory"
|
||||
fi
|
||||
if [ "$name" = "free_memory" ]; then
|
||||
echo "$name.label $name"
|
||||
echo "$name.type GAUGE"
|
||||
echo "$name.draw AREA"
|
||||
# echo "$name.draw STACK"
|
||||
echo "$name.min 0"
|
||||
echo "$name.info free memory"
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
$XM info | while read name bla value; do
|
||||
name=`echo $name | sed -e"s/-/_/"`
|
||||
if [ "$name" = "total_memory" ]; then
|
||||
echo "$name.value $value"
|
||||
fi
|
||||
if [ "$name" = "free_memory" ]; then
|
||||
echo "$name.value $value"
|
||||
fi
|
||||
done
|
||||
|
59
plugins/virtualization/xen_traffic_
Executable file
59
plugins/virtualization/xen_traffic_
Executable file
|
@ -0,0 +1,59 @@
|
|||
#!/bin/sh
|
||||
# Author: mario manno <projects@manno.name>
|
||||
# Description: measure traffic for one xen host
|
||||
# Get xen host name from symlink
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
|
||||
DOMAIN=$( basename $0 | sed 's/^xen_traffic_//g' )
|
||||
NAME=$( echo $DOMAIN | sed -e's/-/_/g' )
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
if which xm > /dev/null ; then
|
||||
echo yes
|
||||
else
|
||||
echo "no (xm not found)"
|
||||
exit 1
|
||||
fi
|
||||
if [ -r /proc/net/dev ]; then
|
||||
echo yes
|
||||
else
|
||||
echo "no (/proc/net/dev not found)"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "suggest" ]; then
|
||||
xm list | awk '{print $1}' | egrep -v "^(Name|Domain-0)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
echo "graph_title Xen Traffic for $NAME"
|
||||
echo 'graph_vlabel bits in (-) / out (+) per ${graph_period}'
|
||||
echo 'graph_args --base 1024 -l 0'
|
||||
echo 'graph_category xen'
|
||||
echo 'out.label sent'
|
||||
echo 'out.type DERIVE'
|
||||
echo 'out.min 0'
|
||||
echo 'out.cdef out,8,*'
|
||||
echo 'in.label received'
|
||||
echo 'in.type DERIVE'
|
||||
echo 'in.min 0'
|
||||
echo 'in.cdef in,8,*'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
dev=$( xm network-list $DOMAIN | egrep "^[0-9]+" | sed 's@^.*vif/\([0-9]*\)/\([0-9]*\).*$@vif\1.\2@')
|
||||
|
||||
awk -v interface="$dev" \
|
||||
'BEGIN { gsub(/\./, "\\.", interface) } \
|
||||
$1 ~ "^" interface ":" {
|
||||
split($0, a, /: */); $0 = a[2]; \
|
||||
print "in.value " $1 "\nout.value " $9 \
|
||||
}' \
|
||||
/proc/net/dev
|
||||
|
70
plugins/virtualization/xen_traffic_all
Executable file
70
plugins/virtualization/xen_traffic_all
Executable file
|
@ -0,0 +1,70 @@
|
|||
#!/bin/sh
|
||||
# Author: mario manno <projects@manno.name>
|
||||
# Description: measure traffic for all xen hosts
|
||||
#
|
||||
# Changelog:
|
||||
# Also handle domUs with named network interfaces.
|
||||
# Ward Vandewege (ward@gnu.org), 2011-04-20
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
if which xm > /dev/null ; then
|
||||
echo yes
|
||||
else
|
||||
echo "no (xm not found)"
|
||||
exit 1
|
||||
fi
|
||||
if [ -r /proc/net/dev ]; then
|
||||
echo yes
|
||||
else
|
||||
echo "no (/proc/net/dev not found)"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
echo 'graph_title Xen Traffic'
|
||||
echo 'graph_vlabel bits received (-) / sent (+) per ${graph_period}'
|
||||
echo 'graph_args --base 1024 -l 0'
|
||||
echo 'graph_category xen'
|
||||
DOMAINS=$(xm list | awk '{print $1}' | egrep -v "^(Name|Domain-0)")
|
||||
for dom in $DOMAINS; do
|
||||
name=$( echo $dom | tr .- __ )
|
||||
#echo $name"UP.label $name"
|
||||
#echo $name"DOWN.label $name"
|
||||
|
||||
echo $name'Down.label received'
|
||||
echo $name'Down.type COUNTER'
|
||||
echo $name'Down.graph no'
|
||||
echo "${name}Down.cdef ${name}Down,8,*"
|
||||
echo "${name}Up.label ${name}"
|
||||
echo $name'Up.type COUNTER'
|
||||
echo "${name}Up.negative ${name}Down"
|
||||
echo "${name}Up.cdef ${name}Up,8,*"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DOMAINS=$(xm list | awk '{print $1}' | egrep -v "^(Name|Domain-0)")
|
||||
for dom in $DOMAINS; do
|
||||
dev=$( xm list $dom --long | awk '/vifname / { print $2 }' | sed 's/)//' )
|
||||
if [ "$dev" == "" ]; then
|
||||
dev=$( xm network-list $dom |\
|
||||
egrep "^[0-9]+" | sed 's@^.*vif/\([0-9]*\)/\([0-9]*\).*$@vif\1.\2@')
|
||||
fi
|
||||
name=$( echo $dom | tr .- __ )
|
||||
#awk -v name="$name" -v interface="$dev" -F'[: \t]+' \
|
||||
#'{ sub(/^ */,""); if ($1 == interface) \
|
||||
#print name"DOWN.value "$2"\n"name"UP.value "$10; }' /proc/net/dev
|
||||
awk -v name="$name" -v interface="$dev" \
|
||||
'BEGIN { gsub(/\./, "\\.", interface) } \
|
||||
$1 ~ "^" interface ":" {
|
||||
split($0, a, /: */); $0 = a[2]; \
|
||||
print name"Down.value " $1 "\n"name"Up.value " $9 \
|
||||
}' \
|
||||
/proc/net/dev
|
||||
done
|
||||
|
115
plugins/virtualization/xen_vbd
Executable file
115
plugins/virtualization/xen_vbd
Executable file
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# 2007-06-01 Zoltan HERPAI <wigyori@uid0.hu>
|
||||
#
|
||||
# Credits goes for:
|
||||
# Adam Crews for his xen_cpu plugin
|
||||
# Mario Manno for his xen_traffic_all plugin
|
||||
#
|
||||
# Script to monitor the I/O usage of Xen domains
|
||||
# Version 0.1
|
||||
#
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
# Location of xm tools
|
||||
$XM = '/usr/sbin/xm';
|
||||
$XMTOP = '/usr/sbin/xentop';
|
||||
|
||||
# ah, parameters coming in
|
||||
if ( defined($ARGV[0]))
|
||||
{
|
||||
if ($ARGV[0] eq 'config') { $arg = 'config'; }
|
||||
if ($ARGV[0] eq 'autoconf') { $arg = 'autoconf'; }
|
||||
|
||||
if ( $arg eq 'autoconf' )
|
||||
{
|
||||
if ( -e $XM && -e $XMTOP )
|
||||
{
|
||||
print "yes\n";
|
||||
exit 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
print "no ($XM and/or $XMTOP not found\n";
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $arg eq 'config' )
|
||||
{
|
||||
%cnf = (
|
||||
'graph_title' => 'Xen Domain I/O usage',
|
||||
'graph_args' => '--base 1024 -l 0',
|
||||
'graph_vlabel' => 'read (-), write (+)',
|
||||
'graph_category' => 'xen',
|
||||
'graph_info' => 'Display the I/O operations for each domain',
|
||||
);
|
||||
|
||||
@domains = `$XM list`;
|
||||
shift(@domains); # we don't need the header line
|
||||
|
||||
foreach $domain ( @domains )
|
||||
{
|
||||
($dom, undef) = split(/\s/, $domain);
|
||||
$dom =~ s/[-.]/_/g;
|
||||
|
||||
$cnf{ $dom.'RD' . '.label' } = 'read';
|
||||
$cnf{ $dom.'RD' . '.type' } = 'COUNTER';
|
||||
$cnf{ $dom.'RD' . '.graph' } = 'no';
|
||||
$cnf{ $dom.'RD' . '.cdef' } = $dom.'RD,8,*';
|
||||
|
||||
$cnf{ $dom.'WR' . '.label' } = $dom;
|
||||
$cnf{ $dom.'WR' . '.type' } = 'COUNTER';
|
||||
$cnf{ $dom.'WR' . '.negative' } = $dom.'RD';
|
||||
$cnf{ $dom.'WR' . '.cdef' } = $dom.'WR,8,*';
|
||||
|
||||
if ( "$cnt" == "0" )
|
||||
{
|
||||
$cnf { "$dom" . '.draw' } = 'AREA';
|
||||
}
|
||||
$cnt++;
|
||||
}
|
||||
|
||||
foreach $key ( sort(keys(%cnf)) )
|
||||
{
|
||||
print "$key $cnf{$key}\n";
|
||||
}
|
||||
exit 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# No args, get rolling
|
||||
{
|
||||
local $/ = undef;
|
||||
@chunks = split(/^xentop - .*$/m, `$XMTOP -b -i1`);
|
||||
}
|
||||
|
||||
@stats = split (/\n/, pop(@chunks));
|
||||
|
||||
shift(@stats);
|
||||
shift(@stats);
|
||||
shift(@stats);
|
||||
shift(@stats);
|
||||
|
||||
foreach $domain (@stats)
|
||||
{
|
||||
$domain =~ s/^\s+//;
|
||||
@tmp = split(/\s+/, $domain);
|
||||
|
||||
$domname = $tmp[0];
|
||||
$domname =~ s/[-.]/_/g;
|
||||
$vbdrd = $tmp[14];
|
||||
$vbdwr = $tmp[15];
|
||||
|
||||
$vals{$domname."RD"}{'value'} = $vbdrd;
|
||||
$vals{$domname."WR"}{'value'} = $vbdwr;
|
||||
}
|
||||
|
||||
foreach $key ( sort(keys(%vals)) )
|
||||
{
|
||||
print "$key.value " . ($vals{$key}{'value'}) . "\n";
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue