root / plugins / sensors / esxi__sensors @ 7da1b039
Historique | Voir | Annoter | Télécharger (4,75 ko)
| 1 | 5332dc60 | Phil! Gold | #!/usr/bin/env python |
|---|---|---|---|
| 2 | # coding=iso-8859-1 |
||
| 3 | |||
| 4 | """ |
||
| 5 | =head1 NAME |
||
| 6 | |||
| 7 | esxi__sensors - Munin plugin to monitor hardware sensors in a VMware ESXi |
||
| 8 | installation. |
||
| 9 | |||
| 10 | =head1 APPLICABLE SYSTEMS |
||
| 11 | |||
| 12 | VMware ESX and ESXi systems. Might work with other systems that use CIM and |
||
| 13 | CIM_NumericSensors, probably with changes to the namespace. |
||
| 14 | |||
| 15 | The host on which the plugin is run must have the pywbem Python library |
||
| 16 | installed. |
||
| 17 | |||
| 18 | =head1 CONFIGURATION |
||
| 19 | |||
| 20 | The remote host name is taken from the plugin name as the SNMP plugins are; |
||
| 21 | to monitor host 192.168.1.15, symlink the plugin to snmp_192.168.1.15_sensors . |
||
| 22 | |||
| 23 | The username and password for accessing the ESXi system must be set in a config |
||
| 24 | file: |
||
| 25 | |||
| 26 | [esxi_192.168.1.15_*] |
||
| 27 | env.user monitor |
||
| 28 | env.pass passw0rd |
||
| 29 | |||
| 30 | In the event that not all sensor types are desired, the plugin can be limited |
||
| 31 | to a subset of the types available: |
||
| 32 | |||
| 33 | env.sensors 2 3 5 |
||
| 34 | |||
| 35 | Check the sensor_data dictionary at the top of the script to see what sensor |
||
| 36 | types are available. |
||
| 37 | |||
| 38 | =head1 INTERPRETATION |
||
| 39 | |||
| 40 | This is a multigraph plugin that will generate separate graphs for each type |
||
| 41 | of sensor. The names of the sensors are taken from the ESXi host. |
||
| 42 | |||
| 43 | If the host provides error thresholds for the sensor readings, those will be |
||
| 44 | passed along to munin. |
||
| 45 | |||
| 46 | =head1 VERSION |
||
| 47 | |||
| 48 | 1.0 |
||
| 49 | |||
| 50 | =head1 AUTHOR |
||
| 51 | |||
| 52 | Phil Gold <phil_g@pobox.com> |
||
| 53 | |||
| 54 | =head1 LICENSE |
||
| 55 | |||
| 56 | To the extent possible under law, the author(s) have dedicated all copyright and |
||
| 57 | related and neighboring rights to this software to the public domain worldwide |
||
| 58 | under a CC0 waiver. This software is distributed without any warranty. |
||
| 59 | |||
| 60 | http://creativecommons.org/publicdomain/zero/1.0/ |
||
| 61 | |||
| 62 | =cut |
||
| 63 | """ |
||
| 64 | |||
| 65 | import os, sys |
||
| 66 | import re, string |
||
| 67 | import pywbem |
||
| 68 | |||
| 69 | NS = 'root/cimv2' |
||
| 70 | |||
| 71 | sensor_data = {
|
||
| 72 | 2 : {'prefix':'temp', 'title':'Temperatures', 'unit':'?C'},
|
||
| 73 | 3 : {'prefix':'volt', 'title':'Voltages', 'unit':'Volts'},
|
||
| 74 | 4 : {'prefix':'amp', 'title':'Current', 'unit':'Amps'},
|
||
| 75 | 5 : {'prefix':'fan', 'title':'Fans', 'unit':'RPM'}
|
||
| 76 | } |
||
| 77 | |||
| 78 | def munin_id(instance): |
||
| 79 | return sensor_data[instance['SensorType']]['prefix'] + \ |
||
| 80 | re.sub('[^a-zA-Z0-9]', '_', instance['DeviceId'])
|
||
| 81 | |||
| 82 | def inst_val(instance, field): |
||
| 83 | return instance[field] * 10 ** instance['UnitModifier'] |
||
| 84 | |||
| 85 | def munin_warning(instance): |
||
| 86 | if not instance['EnabledThresholds']: |
||
| 87 | return ':' |
||
| 88 | |||
| 89 | result = '' |
||
| 90 | if 0 in instance['EnabledThresholds']: |
||
| 91 | result += str(inst_val(instance, 'LowerThresholdNonCritical')) |
||
| 92 | result += ':' |
||
| 93 | if 1 in instance['EnabledThresholds']: |
||
| 94 | result += str(inst_val(instance, 'UpperThresholdNonCritical')) |
||
| 95 | return result |
||
| 96 | |||
| 97 | def munin_critical(instance): |
||
| 98 | if not instance['EnabledThresholds']: |
||
| 99 | return ':' |
||
| 100 | |||
| 101 | result = '' |
||
| 102 | if 2 in instance['EnabledThresholds']: |
||
| 103 | result += str(inst_val(instance, 'LowerThresholdCritical')) |
||
| 104 | elif 4 in instance['EnabledThresholds']: |
||
| 105 | result += str(inst_val(instance, 'LowerThresholdFatal')) |
||
| 106 | result += ':' |
||
| 107 | if 3 in instance['EnabledThresholds']: |
||
| 108 | result += str(inst_val(instance, 'UpperThresholdCritical')) |
||
| 109 | elif 5 in instance['EnabledThresholds']: |
||
| 110 | result += str(inst_val(instance, 'UpperThresholdFatal')) |
||
| 111 | return result |
||
| 112 | |||
| 113 | def print_sensors(sensor_type, instances, config): |
||
| 114 | print 'multigraph esxi_' + sensor_data[sensor_type]['prefix'] + 's' |
||
| 115 | |||
| 116 | if config: |
||
| 117 | print "graph_title ESXi " + sensor_data[sensor_type]['title'] |
||
| 118 | print "graph_args --base 1000 -l 0" |
||
| 119 | print "graph_vlabel " + sensor_data[sensor_type]['unit'] |
||
| 120 | print "graph_category sensors" |
||
| 121 | for i in instances: |
||
| 122 | if i['SensorType'] == sensor_type: |
||
| 123 | print '{0}.label {1}'.format(munin_id(i), i['Caption'])
|
||
| 124 | print '{0}.max {1}'.format(munin_id(i), inst_val(i, 'MaxReadable'))
|
||
| 125 | print '{0}.min {1}'.format(munin_id(i), inst_val(i, 'MinReadable'))
|
||
| 126 | if munin_warning(i) != ':': |
||
| 127 | print '{0}.warning {1}'.format(munin_id(i), munin_warning(i))
|
||
| 128 | if munin_critical(i) != ':': |
||
| 129 | print '{0}.critical {1}'.format(munin_id(i), munin_critical(i))
|
||
| 130 | |||
| 131 | print '' |
||
| 132 | return |
||
| 133 | |||
| 134 | for i in instances: |
||
| 135 | if i['SensorType'] == sensor_type: |
||
| 136 | print '{0}.value {1}'.format(munin_id(i), inst_val(i, 'CurrentReading'))
|
||
| 137 | print '' |
||
| 138 | |||
| 139 | plugin_name = list(os.path.split(sys.argv[0]))[1] |
||
| 140 | host = plugin_name[string.index(plugin_name, '_')+1:string.rindex(plugin_name, '_')] |
||
| 141 | if host == '': |
||
| 142 | sys.stderr.write("No hostname found.\n")
|
||
| 143 | exit(1) |
||
| 144 | try: |
||
| 145 | username = os.environ['user'] |
||
| 146 | password = os.environ['pass'] |
||
| 147 | except KeyError: |
||
| 148 | sys.stderr.write("Username and password must be specified.\n")
|
||
| 149 | exit(1) |
||
| 150 | |||
| 151 | try: |
||
| 152 | sensors = map(int, re.split(',? +', os.environ['sensors']))
|
||
| 153 | except: |
||
| 154 | sensors = [2, 3, 4, 5] |
||
| 155 | |||
| 156 | config = len(sys.argv) > 1 and sys.argv[1] == 'config' |
||
| 157 | |||
| 158 | wbemclient = pywbem.WBEMConnection('https://' + host, (username, password), NS)
|
||
| 159 | insts = sorted(wbemclient.EnumerateInstances('CIM_NumericSensor'))
|
||
| 160 | |||
| 161 | print 'host_name ' + host |
||
| 162 | for sensor_type in sensors: |
||
| 163 | print_sensors(sensor_type, insts, config) |
