This is an old revision of the document!
vCenter VM monitoring with Graphite
This was done on a CentOS 6.3 server your mileage may vary on another platform.
You will need to have a version of collectd compiled that has the python plugin enabled. This can be down by downloading the collectd source and building it, making sure to have python-devel package installed.
We don't use the collectd RPM from the EPEL repository as its too old and does not have the graphite_write plugin.
Mathew has a good write on the graphite / collectd compilation and configuration for graphite. http://blog.matthewdfuller.com/2014/06/sending-collectd-metrics-to-graphite.html
Be sure to have this installed before run “./configure”
yum install python-devel
The configuration of /opt/collectd/etc/collectd.conf requires the following entries. Adjust the Username, Vcenter and Password to suit your environment.
<LoadPlugin python> Globals true </LoadPlugin> <Plugin python> # vcenter.py is at /usr/lib/python2.6/site-packages LogTraces true Interactive false Import vcenter <Module vcenter> Username "root" Vcenter "vc.local" Password "vmware" Verbose false </Module> </Plugin>
This works fine in my lab where I have a single vCenter instance.
vcenter.py
#!/usr/bin/python # Collect basic stats about power on VM's on a single vCenter # Brett England - 1-Oct-2014 import collectd from pysphere import VIServer NAME = 'vCenter' # Plugin name # Metric and reporting type as a value METRIC={"name":None, "runtime.powerState":None, "summary.quickStats.overallCpuUsage":"gauge", "summary.quickStats.uptimeSeconds":"gauge", "summary.quickStats.guestMemoryUsage":"bytes", "summary.quickStats.hostMemoryUsage":"bytes", "summary.quickStats.overallCpuUsage":"gauge", "config.hardware.memoryMB":"bytes"} def connect(): server = VIServer() try: server.connect(VCENTER, USERNAME, PASSWORD) except: logger('warn', "failed to connect to %s" % (VCENTER)) return None return server def get_stats(): server = connect() if server is None: return [] ret = [] props = server._retrieve_properties_traversal(property_names=METRIC.keys(), obj_type="VirtualMachine") for obj in props: skip_vm = False d={} for vm_property in obj.PropSet: if vm_property.Name == "runtime.powerState": if vm_property.Val != "poweredOn": skip_vm = True break continue d[vm_property.Name] = vm_property.Val if not skip_vm: ret.append(d) server.disconnect() return ret # callback configuration for module def configure_callback(conf): global VCENTER, USERNAME, PASSWORD, VERBOSE_LOGGING VCENTER = '' USERNAME = '' PASSWORD = '' VERBOSE_LOGGING = False for node in conf.children: if node.key == "Vcenter": VCENTER = node.values[0] elif node.key == "Username": USERNAME = node.values[0] elif node.key == "Password": PASSWORD = node.values[0] elif node.key == "Verbose": VERBOSE_LOGGING = bool(node.values[0]) else: logger('warn', 'Unknown config key: %s' % node.key) # https://collectd.org/wiki/index.php/Naming_schema # The serialized form of the identifier is: # host "/" plugin ["-" plugin instance] "/" type ["-" type instance] # # We want: VCENTER / VMNAME / type... def dispatch_value(vmname, value, key, type): logger('verb','%s: Sending value: %s=%s' % (vmname, key, value)) # This is not intuitive but its what we want. val = collectd.Values() val.host = VCENTER val.plugin = vmname val.type = type val.type_instance = key val.values = [value] val.dispatch() def read_callback(): logger('verb', "beginning read_callback") info = get_stats() if not info: logger('warn', "No data received") return for vm in info: vmname = vm['name'] for key,value in vm.items(): type = METRIC[key] if type: dispatch_value(vmname, value, key, type) # logging function def logger(t, msg): if t == 'err': collectd.error('%s: %s' % (NAME, msg)) elif t == 'warn': collectd.warning('%s: %s' % (NAME, msg)) elif t == 'verb': if VERBOSE_LOGGING: collectd.info('%s: %s' % (NAME, msg)) else: collectd.notice('%s: %s' % (NAME, msg)) # main collectd.register_config(configure_callback) collectd.register_read(read_callback)