root / plugins / vmware / esxi__sensors @ 17f78427
Historique | Voir | Annoter | Télécharger (4,98 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 | 6201fbd9 | Diego Elio Pettenò | to monitor host 192.168.1.15, symlink the plugin to esxi_192.168.1.15_sensors . |
| 22 | 5332dc60 | Phil! Gold | |
| 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 | 5e6330c6 | Phil! Gold | To create an account just for monitoring the ESXi, add a user to the host, |
| 31 | make it a member of the 'root' group, and give it the 'No access' role. |
||
| 32 | That will allow the account to connect via WBEM, but not via any of the |
||
| 33 | management tools. |
||
| 34 | |||
| 35 | 5332dc60 | Phil! Gold | In the event that not all sensor types are desired, the plugin can be limited |
| 36 | to a subset of the types available: |
||
| 37 | |||
| 38 | env.sensors 2 3 5 |
||
| 39 | |||
| 40 | Check the sensor_data dictionary at the top of the script to see what sensor |
||
| 41 | types are available. |
||
| 42 | |||
| 43 | =head1 INTERPRETATION |
||
| 44 | |||
| 45 | This is a multigraph plugin that will generate separate graphs for each type |
||
| 46 | of sensor. The names of the sensors are taken from the ESXi host. |
||
| 47 | |||
| 48 | If the host provides error thresholds for the sensor readings, those will be |
||
| 49 | passed along to munin. |
||
| 50 | |||
| 51 | =head1 VERSION |
||
| 52 | |||
| 53 | 1.0 |
||
| 54 | |||
| 55 | =head1 AUTHOR |
||
| 56 | |||
| 57 | Phil Gold <phil_g@pobox.com> |
||
| 58 | |||
| 59 | =head1 LICENSE |
||
| 60 | |||
| 61 | To the extent possible under law, the author(s) have dedicated all copyright and |
||
| 62 | related and neighboring rights to this software to the public domain worldwide |
||
| 63 | 17f78427 | Lars Kruse | under a CC0 waiver. This software is distributed without any warranty. |
| 64 | 5332dc60 | Phil! Gold | |
| 65 | http://creativecommons.org/publicdomain/zero/1.0/ |
||
| 66 | |||
| 67 | =cut |
||
| 68 | """ |
||
| 69 | |||
| 70 | import os, sys |
||
| 71 | import re, string |
||
| 72 | import pywbem |
||
| 73 | |||
| 74 | NS = 'root/cimv2' |
||
| 75 | |||
| 76 | sensor_data = {
|
||
| 77 | 2 : {'prefix':'temp', 'title':'Temperatures', 'unit':'?C'},
|
||
| 78 | 3 : {'prefix':'volt', 'title':'Voltages', 'unit':'Volts'},
|
||
| 79 | 4 : {'prefix':'amp', 'title':'Current', 'unit':'Amps'},
|
||
| 80 | 5 : {'prefix':'fan', 'title':'Fans', 'unit':'RPM'}
|
||
| 81 | } |
||
| 82 | |||
| 83 | def munin_id(instance): |
||
| 84 | return sensor_data[instance['SensorType']]['prefix'] + \ |
||
| 85 | re.sub('[^a-zA-Z0-9]', '_', instance['DeviceId'])
|
||
| 86 | |||
| 87 | def inst_val(instance, field): |
||
| 88 | return instance[field] * 10 ** instance['UnitModifier'] |
||
| 89 | |||
| 90 | def munin_warning(instance): |
||
| 91 | if not instance['EnabledThresholds']: |
||
| 92 | return ':' |
||
| 93 | |||
| 94 | result = '' |
||
| 95 | if 0 in instance['EnabledThresholds']: |
||
| 96 | result += str(inst_val(instance, 'LowerThresholdNonCritical')) |
||
| 97 | result += ':' |
||
| 98 | if 1 in instance['EnabledThresholds']: |
||
| 99 | result += str(inst_val(instance, 'UpperThresholdNonCritical')) |
||
| 100 | return result |
||
| 101 | |||
| 102 | def munin_critical(instance): |
||
| 103 | if not instance['EnabledThresholds']: |
||
| 104 | return ':' |
||
| 105 | |||
| 106 | result = '' |
||
| 107 | if 2 in instance['EnabledThresholds']: |
||
| 108 | result += str(inst_val(instance, 'LowerThresholdCritical')) |
||
| 109 | elif 4 in instance['EnabledThresholds']: |
||
| 110 | result += str(inst_val(instance, 'LowerThresholdFatal')) |
||
| 111 | result += ':' |
||
| 112 | if 3 in instance['EnabledThresholds']: |
||
| 113 | result += str(inst_val(instance, 'UpperThresholdCritical')) |
||
| 114 | elif 5 in instance['EnabledThresholds']: |
||
| 115 | result += str(inst_val(instance, 'UpperThresholdFatal')) |
||
| 116 | return result |
||
| 117 | |||
| 118 | def print_sensors(sensor_type, instances, config): |
||
| 119 | print 'multigraph esxi_' + sensor_data[sensor_type]['prefix'] + 's' |
||
| 120 | |||
| 121 | if config: |
||
| 122 | print "graph_title ESXi " + sensor_data[sensor_type]['title'] |
||
| 123 | print "graph_args --base 1000 -l 0" |
||
| 124 | print "graph_vlabel " + sensor_data[sensor_type]['unit'] |
||
| 125 | print "graph_category sensors" |
||
| 126 | for i in instances: |
||
| 127 | if i['SensorType'] == sensor_type: |
||
| 128 | print '{0}.label {1}'.format(munin_id(i), i['Caption'])
|
||
| 129 | print '{0}.max {1}'.format(munin_id(i), inst_val(i, 'MaxReadable'))
|
||
| 130 | print '{0}.min {1}'.format(munin_id(i), inst_val(i, 'MinReadable'))
|
||
| 131 | if munin_warning(i) != ':': |
||
| 132 | print '{0}.warning {1}'.format(munin_id(i), munin_warning(i))
|
||
| 133 | if munin_critical(i) != ':': |
||
| 134 | print '{0}.critical {1}'.format(munin_id(i), munin_critical(i))
|
||
| 135 | |||
| 136 | print '' |
||
| 137 | return |
||
| 138 | |||
| 139 | for i in instances: |
||
| 140 | if i['SensorType'] == sensor_type: |
||
| 141 | print '{0}.value {1}'.format(munin_id(i), inst_val(i, 'CurrentReading'))
|
||
| 142 | print '' |
||
| 143 | |||
| 144 | plugin_name = list(os.path.split(sys.argv[0]))[1] |
||
| 145 | host = plugin_name[string.index(plugin_name, '_')+1:string.rindex(plugin_name, '_')] |
||
| 146 | if host == '': |
||
| 147 | sys.stderr.write("No hostname found.\n")
|
||
| 148 | exit(1) |
||
| 149 | try: |
||
| 150 | username = os.environ['user'] |
||
| 151 | password = os.environ['pass'] |
||
| 152 | except KeyError: |
||
| 153 | sys.stderr.write("Username and password must be specified.\n")
|
||
| 154 | exit(1) |
||
| 155 | |||
| 156 | try: |
||
| 157 | sensors = map(int, re.split(',? +', os.environ['sensors']))
|
||
| 158 | except: |
||
| 159 | sensors = [2, 3, 4, 5] |
||
| 160 | |||
| 161 | config = len(sys.argv) > 1 and sys.argv[1] == 'config' |
||
| 162 | |||
| 163 | wbemclient = pywbem.WBEMConnection('https://' + host, (username, password), NS)
|
||
| 164 | insts = sorted(wbemclient.EnumerateInstances('CIM_NumericSensor'))
|
||
| 165 | |||
| 166 | print 'host_name ' + host |
||
| 167 | for sensor_type in sensors: |
||
| 168 | print_sensors(sensor_type, insts, config) |
